为啥 Python 文档说我在定义 __eq__ 时需要定义 __ne__?

Posted

技术标签:

【中文标题】为啥 Python 文档说我在定义 __eq__ 时需要定义 __ne__?【英文标题】:Why do the Python docs say I need to define __ne__ when I define __eq__?为什么 Python 文档说我在定义 __eq__ 时需要定义 __ne__? 【发布时间】:2014-08-18 18:36:18 【问题描述】:

根据Python docs:“在定义__eq__() 时,还应该定义__ne__(),以便操作符按预期运行”。

但是,Python 似乎自动将__ne__ 计算为not __eq__

In [8]: class Test:
    def __eq__(self, other):
        print("calling __eq__")
   ...:         return isinstance(other, Test)
   ...:

In [9]: a = Test()

In [10]: b = Test()

In [11]: a == b
calling __eq__
Out[11]: True

In [12]: a != b
calling __eq__
Out[12]: False

In [13]: a == 1
calling __eq__
Out[13]: False

In [14]: a != 1
calling __eq__
Out[14]: True

那么定义__ne__ 如果它只是return not self.__eq__(other) 又有什么意义呢?此外,这种行为实际记录在哪里?

编辑

显然,我使用 Python 3 很重要。在 Python 2 中,我得到了

In [1]: class Test(object):
   ...:     def __eq__(self, other):
   ...:         print("calling __eq__")
   ...:         return isinstance(other, Test)
   ...:

In [2]: a = Test()

In [3]: b = Test()

In [4]: a == b
calling __eq__
Out[4]: True

In [5]: a != b
Out[5]: True

In [6]: a == 1
calling __eq__
Out[6]: False

In [7]: a != 1
Out[7]: True

但我引用的文档是 Python 3 文档。他们只是没有更新吗?

【问题讨论】:

作为猜测(因此不是答案),您可能想要定义一些东西,例如Rect() == Square() # True, Square() == Rect() # False 这就是为什么他们建议您同时定义“以便操作员按预期行事” Related question and a possible duplicate 据我所知,这两种方法是独立的,覆盖其中一个并不意味着覆盖另一个。 @oleg 查看我的最佳示例。覆盖__eq__确实隐式定义__ne__,至少在Python 3中是这样。 看来如果你不定义__ne__它使用not__eq__。但x==y 的真相并不意味着x!=y 是假的。这就是为什么你应该定义两者。 【参考方案1】:

Python 3 更改了 == 案例的行为,请参阅 Python 3, What's New:

!= 现在返回与== 相反的值,除非== 返回NotImplemented

它被认为是a useful change。

文档没有更新确实是long standing bug。

然而,正如对报告的评论指出的那样,如果您从已经定义了 __ne__ 的类继承,仅覆盖 __eq__ 是不够的,您还必须覆盖__ne__ 方法。

【讨论】:

以上是关于为啥 Python 文档说我在定义 __eq__ 时需要定义 __ne__?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Python 有一个 __ne__ 运算符方法而不仅仅是 __eq__?

为啥 `if None.__eq__("a")` 似乎评估为 True(但不完全)?

python __eq__ 测试失败

为啥 Python 没有“__req__”(反射相等)方法?

重载 __eq__ 以返回自定义对象

__eq__ 方法将两个自定义对象与列表进行比较