2009-11-04 25 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