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 ...>
¿Fue útil?

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top