python classmethods不能从类中调用.__ dict__

时间:2017-01-17 11:54:45

标签: python python-2.7 oop class-method

我在python中学习classmethods的概念。

class A():
    n=0
    # object method
    def func_o(self):
        self.n += 1
        print self.n

    # well, class method
    @classmethod
    def func_c(cls):
        cls.n += 1
        print cls.n

在检查班级的callable()属性时,我遇到了这个特殊的输出:

>>> [(k, callable(v)) for k,v in A.__dict__.items()]
[('__module__', False), ('__doc__', False), ('func_o', True), ('func_c', False), ('n', False)] 

('func_o', True)即使已经检查了班级__dict__,出于某种原因同样('func_c', False)

有人可以解释一下吗?

1 个答案:

答案 0 :(得分:6)

classmethod对象不是函数对象,不是。它并不意味着可以赎回。

classmethod个对象是描述符;描述符有助于将对象绑定到特定实例或类。函数和属性也是描述符; binding分别生成方法或属性值。请参阅Python Descriptor How To。如果要在类上访问classmethod描述符,则会触发一个classmethod.__get__(None, cls)调用,该调用会生成一个绑定方法(在调用时,调用原始函数,并将类对象作为第一个传入参数)。

当您通过__dict__属性访问所有类属性时,您绕过了描述符协议,因此您可以自己获取原始描述符对象。

访问类上的对象(从而触发将类方法绑定到类对象的descriptor.__get__(None, cls)调用),手动绑定或显式测试classmethod个对象:

>>> A.__dict__['func_c']
<classmethod object at 0x1018e6cc8>
>>> A.__dict__['func_c'].__get__(None, A)  # explicitly bind to a class
<bound method classobj.func_c of <class __main__.A at 0x101c52328>>
>>> callable(A.__dict__['func_c'].__get__(None, A))
True
>>> A.func_c    # trigger the protocol and bind to a class
<bound method classobj.func_c of <class __main__.A at 0x101c52328>>

您还可以使用classmethod属性访问__func__对象包装的原始函数:

>>> A.__dict__['func_c'].__func__
<function func_c at 0x101c59668>

当然,它本身也可以调用。

请注意,这一切也适用于staticmethod个对象;一个staticmethod对象,绑定时,只返回原始函数。