2014-06-23 60 views
47

爲什麼第一個結果False,應該不是True運營商的非常奇怪的行爲是用方法

>>> from collections import OrderedDict 
>>> OrderedDict.__repr__ is OrderedDict.__repr__ 
False 
>>> dict.__repr__ is dict.__repr__ 
True 
+1

Python 3.3返回True – HashSplat

+0

它是Python 2.7。 – Chameleon

+1

@JustinEngel:這是因爲Python 3消除了未綁定的方法,所有的方法都是綁定的。在Python 3中嘗試'OrderedDict().__ repr__是OrderedDict().__ repr__',你會看到相同的行爲。 –

回答

56

對於用戶定義的函數,在Python 2 未結合結合按需創建方法,通過descriptor protocol; OrderedDict.__repr__就是這樣的一個方法對象,因爲被包裝的函數實現爲pure-Python function

描述符協議將在支持它的對象上調用__get__ method,因此只要您嘗試訪問OrderedDict.__repr__,就會調用__repr__.__get__();對於類None(無實例)並且類對象本身被傳入。因爲每次調用函數__get__方法時,您會得到一個新方法對象,因此is失敗。它不是同一個方法對象。

dict.__repr__不是一個自定義的Python函數,而是一個C函數,它的__get__描述符方法essentially just returns self when accessed on the class。訪問屬性爲您提供了相同的對象每一次,所以is作品:

>>> dict.__repr__.__get__(None, dict) is dict.__repr__ # None means no instance 
True 

方法有__func__屬性引用包裝的函數,用它來測試身份:

>>> OrderedDict.__repr__ 
<unbound method OrderedDict.__repr__> 
>>> OrderedDict.__repr__.__func__ 
<function __repr__ at 0x102c2f1b8> 
>>> OrderedDict.__repr__.__func__.__get__(None, OrderedDict) 
<unbound method OrderedDict.__repr__> 
>>> OrderedDict.__repr__.__func__ is OrderedDict.__repr__.__func__ 
True 

Python 3裏遠與未綁定方法,function.__get__(None, classobj)返回函數對象本身(因此它的行爲與dict.__repr__一樣)。但是您會看到與從實例檢索到的方法綁定的方法具有相同的行爲。

+1

作爲一個簡單的測試來證明你自己,用''__repr__''方法創建一個類爲''' __repr__ = lambda:x'',並且''is''測試將失敗。實際上,重寫''__repr__''通常會導致''is''失敗。 – aruisdante

+0

而且,在一般情況下,NO類的純python未綁定方法與''is''與''True''進行比較。 – aruisdante

+0

@aruisdante:好的,你可以創建(多於一個)方法對象的引用,然後你仍然可以使用'is'。但是,從類中檢索方法將爲您提供一個新對象,因爲函數'__get__'方法會生成一個新對象。 –

1

這兩個OrderedDict.__repr__不綁定到同一個對象。如果您嘗試:

OrderedDict.__repr__ == OrderedDict.__repr__ 

您會看到它們具有相同的值。