我在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)
。
有人可以解释一下吗?
答案 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
对象,绑定时,只返回原始函数。