【问题标题】:Python: case where x==y and x.__eq__y() return different things. Why?Python:x==y 和 x.__eq__y() 返回不同内容的情况。为什么?
【发布时间】:2014-06-03 15:52:12
【问题描述】:

我正在学习我的第一门计算科学课程,我们刚刚了解了类实现和继承。特别是,我们刚刚介绍了方法覆盖以及我们定义的类如何默认继承自 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

【问题讨论】:

    标签: python object inheritance superclass


    【解决方案1】:

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

    所以简而言之,你的困惑源于这个假设,这是不正确的:

    我认为 (x==y) 和 x.__eq__(y) 是同义词,并且进行了完全相同的调用

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

    【讨论】:

      【解决方案2】:

      您看到的从继承的__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,因此当您使用真正的运算符时,您的类会退回到身份比较,但在您直接调用__eq__ 时会显示NotImplemented 标记。

      【讨论】:

        【解决方案3】:

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

        【讨论】:

        • 实际上(如果您使用的是 Python 3 或 Python 2 中的新型类)一个默认的 __eq__,您可以免费获得 - 您继承自object。对于旧式类,如果您不定义 __eq__,您将永远不会像问题中那样从中获得 NotImplemented - 您将获得 AttributeError。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-02
        • 2022-01-17
        • 2018-07-29
        • 2013-01-11
        • 1970-01-01
        相关资源
        最近更新 更多