根据文档(Python 3.8中):
默认情况下,object
使用is
实现__eq__()
,在比较结果为假的情况下返回NotImplemented
:True if x is y else NotImplemented
.
并且:
运算符符号和方法名称之间的对应关系如下:[...] x==y
调用x.__eq__(y)
所以我希望
==
等同于__eq__()
,并且
1.自定义类没有显式定义__eq__
,当使用==
比较类的两个不同示例时返回NotImplemented
。但在下面的示例中,==
比较返回False
,而__eq__()
返回NotImplemented
:
class Dummy():
def __init__(self, a):
self.a = a
d1 = Dummy(3)
d2 = Dummy(3)
d1 == d2 # False
d1.__eq__(d2) # NotImplemented
为什么?
3条答案
按热度按时间ej83mcc01#
原因是如果操作的 * 一 * 方不能(或不愿意)提供答案,另一方就有发言权来处理这个比较,一个常见的例子是float/int比较:
对于
int
和float
,它们都不是对方的子类,并且int
对于它是否等于某个float
没有任何表示,相等性比较由float
类型处理。如果您为左侧和右侧设置不同的类型,并在钩子中添加一些调试输出,则会更容易理解:
演示:
左边的
type(d1).__eq__
通过返回NotImplemented
选择退出,这给了右边一个“第二次机会”来处理这个操作,如果左边返回的是False
而不是NotImplemented
,Python根本不会尝试右边,d1 == d2
的结果将是False
,如果两边都返回NotImplemented
,就像在Dummy
示例中一样,除非对象完全相同(即相同的示例),否则它们将被视为不相等。uxh89sit2#
这里的文档不是很清楚,肯定需要改进。
当一个Python的“内部”方法返回
NotImplemented
时,它通常意味着“找一些其他的方法来做这个操作”。当它找不到“一些其他的方法......”时,Python会做什么取决于操作,并且没有像它应该做的那样被很好地记录下来。因此,例如,如果x.__lt__(y)
返回NotImplemented
,Python可能会尝试调用y.__gt__(x)
。在
==
的情况下,如果x.__eq__(y)
和y.__eq__(x)
都返回NotImplemented
,Python返回False
,这应该被更好地记录下来。3pvhb19x3#
如果左操作数未实现
.__eq__()
,则==
测试右操作数.__eq__()
如果左操作数
.__eq__()
未实现.__eq__()
,则由==
测试右操作数.__eq__()
;如果两者都返回NotImplemented
,则==
返回false。您可以通过更改类来查看此行为:
这是操作符的常见行为,Python测试左操作数是否有实现,如果没有,Python调用右操作数的相同或反射(例如,如果
x.__lt__(y)
没有实现,则调用y.__gt__(x)
)操作符。**!**右前左例外:
如果操作数属于不同类型,并且右操作数的类型是左操作数类型的直接或间接子类,则右操作数的反射方法具有优先级,否则左操作数的方法具有优先级。