以下代码适用于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
答案 0 :(得分:4)
它有效,因为int.__eq__(<something>)
会返回NotImplemented
,当发生这种情况时,会调用other.__eq__(self)
,这就是True
和False
的回复。
<强>演示:强>
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)
When mixing float with an integer type, there's no good uniform approach. https://github.com/python/cpython/blob/2.7/Objects/floatobject.c#L401-L417
P.S. How int() object using "==" operator without __eq__() method in python2?
答案 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
继承了int
从cmp
开始,翻译人员回到使用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