2012-02-01 86 views
3

數據模型基準的,作家花大力氣解釋如何用戶定義的方法創建和操作:(參見http://docs.python.org/reference/datamodel.html#the-standard-type-hierarchy或許經由那個類的一個IN-姿態)得到一個類(的屬性 當滾下)可被創建Python的數據模型文件:將未綁定用戶定義的方法的對象和類方法對象

用戶定義的方法的對象,如果 屬性是一個用戶定義的功能對象,未綁定的用戶定義的方法對象 或一個類方法對象。如果屬性爲 用戶定義的方法對象,則只有在檢索到的類的 類與原始方法對象中存儲的類相同或類派生爲 時,纔會創建新的方法對象;否則, 將原樣使用原始方法對象。

那麼什麼是未綁定的用戶定義的方法對象之間的區別一個類的方法對象

回答

6

從「用戶」的角度來看,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作爲第一個參數。

+0

所以綁定/未綁定的用戶定義的方法是「Method of a instance」,而classmethod是「Method of a class,right? – Determinant 2012-02-01 06:41:18

+0

換句話說,如果您嘗試直接從類中調用unbound方法,您將得到異常,並且爲了調用這個方法,你必須首先創建對象,然後調用方法「from」對象。如果你想從類直接調用方法,你可以使用裝飾器@staticmethod – Denis 2012-02-01 06:55:51

+0

@Denis那麼,當獲得屬性是一種方法裝飾用'@ classmethod',我們可以說它是類的綁定方法嗎? – Determinant 2012-02-01 07:23:50