¿Cómo puedo inferir la clase a la que pertenece un @staticmethod?
-
09-09-2019 - |
Pregunta
Estoy tratando de poner en práctica la función infer_class
que, dado un método, se da cuenta de la clase a la que pertenece el método.
Hasta ahora tengo algo como esto:
import inspect
def infer_class(f):
if inspect.ismethod(f):
return f.im_self if f.im_class == type else f.im_class
# elif ... what about staticmethod-s?
else:
raise TypeError("Can't infer the class of %r" % f)
No funciona para @ métodoestático-s porque no era capaz de llegar a una forma de lograrlo.
¿Alguna sugerencia?
Aquí está infer_class
en acción:
>>> class Wolf(object):
... @classmethod
... def huff(cls, a, b, c):
... pass
... def snarl(self):
... pass
... @staticmethod
... def puff(k,l, m):
... pass
...
>>> print infer_class(Wolf.huff)
<class '__main__.Wolf'>
>>> print infer_class(Wolf().huff)
<class '__main__.Wolf'>
>>> print infer_class(Wolf.snarl)
<class '__main__.Wolf'>
>>> print infer_class(Wolf().snarl)
<class '__main__.Wolf'>
>>> print infer_class(Wolf.puff)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in infer_class
TypeError: Can't infer the class of <function puff at ...>
Solución
Esto se debe a staticmethods realmente no son métodos. El descriptor de métodoestático devuelve la función original como es. No hay manera de conseguir la clase a través de la cual se accedió a la función. Pero no hay ninguna razón real para utilizar staticmethods para los métodos de todos modos, siempre use classmethods.
El único uso que he encontrado para staticmethods es almacenar objetos funcionan como atributos de clase y no tener los convierten en los métodos.
Otros consejos
tengo problemas con lo que a mí mismo que en realidad recomiendan esto, pero parece que no funciona para casos sencillos, al menos:
import inspect
def crack_staticmethod(sm):
"""
Returns (class, attribute name) for `sm` if `sm` is a
@staticmethod.
"""
mod = inspect.getmodule(sm)
for classname in dir(mod):
cls = getattr(mod, classname, None)
if cls is not None:
try:
ca = inspect.classify_class_attrs(cls)
for attribute in ca:
o = attribute.object
if isinstance(o, staticmethod) and getattr(cls, sm.__name__) == sm:
return (cls, sm.__name__)
except AttributeError:
pass