检查函数是否使用@classmethod

时间:2013-10-07 14:40:56

标签: python decorator class-method python-decorators

TL; DR 如何使用@classmethod或具有相同效果的内容确定功能是否已定义?


我的问题

为了实现类装饰器,我想检查方法是否将类作为其第一个参数,例如通过

实现
@classmethod
def function(cls, ...):

如果@staticmethod是静态的,我找到了通过types模块检查isinstance(foo, types.UnboundMethodType)的解决方案Falsefoo,请参阅{{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

5 个答案:

答案 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的答案,但不需要访问类本身。