從「用戶」的角度來看,Python中的類方法是一種接收其類作爲其第一個參數的方法 - 與接收該類的實例作爲其第一個參數的「普通」方法不同 - 叫做self
。
如果您從類而不是從該類的實例中檢索「普通」方法,則會得到一個「未綁定方法」 - 即一個對象,該對象是函數的包裝器,但不會自動添加無論是類本身,還是任何實例作爲調用時的第一個參數。因此,如果您要調用「未綁定方法」,則必須手動傳遞其類的實例作爲其第一個參數。
如果手動調用類方法,而另一方面,類填充爲你的第一個參數:
>>> class A(object):
... def b(self):
... pass
... @classmethod
... def c(cls):
... pass
...
>>> A.b
<unbound method A.b>
>>> A.c
<bound method type.c of <class '__main__.A'>>
>>> A.c()
>>> A.b()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method b() must be called with A instance as first argument (got nothing instead)
>>>
引擎蓋下發生的事情或多或少這樣的 - 與「新風格類「:
當定義一個類體時,這些方法只是普通函數 - 當類體結束時,Python調用類的元類(通常是內建的type
) - 並將其作爲參數傳遞給它名稱,基類和類體字典。這個調用產生一個類 - 在Python中,它是一個類,因爲所有東西都是一個對象。
現在,Python有一些漂亮的方式來定製屬性訪問 - 所謂的「描述符」。描述符是定義名爲__get__
(或__set__
或__del__
,但我們不在乎這些方法)的方法的任何對象。當在Python中訪問類或對象的屬性時,將返回由該屬性引用的對象 - 除非它是類屬性,並且對象是描述符。在這種情況下,Python不是返回對象本身,而是調用該對象的__get__
方法,並返回其結果。例如,內置的property
僅適用於實現__set__
,__get__
和__del__
的類。
現在,檢索屬性時發生的情況是,其正文中的任何函數(或類方法或未綁定的方法,如數據模型所示)都有一個__get__
方法,該方法使其成爲描述符。基本上,一個描述符在每個屬性訪問中檢索名爲函數的對象,如函數體上定義的那樣,創建一個圍繞該函數的新對象 - 一個被調用的對象將自動填充第一個參數 - 這是說,一個method
。
例:
>>> class B(object):
... def c(self):
... pass
... print c
...
<function c at 0x1927398>
>>> print B.c
<unbound method B.c>
>>> b = B()
>>> b.c
<bound method B.c of <__main__.B object at 0x1930a10>
如果你要檢索的功能對象,無需轉換的方法對象,你可以通過類的__dict__
屬性,這不會觸發描述這樣做的:
>>> B.__dict__["c"]
<function c at 0x1927398>
>>> B.__dict__["c"].__get__
<method-wrapper '__get__' of function object at 0x1927398>
>>> B.__dict__["c"].__get__(b, B)
<bound method B.c of <__main__.B object at 0x1930a10>>
>>> B.__dict__["c"].__get__(None, B)
<unbound method B.c>
對於「類方法」,這些只是不同類型的對象,它們是用內置的明確裝飾的classmethod
- 它調用__get__
時返回的對象是原始包裝nal函數將填入cls
作爲第一個參數。
所以綁定/未綁定的用戶定義的方法是「Method of a instance」,而classmethod是「Method of a class,right? – Determinant 2012-02-01 06:41:18
換句話說,如果您嘗試直接從類中調用unbound方法,您將得到異常,並且爲了調用這個方法,你必須首先創建對象,然後調用方法「from」對象。如果你想從類直接調用方法,你可以使用裝飾器@staticmethod – Denis 2012-02-01 06:55:51
@Denis那麼,當獲得屬性是一種方法裝飾用'@ classmethod',我們可以說它是類的綁定方法嗎? – Determinant 2012-02-01 07:23:50