- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在使用 __eq__
运算符和 NotImplemented
值。
我试图了解当 obj1.__eq__(obj2)
返回 NotImplemented
并且 obj2.__eq__(obj1)
也返回时会发生什么未实现
。
根据的回答Why return NotImplemented instead of raising NotImplementedError ,以及详细文章 How to override comparison operators in Python 在“LiveJournal”博客中,运行时应该回退到内置行为(基于 ==
和 !=
的标识)。
但是,尝试下面的示例,我似乎为每对对象多次调用了 __eq__
。
class Apple(object):
def __init__(self, color):
self.color = color
def __repr__(self):
return "<Apple color='{color}'>".format(color=self.color)
def __eq__(self, other):
if isinstance(other, Apple):
print("{self} == {other} -> OK".format(self=self, other=other))
return self.color == other.color
print("{self} == {other} -> NotImplemented".format(self=self, other=other))
return NotImplemented
class Orange(object):
def __init__(self, usage):
self.usage = usage
def __repr__(self):
return "<Orange usage='{usage}'>".format(usage=self.usage)
def __eq__(self, other):
if isinstance(other, Orange):
print("{self} == {other}".format(self=self, other=other))
return self.usage == other.usage
print("{self} == {other} -> NotImplemented".format(self=self, other=other))
return NotImplemented
>>> apple = Apple("red")
>>> orange = Orange("juice")
>>> apple == orange
<Apple color='red'> == <Orange usage='juice'> -> NotImplemented
<Orange usage='juice'> == <Apple color='red'> -> NotImplemented
<Orange usage='juice'> == <Apple color='red'> -> NotImplemented
<Apple color='red'> == <Orange usage='juice'> -> NotImplemented
False
我预计只有:
<Apple color='red'> == <Orange usage='juice'> -> NotImplemented
<Orange usage='juice'> == <Apple color='red'> -> NotImplemented
然后回到身份比较 id(apple) == id(orange)
-> False
。
最佳答案
这是 issue #6970在 Python 跟踪器中;它在 2.7 和 Python 3.0 和 3.1 中仍未修复。
这是由于在使用 __eq__
方法执行两个自定义类之间的比较时,两个地方尝试直接比较和交换比较引起的。
通过 PyObject_RichCompare()
function 进行丰富的比较,对于不同类型的对象(间接)委托(delegate)给 try_rich_compare()
.在这个函数中,v
和 w
是左右操作数对象,因为它们都有一个 __eq__
方法,所以函数同时调用了 v ->ob_type->tp_richcompare()
和 w->ob_type->tp_richcompare()
。
对于自定义类,tp_richcompare()
slot被定义为 slot_tp_richcompare()
function ,并且此函数再次为双方执行__eq__
,首先是self.__eq__(self, other)
然后是other.__eq__(other , self )
.
最后,这意味着 apple.__eq__(apple, orange)
和 orange.__eq__(orange, apple)
在 中的第一次尝试被调用try_rich_compare()
,然后反向调用,导致 orange.__eq__(orange, apple)
和 apple.__eq__(apple, orange)
调用因为 self
和 other
在 slot_tp_richcompare()
中交换。
请注意,该问题仅限于不同自定义类的实例,其中两个类 都定义了一个__eq__
方法。如果任何一方都没有这样的方法 __eq__
只执行一次:
>>> class Pear(object):
... def __init__(self, purpose):
... self.purpose = purpose
... def __repr__(self):
... return "<Pear purpose='{purpose}'>".format(purpose=self.purpose)
...
>>> pear = Pear("cooking")
>>> apple == pear
<Apple color='red'> == <Pear purpose='cooking'> -> NotImplemented
False
>>> pear == apple
<Apple color='red'> == <Pear purpose='cooking'> -> NotImplemented
False
如果您有两个相同类型的实例并且__eq__
返回NotImplemented
,您甚至会得到六次 比较:
>>> class Kumquat(object):
... def __init__(self, variety):
... self.variety = variety
... def __repr__(self):
... return "<Kumquat variety=='{variety}'>".format(variety=self.variety)
... def __eq__(self, other):
... # Kumquats are a weird fruit, they don't want to be compared with anything
... print("{self} == {other} -> NotImplemented".format(self=self, other=other))
... return NotImplemented
...
>>> Kumquat('round') == Kumquat('oval')
<Kumquat variety=='round'> == <Kumquat variety=='oval'> -> NotImplemented
<Kumquat variety=='oval'> == <Kumquat variety=='round'> -> NotImplemented
<Kumquat variety=='round'> == <Kumquat variety=='oval'> -> NotImplemented
<Kumquat variety=='oval'> == <Kumquat variety=='round'> -> NotImplemented
<Kumquat variety=='oval'> == <Kumquat variety=='round'> -> NotImplemented
<Kumquat variety=='round'> == <Kumquat variety=='oval'> -> NotImplemented
False
第一组两个比较是从优化尝试中调用的;当两个实例具有相同的类型时,您只需要调用 v->tp_richcompare(v, w)
并且可以跳过强制转换(对于数字),毕竟。但是,当比较失败时(返回 NotImplemented
),则也尝试了标准路径。
在 Python 2 中如何进行比较变得相当复杂,因为仍然必须支持旧的 __cmp__
3 向比较方法;在 Python 3 中,随着对 __cmp__
的支持被删除,更容易解决这个问题。因此,此修复程序从未向后移植到 2.7。
关于python - 为什么使用 __eq__ 运算符多次评估 NotImplemented,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39558377/
Or 运算符 对两个表达式进行逻辑“或”运算。 result = expression1 Or expression2 参数 result 任意数值变量。 expression1 任意
Not 运算符 对表达式执行逻辑非运算。 result = Not expression 参数 result 任意数值变量。 expression 任意表达式。 说明 下表显示如何
Is 运算符 比较两个对象引用变量。 result = object1 Is object2 参数 result 任意数值变量。 object1 任意对象名。 object2 任意
\ 运算符 两个数相除并返回以整数形式表示的结果。 result = number1\number2 参数 result 任意数值变量。 number1 任意数值表达式。 numbe
And 运算符 对两个表达式进行逻辑“与”运算。 result = expression1 And expression2 参数 result 任意数值变量。 expression1
运算符(+) 计算两个数之和。 result = expression1 + expression2 参数 result 任意数值变量。 expression1 任意表达式。 exp
我对此感到困惑snippet : var n1 = 5-"4"; var n2 = 5+"4"; alert(n1); alert(n2); 我知道 n1 是 1。那是因为减号运算符会将字符串“4”转
我想我会得到 12,而不是 7。 w++,那么w就是4,也就是100,而w++, w 将是 8,1000;所以 w++|z++ 将是 100|1000 = 1100 将是 12。 我怎么了? int
Xor 运算符 对两个表达式进行逻辑“异或”运算。 result = expression1 Xor expression2 参数 result 任意数值变量。 expression1
Mod 运算符 两个数值相除并返回其余数。 result = number1 Mod number2 参数 result 任意数值变量。 number1 任意数值表达式。 numbe
Imp 运算符 对两个表达式进行逻辑蕴涵运算。 result = expression1 Imp expression2 参数 result 任意数值变量。 expression1 任
Eqv 运算符 执行两个表达式的逻辑等价运算。 result = expression1 Eqv expression2 参数 result 任意数值变量。 expression1 任
我有一个运算符重载的简单数学 vector 类。我想为我的运算符(operator)获取一些计时结果。我可以通过计时以下代码轻松计时我的 +=、-=、*= 和/=: Vector sum; for(s
我是用户定义比较运算符的新手。我正在读一本书,其中提到了以下示例: struct P { int x, y; bool operator、运算符<等),我们
在 SQL 的维基百科页面上,有一些关于 SQL 中 bool 逻辑的真值表。 [1] 维基百科页面似乎来源于 SQL:2003 标准。 等号运算符 (=) 的真值表与 SQL:2003 草案中的 I
我遇到了一个奇怪的 C++ 运算符。 http://www.terralib.org/html/v410/classoracle_1_1occi_1_1_number.html#a0f2780081f
我正在阅读关于 SO 和 answers 中的一个问题,它被提到为: If no unambiguous matching deallocation function can be found, pr
我偶然发现了这个解决方案,但我无法理解其中到底发生了什么。谁能解释一下! 据我了解,它试图通过计算一半的单元格然后将其加倍来计算 a*b 网格中的单元格数量。但是我无法理解递归调用。 请不要建议其他解
Go的基本类型 布尔类型bool 长度:1字节 取值:布尔类型的取值只能是true或者false,不能用数字来表示 整型 通用整型 int / uint(有符号 / 无符号,下面也类似) 长度:根据运
在本教程中,您将学习JavaScript中可用的不同运算符,以及在示例的帮助下如何使用它们。 什么是运算符? 在JavaScript中,运算符是一种特殊符号,用于对运算数(值和变量)执行操作。例如,
我是一名优秀的程序员,十分优秀!