为什么`int .__ eq __(其他)`是一个有效的比较?

时间:2016-12-09 12:23:47

标签: python python-2.7

以下代码适用于Python 2.7:

>>> class Derived(int):
...     def __eq__(self, other):
...         return int.__eq__(other)
...
>>> Derived(12) == 12.0
True
>>> Derived(12) == 13
False

我不明白,为什么它有效,因为self属性未明确赋予int.__eq__()方法调用。

[编辑]

到目前为止,

答案提示,它是关于NotImplemented返回self.__eq__(other)并因此调用other.__eq__(self)。然后Derived(12) == Derived(12)我希望是一个不定式的递归,事实并非如此:

>>> Derived(12) == Derived(12)
True

3 个答案:

答案 0 :(得分:4)

它有效,因为int.__eq__(<something>)会返回NotImplemented,当发生这种情况时,会调用other.__eq__(self),这就是TrueFalse的回复。

<强>演示:

class Derived(int):
     def __eq__(self, other):
         print self, other
         print int.__eq__(other)
         print other.__eq__(self)
         return int.__eq__(other)

>>> Derived(12) == 12.0
12 12.0
NotImplemented
True
True
>>> Derived(12) == 13.0
12 13.0
NotImplemented
False
False

来自NotImplemented 的文档:

  

二进制特殊方法应返回的特殊值   (例如__eq__()__lt__()__add__()__rsub__()等)   表明该操作未实现   其他类型;可以通过就地二进制特殊方法返回   (例如__imul__()__iand__()等)出于同样的目的。它的   真值是真的。

     

注意当返回NotImplemented时,解释器将尝试   另一种类型的反射操作,或其他一些后备,   取决于运营商。如果所有尝试的操作都返回   未实现,解释器将引发适当的异常。

__eq__返回NotImplemented时会发生什么?

Python 2和3中的行为不同。

在Python 2中,它首先回到__cmp__方法,而整数有__cmp__ method in Python 2。它已在Python 3中删除。

根据Python 2文档,如果没有找到任何内容,它最终会回归到身份比较:

  

如果未定义__cmp__()__eq__()__ne__()操作,则为class   实例按对象标识(“地址”)进行比较

class Derived(int):
    def __eq__(self, other):
        print ("Inside  __eq__")
        return NotImplemented

    def __cmp__(self, other):
        print ("Inside __cmp__ finally")
        return True

>>> Derived(12) == Derived(12)
Inside  __eq__
Inside  __eq__
Inside __cmp__ finally
False

不要让我们定义一个没有定义方法的类:

class Derived(object):
    pass

>>> Derived() == Derived()  
False
>>> d = Derived()
>>> d == d  # Same objects.
True

Python 3不再具有__cmp__方法,但现在似乎又回归到身份。它似乎也没有记录。

#  Python 3.5
>>> Derived() == Derived()
False
>>> d = Derived()
>>> d == d
True

答案 1 :(得分:1)

答案 2 :(得分:0)

在Python 2.7中,如果你致电int.__eq__,它总会返回NotImplemented。例如:

>>> int.__eq__(12.0)
NotImplemented

当您使用==运算符时,它将尝试在左参数上运行__eq__方法,如果它获得NotImplemented,它将返回__eq__的结果来自右边的参数的方法。

Derived(12) == 12.0的示例中,解释程序首先尝试Derived(12).__eq__(12.0),然后获取NotImplemented。然后,它会在__eq__float上运行12.0方法并获取True

对于您的Derived(12) == Derived(12)示例,可能发生的事情是,因为两个对象都为NotImplemented方法返回__eq__,并且Derived继承了intcmp开始,翻译人员回到使用int的{​​{1}}内置行为(根据this answer,这是与您的问题的另一个答案相关联的。)< / p>

以下是一个说明您案例的例子:

class Derived(int):
    def __eq__(self, other):
        print 'Doing eq'
        return NotImplemented
    def __cmp__(self, other):
        print 'doing cmp'
        return 0  # contrived example - don't do this

>>> Derived(12) == Derived(12)
doing eq
doing eq
doing cmp
True