python 对象相等('==')的默认行为在哪里定义?

p4tfgftt  于 2023-03-11  发布在  Python
关注(0)|答案(1)|浏览(115)

根据object.__eq__()文档,==的默认(即在object类中)实现如下:

True if x is y else NotImplemented

仍然按照NotImplemented的文档,我推断NotImplemented暗示Python运行时将尝试相反的比较,即如果x.__eq__(y)返回NotImplemented,则尝试y.__eq__(x)(在==操作符的情况下)。
现在,下面的代码在python 3.9中打印FalseTrue

class A:
   pass
print(A() == A())
print(bool(NotImplemented))

因此,我的问题是:文档在__eq__上下文中的何处提到了NotImplemented的特殊行为?
PS:我在CPython源代码中找到了答案,但我猜这一定/应该在文档中的某个地方。

zujrkrfu

zujrkrfu1#

根据object.__eq__()文档,==的缺省(即在对象类中)实现如下
否;这是__eq__的默认实现==是一个运算符,不能在类中实现。
Python的运算符实现是合作的,有硬编码的逻辑使用dunder方法来计算应该发生什么,并且可能福尔斯默认值,这种逻辑是在任何类之外的。
您可以看到内置len的另一个示例:一个类可以从它的__len__方法返回任何它喜欢的东西,原则上你可以直接调用它并得到任何类型的值。然而,这并不能正确地实现协议,当len没有得到一个非负整数时,它会抱怨。没有任何类包含类型检查和值检查逻辑。它是外部的。
仍然按照NotImplemented的文档,我推断NotImplemented暗示Python运行时将尝试相反的比较,即如果x.__eq__(y)返回NotImplemented,则尝试y.__eq__(x)(在==操作符的情况下)。
NotImplemented只是一个对象,它不是语法,它没有任何特殊行为,在Python中,简单地返回一个值并不会触发特殊行为,除了返回值之外。
二元运算符的外部代码将尝试查找匹配的__op__,如果__op__不起作用,则尝试查找匹配的__rop__。(它是专门为此目的而存在的标记,因为None可接受的答案)。通常,如果到目前为止答案仍然是NotImplemented,则外部代码将是raise NotImplementedError

作为特殊情况,不提供自身比较的对象(即,object中的默认值用于__eq____ne__)将比较为“不相等”,除非它们相同。(我猜是在类 * 显式 * 将__eq____ne__直接定义为return NotImplemented的情况下)这是因为给予这个结果被认为是明智的,而在有一个明智的默认值的情况下让==一直失败是令人讨厌的。

然而,如果没有显式逻辑,这两个对象仍然是不可 * 排序 * 的,因为没有合理的默认值(您可以比较指针值,但它们是任意的,与让您到达该点的Python逻辑没有任何关系;所以这样排序对于编写Python代码实际上没有什么用处。)例如,如果没有提供比较逻辑,x < y将引发TypeError(它这样做 * 即使 * x is y;在这种情况下,您可以合理地说<=>=应该为真,<>应该为假,但这会使事情变得过于复杂,而且不是很有用。)
[观察结果:打印print(bool(NotImplemented))打印True]
是的,NotImplemented是一个对象,所以默认情况下是true;它不代表一个数值,也不是一个容器,所以它没有理由是假的。
然而,这也没有告诉我们任何有用的东西,我们不关心NotImplemented的真实性,在Python实现中也没有这样使用它,它只是一个哨兵值。
文档在哪里提到了NotImplemented在__eq__上下文中的特殊行为?
没有,因为它 * 不是NotImplemented * 的行为,如上所述。
好吧,但还有个潜在的问题:文档在哪里解释了默认情况下==操作符的作用?
答:因为我们讨论的是一个运算符,而不是一个方法,所以它不在关于dunder方法的章节中,而是在关于表达式的章节6中,具体来说就是6.10.1.值比较:
相等比较的默认行为(==!=)基于对象的标识。因此,具有相同标识的示例的相等性比较导致相等,对具有不同标识的示例进行比较和相等性比较会导致不相等。这种默认行为的动机是希望所有对象都是自反的(即x is y意味着x == y)。

相关问题