为什么/何时在Python中,`x==y`调用`y.\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\?
Python文档清楚地声明为什么/何时在Python中,`x==y`调用`y.\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\?,python,comparison,operator-overloading,Python,Comparison,Operator Overloading,Python文档清楚地声明x==y调用x.\uuuueq\uuuuy(y)。然而,在许多情况下,情况似乎恰恰相反。在何处记录了发生这种情况的时间或原因,以及如何确定对象的\uuuucmp\uuuuuuu或\uuuuuuu eq\uuuuu方法是否将被调用 编辑:我只是想澄清一下,我知道调用\uuuuuueq\uuuuuu比调用\uuuucmp\uuuuuuuu更优先,但我不清楚为什么y.\uuuuuueq\uuuuuuuuuuuuuuuux比调用x.\uuuuuuuuuueq\uuuuuuuuu
x==y
调用x.\uuuueq\uuuuy(y)
。然而,在许多情况下,情况似乎恰恰相反。在何处记录了发生这种情况的时间或原因,以及如何确定对象的\uuuucmp\uuuuuuu
或\uuuuuuu eq\uuuuu
方法是否将被调用
编辑:我只是想澄清一下,我知道调用\uuuuuueq\uuuuuu
比调用\uuuucmp\uuuuuuuu
更优先,但我不清楚为什么y.\uuuuuueq\uuuuuuuuuuuuuuuux
比调用x.\uuuuuuuuuueq\uuuuuuuuuuuuuy
更优先,而文档状态就是后者
>>> class TestCmp(object):
... def __cmp__(self, other):
... print "__cmp__ got called"
... return 0
...
>>> class TestEq(object):
... def __eq__(self, other):
... print "__eq__ got called"
... return True
...
>>> tc = TestCmp()
>>> te = TestEq()
>>>
>>> 1 == tc
__cmp__ got called
True
>>> tc == 1
__cmp__ got called
True
>>>
>>> 1 == te
__eq__ got called
True
>>> te == 1
__eq__ got called
True
>>>
>>> class TestStrCmp(str):
... def __new__(cls, value):
... return str.__new__(cls, value)
...
... def __cmp__(self, other):
... print "__cmp__ got called"
... return 0
...
>>> class TestStrEq(str):
... def __new__(cls, value):
... return str.__new__(cls, value)
...
... def __eq__(self, other):
... print "__eq__ got called"
... return True
...
>>> tsc = TestStrCmp("a")
>>> tse = TestStrEq("a")
>>>
>>> "b" == tsc
False
>>> tsc == "b"
False
>>>
>>> "b" == tse
__eq__ got called
True
>>> tse == "b"
__eq__ got called
True
编辑:从马克·迪金森的回答和评论来看:
\uuu cmp\uuuu
\uuuu eq\uuuuu
是它自己的\uuuu rop\uuuuu
(类似于\uu lt\uuuuuu
,\uu ge\uuuuuuu
等)\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
之前尝试右侧对象的
TestStrCmp
示例中的行为TestStrCmp
是str
的一个子类,但没有实现自己的\uuuu eq\uuuu
,因此str
的\uuuu eq\uuuuuu
在这两种情况下都优先(即tsc==“b”
调用b.\uu eq\uuuuuu(tsc)
作为\uuu rop\uuuu>因为规则1)
在TestStrEq
示例中,tse.\uuuuu eq\uuuu
在这两个实例中都被调用,因为TestStrEq
是str
的子类,因此优先调用它
在TestEq
示例中,TestEq
实现了\uuuueq\uuuuu
,而int
则不会同时调用\uuuuueq\uuuuu
(规则1)
但是我仍然不理解TestCmp
的第一个示例tc
不是int
上的子类,因此AFAICT1。应该调用\uuuu cmp\uuuuu(tc)
,但不是。中是否没有记录这一点?只要快速看一下,当定义了\uuuuuueq\uuuu
,\uult\uuuu
等时,似乎忽略了\uucmp\uuuuu
。我的理解是,包括在父类上定义\uuuu eq\uuu
的情况<代码>str.uuu eq_uuu
已定义,因此将忽略其子类上的\uuuu cmp\uuuu
<代码>对象。未定义\uuuu eq\uuuu等,因此其子类上的\uuuu cmp\uuuu
将得到尊重
针对澄清的问题:
我知道\uuuu eq\uuuu
被调用了
我更喜欢\uuu cmp\uuuu
,但我不是
清楚为什么y.。\uuuueq\uuuuux)
在中被调用
当
后者是docs州将要做的事情
发生
文档说x.。\uuuueq\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。我不知道你为什么相信这里发生了一些不同的事情
你对哪种情况特别感到困惑?我理解你只是对“b”==tsc
和tsc==“b”
案例感到困惑,对吗?在这两种情况下,str.\uuuuuueq\uuuuuuu(一件事,另一件事)
正在被调用。由于您没有重写TestStrCmp中的\uuuuuu eq\uuuuu
方法,因此最终您只依赖于基本字符串方法,它表示对象不相等
在不知道str.\uuuuu eq\uuuu
的实现细节的情况下,我不知道(“b”)。\uuuuuu eq\uuuu(tsc)
是否会返回NotImplemented
,并给tsc一个处理平等性测试的机会。但即使它这样做了,按照TestStrCmp的定义方式,您仍然会得到一个错误的结果
所以不清楚你在这里看到了什么,这是出乎意料的
也许现在的情况是,如果Python在被比较的对象上定义了\uuuuu eq\uuuu
,那么它更喜欢\uuuuu cmp\uuuuu
,而您希望最左侧对象上的\uuuu cmp\uuuuu
优先于右侧对象上的\uuu eq\uu
。是吗?据我所知,\uuuuuu eq\uuuuu()
是一种所谓的“丰富比较”方法,与下面的\uuuu cmp\uuuuu()
相比,它更适合于比较运算符<如果未定义“丰富比较”,则调用代码>\uuuu cmp\uuuu()
所以在A==B:如果在中定义了
\uuuuu eq\uuuu()
,则将调用否则将调用
\uuu cmp\uuu()
在'str'中定义了\uuuuu eq\uuuuuuuuuuuuuu()
,因此未调用您的\uuuuuuu cmp\uuuuuuuuuuuuu()
函数
同样的规则也适用于\uuu ne\uuuuuuu()、\ uuuu gt\uuuuuu()、\ uu ge\uuuuuuuuu()、\ uuuuuu lt\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu()
和\uuuuuuuuuuuuuu
如果未定义富比较(见上文),则比较操作会调用[\uuu\cmp\uu
\uuuuuu eq\uuuuu
是一种丰富的比较方法,在TestCmp
的情况下没有定义,因此调用\uuuuu cmp\uuuu
您缺少一个常见行为的关键异常:当右侧操作数是左侧操作数类的子类的实例时,首先调用右操作数的特殊方法
请参阅以下网址的文档:
特别是以下两段:
对于对象x
和y
,首先
x.\uuuu op\uuuuu(y)
已尝试。如果不是这样的话
执行或返回
NotImplemented
,y.\uuuuu-rop\uuuuuuuux
是
尝试如果这也没有实现
或返回未实现
,一个
引发TypeError异常。但是看到了吗
以下例外情况:
前一项的例外情况:如果
左操作数是
内置类型或新样式的类,
右操作数是一个实例
适当的