继承list/tuple未重写__eq__时,a==b为何调用b.__eq__?
问题解析:为何
ListVector() == TupleVector()会调用右操作数的__eq__ 核心原因:list.__eq__对非list类型返回NotImplemented
Python运算符重载的规则是:当左操作数的__eq__方法返回NotImplemented时,解释器会尝试调用右操作数的__eq__方法,而非直接判定不相等。
你继承的list.__eq__方法逻辑如下:
- 若比较对象是
list或其子类,逐元素比较并返回布尔值 - 若为其他类型,直接返回
NotImplemented,告知Python“我无法处理该比较,试试对方的方法”
由于ListVector未重写__eq__,执行ListVector() == TupleVector()时:
- 先调用左方的
list.__eq__,传入TupleVector实例作为other - 因
TupleVector继承自tuple而非list,list.__eq__返回NotImplemented - Python转而调用右方的
TupleVector.__eq__,该方法通过zip逐元素比较返回True,导致断言意外成功
验证逻辑
直接测试list.__eq__的返回值即可确认:
lv = ListVector((1,2,3)) tv = TupleVector((1,2,3)) print(list.__eq__(lv, tv)) # 输出: NotImplemented
这也解释了为何会看到两次TupleVector.__eq__ called:
- 第一次
TupleVector() == ListVector():直接调用TupleVector.__eq__ - 第二次
ListVector() == TupleVector():list.__eq__返回NotImplemented,触发调用TupleVector.__eq__
解决方案
要让两种向量的比较符合预期,必须为ListVector重写__eq__和__ne__,统一比较逻辑:
class ListVector(list): def __eq__(self, other): # 兼容list、tuple及自定义向量类的比较 if isinstance(other, (list, tuple, ListVector, TupleVector)): return all(x == y for x, y in zip(self, other, strict=True)) return NotImplemented def __ne__(self, other): return not self.__eq__(other)
此实现既保证了元素级别的相等性判断,又遵循Python运算符重载规范——对非可迭代类型返回NotImplemented,让对方继续处理比较逻辑。
内容的提问来源于stack exchange,提问作者Don Hatch
相关产品推荐
相关产品推荐

