为什么方法没有引用相等? [英] Why don't methods have reference equality?
问题描述
我遇到一个错误,即使用is
时我依赖于彼此相等的方法.事实并非如此:
>>> class What:
... def meth(self):
... pass
>>> What.meth is What.meth
True
>>> inst = What()
>>> inst.meth is inst.meth
False
为什么会这样?它适用于常规功能:
>>> def func(): pass
>>> func is func
True
每次访问它们时都会创建方法对象.函数充当描述符,当它们的.__get__
方法称为:
>>> What.__dict__['meth']
<function What.meth at 0x10a6f9c80>
>>> What.__dict__['meth'].__get__(What(), What)
<bound method What.meth of <__main__.What object at 0x10a6f7b10>>
如果您使用的是Python 3.8或更高版本,则可以改用==
相等性测试.在Python 3.8和更高版本上,如果两个方法的.__self__
和.__func__
属性是相同的对象(因此,如果它们包装相同的函数并绑定到相同的实例,并且都用is
测试),则这两个方法是相等的.>
在3.8之前,根据方法的实现方式,方法==
的行为是不一致的-Python方法和两种C方法类型之一比较__self__
是否相等,而不是标识,而另一种C方法类型比较
如果需要测试这些方法表示相同的基础函数,请测试其__func__
属性:
>>> What.meth == What.meth # functions (or unbound methods in Python 2)
True
>>> What().meth == What.meth # bound method and function
False
>>> What().meth == What().meth # bound methods with *different* instances
False
>>> What().meth.__func__ == What().meth.__func__ # functions
True
I had a bug where I was relying on methods being equal to each other when using is
. It turns out that's not the case:
>>> class What:
... def meth(self):
... pass
>>> What.meth is What.meth
True
>>> inst = What()
>>> inst.meth is inst.meth
False
Why is that the case? It works for regular functions:
>>> def func(): pass
>>> func is func
True
Method objects are created each time you access them. Functions act as descriptors, returning a method object when their .__get__
method is called:
>>> What.__dict__['meth']
<function What.meth at 0x10a6f9c80>
>>> What.__dict__['meth'].__get__(What(), What)
<bound method What.meth of <__main__.What object at 0x10a6f7b10>>
If you're on Python 3.8 or later, you can use ==
equality testing instead. On Python 3.8 and later, two methods are equal if their .__self__
and .__func__
attributes are identical objects (so if they wrap the same function, and are bound to the same instance, both tested with is
).
Before 3.8, method ==
behaviour is inconsistent based on how the method was implemented - Python methods and one of the two C method types compare __self__
for equality instead of identity, while the other C method type compares __self__
by identity. See Python issue 1617161.
If you need to test that the methods represent the same underlying function, test their __func__
attributes:
>>> What.meth == What.meth # functions (or unbound methods in Python 2)
True
>>> What().meth == What.meth # bound method and function
False
>>> What().meth == What().meth # bound methods with *different* instances
False
>>> What().meth.__func__ == What().meth.__func__ # functions
True
这篇关于为什么方法没有引用相等?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!