2013-04-12 45 views
10

我在使用is時曾依賴於彼此相等的方法。事實證明情況並非如此:爲什麼方法沒有引用平等?

>>> class What(object): 
    def meth(self): 
     pass 

>>> What.meth is What.meth 
False 
>>> inst = What() 
>>> inst.meth is inst.meth 
False 

這是爲什麼?它適用於常規功能:

>>> def func(): 
    pass 

>>> func is func 
True 
+3

這適用於Python 3 btw。 – poke

回答

19

Method對象被創建每次訪問他們時間。功能作爲descriptors,返回一個方法對象時,他們的.__get__方法被稱爲:

>>> What.__dict__['meth'] 
<function meth at 0x10a6f9c80> 
>>> What.__dict__['meth'].__get__(None, What) 
<unbound method What.meth> 
>>> What.__dict__['meth'].__get__(What(), What) 
<bound method What.meth of <__main__.What object at 0x10a6f7b10>> 

使用==平等的測試來代替。

如果兩個方法的.im_self.im_func屬性相同,則兩個方法相同。如果你需要測試的方法代表相同的底層功能,測試其im_func屬性:

>>> What.meth == What.meth  # unbound methods (or functions in Python 3) 
True 
>>> What().meth == What.meth # unbound method and bound method 
False 
>>> What().meth == What().meth # bound methods with *different* instances 
False 
>>> What().meth.im_func == What().meth.im_func # functions 
True 
+0

如果我使用'=='我會得到我正在尋找的身份平等行爲嗎? – Claudiu

+0

我認爲方法相等檢查'.im_self'的身份,而不是相等。 [檢查出來](http://pastebin.com/mSbDWUna) – Claudiu

+0

@Claudiu:是的,對不起,它測試'im_self'是否相同。 –

1

的Martijn是正確的,新的方法是通過.__get__產生的對象,使他們的地址指針不以等號is評價。請注意,使用==將按照Python 2.7中的預期進行評估。然而

Python2.7 
class Test(object): 
    def tmethod(self): 
     pass 

>>> Test.meth is Test.meth 
False 
>>> Test.meth == Test.meth 
True 

>>> t = Test() 
>>> t.meth is t.meth 
False 
>>> t.meth == t.meth 
True 

注意,從一個實例引用的方法不等同於那些從類,因爲從一個實例方法一起進行自我參考引用。

>>> t = Test() 
>>> t.meth is Test.meth 
False 
>>> t.meth == Test.meth 
False 

在Python 3.3 is運營商的方法更經常的行爲一樣==讓您得到預期的行爲,而不是在這個例子中。這是由於__cmp__消失以及Python 3中更清晰的方法對象表示造成的;方法現在有__eq__,並且引用不是動態內建的對象,因此,如果沒有Python 2期望,行爲可能會如預期的那樣。

Python3.3 
>>> Test.meth is Test.meth 
True 
>>> Test.meth == Test.meth 
True 
>>> Test.meth.__eq__(Test.meth) 
True 
+0

您的分析已關閉。您在Python 3中觀察到的更改與「is」無關;它們是由於Python 3中未綁定方法對象的消失所致。「Test.meth」現在只是您定義的原始函數對象,而不是即時創建的未綁定方法對象。 – user2357112

+0

啊,是的,我添加了一些澄清的細節,包括未綁定的對象問題。 – Pyrce

相關問題