2013-04-12 17 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

相关问题