TL; DR 如何使用@classmethod
或具有相同效果的内容确定功能是否已定义?
我的问题
为了实现类装饰器,我想检查方法是否将类作为其第一个参数,例如通过
实现@classmethod
def function(cls, ...):
如果@staticmethod
是静态的,我找到了通过types
模块检查isinstance(foo, types.UnboundMethodType)
的解决方案False
为foo
,请参阅{{3} }),但没有找到关于如何@classmethod
上下文
我想要做的是
def class_decorator(cls):
for member in cls.__dict__:
if (isclassmethod(getattr(cls, member))):
# do something with the method
setattr(cls, member, modified_method)
return cls
我不知道如何实现我在此示例中所谓的isclassmethod
答案 0 :(得分:18)
对于Python 2,您需要测试对象是否为方法,和如果__self__
指向该类(对于常规方法,它将是None
从班级中检索时):
>>> class Foo(object):
... @classmethod
... def bar(cls):
... pass
... def baz(self):
... pass
...
>>> Foo.baz
<unbound method Foo.baz>
>>> Foo.baz.__self__
>>> Foo.baz.__self__ is None
True
>>> Foo.bar.__self__
<class '__main__.Foo'>
>>> Foo.bar.__self__ is Foo
True
在Python 3中,常规方法显示为函数(未绑定的方法已被废除)。
将此与inspect.ismethod()
结合使用,以便在Python 2和3中检测类方法的故障安全方法:
import inspect
if inspect.ismethod(cls.method) and cls.method.__self__ is cls:
# class method
在Python 2.6中添加了method.__self__
属性以与Python 3保持一致。在Python 2.6和2.7中,它是别名method.im_self
。
答案 1 :(得分:5)
您应该使用inspect.ismethod。它的工作原理是因为classmethod将函数绑定到类对象。请参阅以下代码:
>>> class Foo:
... @classmethod
... def bar():
... pass
... def baz():
... pass
...
>>> Foo.bar
<bound method type.bar of <class '__main__.Foo'>>
>>> Foo.baz
<function Foo.baz at 0x0000000002CCC1E0>
>>> type(Foo.bar)
<class 'method'>
>>> type(Foo.baz)
<class 'function'>
>>> import inspect
>>> inspect.ismethod(Foo.bar)
True
>>> inspect.ismethod(Foo.baz)
False
答案 2 :(得分:2)
class Foo(object):
@classmethod
def baaz(cls):
print "baaz"
isinstance(Foo.__dict__["baaz"], classmethod)
答案 3 :(得分:1)
没有一个答案解决从类的实例中识别方法是否用类方法修饰的问题。以下代码探讨了实例的类字典,以区分类方法和其他方法。
Attach()
这将同时适用于Python 2和3。
答案 4 :(得分:0)
这对我有用:
def is_classmethod(method):
"""
Is method a classmethod?
"""
return isinstance(getattr(method, '__self__', None), type)
它基本上测试method.__self__
是否存在并且是一个类,如Martijn的答案,但不需要访问类本身。