2013-04-12 21 views
10

is kullanırken, birbirine eşit olan yöntemlere güvenmekte olduğum bir hata oluştu. Durum böyle değil: Bu durum neden böyle? Düzenli fonksiyonlar için çalışır:Neden yöntemler referans eşitliğine sahip değil?

>>> def func(): 
    pass 

>>> func is func 
True 
+3

Bu, Python 3 btw içinde çalışır. – poke

cevap

19

Yöntem nesneleri, bunlara her eriştiğinizde oluşturulur. Onların .__get__ yöntemi çağrıldığında Fonksiyonlar bir yöntem nesnesi döndüren descriptors olarak hareket:

>>> 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>> 

Kullanım == eşitlik test yerine.

.im_self ve .im_func öznitelikleri aynıysa, iki yöntem eşittir. Eğer yöntemler aynı temel işlevi temsil ettiğini test etmek gerekirse, onların im_func özelliklerini test etmek:

>>> 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

'==' kullanırsam, aradığım kimlik eşitliği davranışını alır mıyım? – Claudiu

+0

Bence yöntem eşitliği, eşitliği değil, “.im_self” kimliğini kontrol eder. [check it out] (http://pastebin.com/mSbDWUna) – Claudiu

+0

@Claudiu: Evet, üzgünüm, im_self'in özdeş olup olmadığını test eder. –

1

Martijn yeni yöntemler böylece onların adres işaretçileri bir ile denk değildir .__get__ tarafından üretilen nesnelerdir bu doğru is değerlendirme. =='u kullanmanın Python 2.7'de belirtilen şekilde değerlendirileceğini unutmayın. örneğinden başvurulan yöntem de örneğinden yöntemi ile birlikte taşınan bir dizi kendinden referans sınıfından referans ile eşit olmadığı, ancak

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 

not edin. Python 3.3 yöntemleri için is operatör olarak

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

daha sık bu yüzden bu örnekte yerine beklenen davranışı elde == aynı şekilde davranır. Bu, hem __cmp__ kaybolan hem de Python 3'te daha temiz bir metod nesnesi temsilinden kaynaklanır; yöntemleri şimdi __eq__ var ve referanslar anında-yerleşik nesneler değildir, bu yüzden davranış, Python 2 beklentileri olmadan beklenebilir.

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

Analiziniz kapalı. Python 3'te gözlemlediğiniz değişiklikler 'is' ile ilgili değildir; bunlar, Python 3'teki ilişkisiz yöntem nesnelerinin kaybolmasından kaynaklanır. 'Test.meth', artık, yalnızca, oluşturulan bir ilişkisiz nesne nesnesinin yerine tanımladığınız ham işlev nesnesidir. – user2357112

+0

Ahh evet, ilişkisiz nesne sorununu dahil etmek için bazı açıklayıcı ayrıntılar ekledim. – Pyrce