Domanda

Sto cercando di implementare la funzione infer_class che, dato un metodo, capisce la classe a cui appartiene il metodo.

Finora ho qualcosa di simile:

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)

Non funziona per @ staticmethod-s, perché non ero in grado di trovare un modo per raggiungere questo obiettivo.

Qualche suggerimento?

Ecco infer_class in azione:

>>> 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 ...>
È stato utile?

Soluzione

Questo perché staticmethods in realtà non sono metodi. Il descrittore staticmethod restituisce la funzione originale come è. Non v'è alcun modo per ottenere la classe attraverso il quale si accedeva alla funzione. Ma non c'è una vera ragione per usare staticmethods per i metodi in ogni caso, sempre utilizzare classmethods.

L'unico uso che ho trovato per staticmethods è quello di memorizzare oggetti funzione come attributi di classe e non hanno li trasformano in metodi.

Altri suggerimenti

Ho problemi portando a me stesso di realtà consiglia questo, ma sembra di lavorare per i casi semplici, almeno:

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top