Comment puis-je déduire la classe à laquelle appartient un @staticmethod?
-
09-09-2019 - |
Question
Je suis en train de mettre en œuvre la fonction infer_class
que, étant donné une méthode, figure la classe à laquelle appartient la méthode.
Jusqu'à présent, j'ai quelque chose comme ceci:
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)
Il ne fonctionne pas pour @ staticmethod-s parce que je ne pouvais pas trouver un moyen d'y parvenir.
Toutes les suggestions?
Ici se infer_class
en action:
>>> 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 ...>
La solution
C'est parce que staticmethods ne sont vraiment pas des méthodes. Le descripteur de staticmethod retourne la fonction initiale est. Il n'y a pas moyen d'obtenir la classe via laquelle la fonction a été consulté. Mais il n'y a aucune raison d'utiliser staticmethods pour les méthodes de toute façon, utilisez toujours classmethods.
La seule utilisation que je l'ai trouvé pour staticmethods est de stocker des objets de fonction comme attributs de classe et pas les transformer en méthodes.
Autres conseils
J'ai du mal à me mettre à réellement recommander , mais il ne semble pas fonctionner pour les cas simples, au moins:
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