method - python static variable
El objeto ''classmethod'' no es invocable (6)
Ok así que tengo este código:
class SomeClass:
@classmethod
def func1(cls,arg1):
#---Do Something---
@classmethod
def func2(cls,arg1):
#---Do Something---
# A ''function map'' that has function name as its keys and the above function
# objects as values
func_map={''func1'':func1,''func2'':func2}
@classmethod
def func3(cls,arg1):
# following is a dict(created by reading a config file) that
# contains func names as keys and boolean as values that tells
# the program whether or not to run that function
global funcList
for func in funcList:
if funcList[func]==True:
cls.func_map[func](arg1) #TROUBLING PART!!!
if _name__=''main''
SomeClass.func3(''Argumentus-Primus'')
Cuando ejecuto esto sigo recibiendo el error:
Exception TypeError: "''classmethod'' object is not callable"
No puedo averiguar cuál es el problema con esto y agradecería su ayuda.
Agregue self como un argumento para cada método dentro de la clase.
también
if _name__=''main''
SomeClass.func3(''Argumentus-Primus'')
debería verse así:
if __name__==''__main__'':
SomeClass.func3(''Argumentus-Primus'')
y no debe estar dentro del cuerpo de la clase.
Descubrí algo esta noche que será útil aquí: podemos desenvolver objetos staticmethod
y de classmethod
staticmethod
mágico a través de: getattr(func, ''__func__'')
¿Cómo encontré esta información? Usando PyCharm de JetBrains (no sé sobre otros IDE de Python), vi el código fuente de @staticmethod
y @classmethod
. Ambas clases definen el atributo __func__
.
"El resto se deja como un ejercicio para el lector".
No puede crear referencias a los métodos de clase hasta que la clase haya sido definida. Tendrás que moverlo fuera de la definición de clase. Sin embargo, usar un mapa de funciones global para decidir qué se ejecuta es realmente incómodo. Si describió lo que está tratando de hacer con esto, probablemente podríamos sugerir una mejor solución.
class SomeClass(object):
@classmethod
def func1(cls, arg1):
print("Called func1({})".format(arg1))
@classmethod
def func2(cls, arg1):
print("Call func2({})".format(arg1))
@classmethod
def func3(cls, arg1):
for fnName,do in funcList.iteritems():
if do:
try:
cls.func_map[fnName](arg1)
except KeyError:
print("Don''t know function ''{}''".format(fnName))
# can''t create function map until class has been created
SomeClass.func_map = {
''func1'': SomeClass.func1,
''func2'': SomeClass.func2
}
if __name__==''__main__'':
funcList = {''func1'':True, ''func2'':False}
SomeClass.func3(''Argumentus-Primus'')
Puede que necesite probar un método estático.
@staticmethod
def function():...
Los métodos estáticos no pasan la clase como primer argumento implícito.
Todas las otras respuestas sugieren agregar algún código fuera de la definición de class SomeClass
la class SomeClass
. Puede estar bien en algunos casos, pero en mi caso fue muy inconveniente. Tenía muchas ganas de mantener el func_map
dentro de la clase.
Sugiero el siguiente enfoque. No use una variable de clase, sino un método de clase más:
class SomeClass:
# ...
@classmethod
def get_func_map(cls):
return {''func1'': cls.func1, ''func2'': cls.func2}
@classmethod
def func3(cls, arg1):
# .....
cls.get_func_map()[func_name](arg1)
Por supuesto, debe modificar este código para que no se construya un nuevo diccionario cada vez que llame al método get_func_map
. Es fácil, no lo hice para mantener el ejemplo pequeño y claro.
Probado en Python 3.6
Un método de clase envuelve una función dada con un objeto mágico que de hecho no es llamable. Solo se puede llamar utilizando la sintaxis ClassName.method(args)
.
No recomendaría que lo hagas de esta manera, considera hacer algo como esto en su lugar:
func_list = {
''func1'': True,
''func2'': False
}
class SomeClass(object):
def do_func1(self, arg1):
print("func1", arg1)
def do_func2(self, arg1):
print("func2", arg1)
def run(self, arg1):
for name, enabled in func_list.items():
if enabled:
the_method = getattr(self, ''do_'' + name)
the_method(arg1)
if __name__ == ''__main__'':
sc = SomeClass()
sc.run(''Argumentus-Primus'')