Python:x == y和x .__ eq__y()的情况返回不同的东西。为什么?

时间:2014-04-19 04:46:32

标签: python object inheritance superclass

我参加了我的第一个计算科学课程,我们刚刚学习了类实现和继承。特别是,我们刚刚介绍了方法覆盖以及我们定义的类如何默认继承自object超类。作为我尝试这种特殊继承情况的一个例子,我使用了以下代码:

class A:
    def __init__(self, i):
        self.i = i
    def __str__(self):
        return "A"
    # Commenting out these two lines to not override __eq__(), just use the 
    # default from our superclass, object
    #def __eq__(self, other):
        #return self.i == other.i

x = A(2)
y = A(2)

>>>print(x == y)
False
>>>print(x.__eq__(y))
NotImplemented

我期待(x == y)的结果,因为根据我的理解,__eq__()的默认设置是检查它们是否是相同的对象,而不是担心内容。哪个是Falsexy具有相同的内容,但却是不同的对象。第二个让我感到惊讶。

所以我的问题:我认为(x==y)x.__eq__(y)是同义词并且完全相同。为什么这些会产生不同的输出?为什么第二个条件返回NotImplemented

3 个答案:

答案 0 :(得分:9)

==运算符等效于eq函数,如果存在,则会在内部调用左操作数的__eq__方法以尝试确定相等性。这不是唯一的事情,如果__eq__不存在,就像这里的情况一样,它会做其他检查,例如检查两者是否是同一个对象,或__cmp__ pre-Python 3。

简而言之,您的混淆源于这种假设,这是不正确的:

  

我认为(x == y)和x .__ eq __(y)是同义词并且完全相同的呼叫

事实上,(x==y)operators.eq(x, y)是同义词,x.__eq__(y)eq(x, y)尝试检查的内容之一。

答案 1 :(得分:6)

您从继承的__eq__方法返回的NotImplemented value是一个特殊的内置值,在Python中用作哨兵。它可以由实现数学运算符或比较运算符的__magic__方法返回,以指示该类不支持尝试的运算符(使用提供的参数)。

这比引发异常更有用,因为它允许Python回退到其他选项来解决操作符的使用。例如,如果你执行x + y,Python将首先尝试运行x.__add__(y)。如果返回NotImplemented,则接下来会尝试"反向"版本y.__radd__(x),如果y是比x更复杂的类型,则可能有效。

如果您要询问x == y,则Python首先尝试x.__eq__(y),然后y.__eq__(x),最后x is y(最终将评估为布尔值)。由于object.__eq__在所有情况下均返回NotImplemented,因此当您使用真实运算符时,您的类会回退到身份比较,但在您直接调用NotImplemented时会向您显示__eq__标记

答案 2 :(得分:0)

如果您已为某个类实现了__eq__()函数,则在使用x == y时会调用它。否则x == y依赖于默认比较逻辑。定义类时,__eq__()不会自动实现。