Varios errores en el código que intenta llamar a classmethods

Tengo este codigo

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: "el objeto '' classmethod 'no se puede llamar"

No puedo entender qué es lo que está mal con esto y agradecería su ayuda.

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') 

Descubrí algo esta noche que será útil aquí: podemos desenvolver objetos staticmethod y de classmethod través de: getattr(func, '__func__')

¿Cómo encontré esta información? Al usar 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 rest se deja como ejercicio para el lector”.

Agregue self como un argumento para cada método dentro de la clase.

también

  if _name__='main' SomeClass.func3('Argumentus-Primus') 

debe tener este aspecto:

 if __name__=='__main__': SomeClass.func3('Argumentus-Primus') 

y no debe estar dentro del cuerpo de la clase.

Es posible que deba 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 demás 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 utilice 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

Aquí hay una mala manera de hacerlo:

 def func3(cls,arg1): global funcList for func in funcList: if funcList[func]==True: eval(f'SomeClass.{func}')(arg1) 

Solo funciona si func es el nombre de la función. Dicho esto, no utilice este método, porque está tomando información del usuario. Sería muy fácil inyectar código desagradable en la llamada. Dicho esto, esto funciona.