2009-11-04 72 views
7

我很难理解classmethod对象在Python中的工作方式,特别是在metaclass和__new__中。在我的特殊情况下,我想获得一个classmethod成员的名字,当我遍历__new__给出的membersclassmethod对象如何工作?

对于常规方法,名称只存储在__name__属性中,但对于类方法,显然没有这样的属性。我什至不知道如何调用类方法,因为也没有__call__属性。

有人可以向我解释一个classmethod是如何工作的或指向我的一些文档?谷歌搜索导致我无处。谢谢!

+0

我对“缺少”'__name__'没有深入的了解,但要确保类方法有一个'__call__'包装。 – mjv 2009-11-05 00:29:14

回答

18

A classmethod对象是描述符。你需要了解描述符是如何工作的。

概括地说,描述符是具有方法__get__,它有三个参数的对象:self,一个instanceinstance type

在正常属性查询,如果查到的对象A有一个方法__get__,该方法被调用和它返回的地方被替换为对象A。这就是函数(也是描述符)在对象上调用方法时如何成为绑定方法。

class Foo(object): 
    def bar(self, arg1, arg2): 
     print arg1, arg2 

foo = Foo() 
# this: 
foo.bar(1,2) # prints '1 2' 
# does about the same thing as this: 
Foo.__dict__['bar'].__get__(foo, type(foo))(1,2) # prints '1 2' 

A classmethod对象的工作方式相同。当它被抬起时,它的__get__方法被调用。类方法的__get__丢弃对应于instance(如果有的话)的参数,并且当它在包装的函数上调用__get__时仅传递instance_type

一个说明性的涂鸦:

In [14]: def foo(cls): 
    ....:  print cls 
    ....:  
In [15]: classmethod(foo) 
Out[15]: <classmethod object at 0x756e50> 
In [16]: cm = classmethod(foo) 
In [17]: cm.__get__(None, dict) 
Out[17]: <bound method type.foo of <type 'dict'>> 
In [18]: cm.__get__(None, dict)() 
<type 'dict'> 
In [19]: cm.__get__({}, dict) 
Out[19]: <bound method type.foo of <type 'dict'>> 
In [20]: cm.__get__({}, dict)() 
<type 'dict'> 
In [21]: cm.__get__("Some bogus unused string", dict)() 
<type 'dict'> 

上描述更多信息可以在这里找到(在其他地方): http://users.rcn.com/python/download/Descriptor.htm

为了得到由classmethod包裹函数名的特定任务:

In [29]: cm.__get__(None, dict).im_func.__name__ 
Out[29]: 'foo' 
+0

谢谢,解决了我的问题!因为原则上我知道描述符,所以我觉得现在有点愚蠢。但是我很困惑地看到一个classmethod被封装在一个不可调用的描述符中:-) – nikow 2009-11-05 11:44:38

+0

对不起,我忘了强调我非常感谢你的非常详细的答案,这太棒了。 – nikow 2009-11-05 11:45:51

1

This看起来像它有货。

+0

谢谢,我不知道术语Metamethods,所以这是一个有趣的阅读。但是恐怕没有太多关于类方法对象本身的信息。 – nikow 2009-11-05 00:28:05