为什么方法不具有引用相等性?
- 2025-01-14 08:50:00
- admin 原创
- 107
问题描述:
我遇到了一个 bug,在使用时我依赖于方法彼此相等is
。但事实并非如此:
>>> class What:
... def meth(self):
... pass
>>> What.meth is What.meth # This is False in Python 2
True
>>> inst = What()
>>> inst.meth is inst.meth
False
为什么会这样?它适用于常规函数:
>>> def func(): pass
>>> func is func
True
另请参阅:Python 的属性查找过程如何工作?。
解决方案 1:
每次访问方法对象时都会创建它们。函数充当描述符.__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 方法类型__self__
则按身份进行比较。请参阅Python 问题 1617161。
如果需要测试方法是否代表相同的底层功能,请测试它们的__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
解决方案 2:
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
相关推荐
热门文章
项目管理软件有哪些?
热门标签
云禅道AD