And*_*eas 18 python python-3.x
__eq__如果比较的一侧是从另一侧继承的对象,我最近偶然发现了关于方法执行顺序的看似奇怪的行为。
在一个公认的学术示例中,我已经在Python 3.7.2中进行了尝试。通常,在进行相等性比较的情况下,如果第一个调用返回了a == b,我希望a.__eq__首先被b.__eq__调用NotImplemented。但是,如果a和b属于同一类层次结构的一部分,则情况似乎并非如此。考虑以下示例:
class A(object):
def __eq__(self, other):
print("Calling A({}).__eq__".format(self))
return NotImplemented
class B(A):
def __eq__(self, other):
print("Calling B({}).__eq__".format(self))
return True
class C(object):
def __eq__(self, other):
print("Calling C({}).__eq__".format(self))
return False
a = A()
b = B()
c = C()
print("a: {}".format(a)) # output "a: <__main__.A object at 0x7f8fda95f860>"
print("b: {}".format(b)) # output "b: <__main__.B object at 0x7f8fda8bcfd0>"
print("c: {}".format(c)) # output "c: <__main__.C object at 0x7f8fda8bcef0>"
a == a # case 1
a == b # case 2.1
b == a # case 2.2
a == c # case 3.1
c == a # case 3.2
Run Code Online (Sandbox Code Playgroud)
在情况1中,我希望a.__eq__两次被调用,这也是我得到的:
Calling A(<__main__.A object at 0x7f8fda95f860>).__eq__
Calling A(<__main__.A object at 0x7f8fda95f860>).__eq__
Run Code Online (Sandbox Code Playgroud)
但是,在情况2.1和2.2中,b.__eq__无论处于比较的哪一侧,总是首先执行:
Calling B(<__main__.B object at 0x7f8fda8bcfd0>).__eq__ # case 2.1
Calling B(<__main__.B object at 0x7f8fda8bcfd0>).__eq__ # case 2.2
Run Code Online (Sandbox Code Playgroud)
然后在情况3.1和3.2中,如我所料,首先再次评估左侧:
Calling A(<__main__.A object at 0x7f8fda95f860>).__eq__ # case 3.1
Calling C(<__main__.C object at 0x7f8fda8bcef0>).__eq__ # case 3.1
Calling C(<__main__.C object at 0x7f8fda8bcef0>).__eq__ # case 3.2
Run Code Online (Sandbox Code Playgroud)
似乎,如果比较的对象彼此相关,__eq__则总是首先评估子类的对象。这种行为背后是否有更深层的推理?如果是这样,这是否记录在某处?据我所知,PEP 207没有提到这种情况。还是我可能在这里错过了明显的东西?
Len*_*mju 18
如果操作数是不同类型的,并且右操作数的类型是左操作数类型的直接或间接子类,则右操作数的反射方法具有优先级,否则左操作数的方法具有优先级。
| 归档时间: |
|
| 查看次数: |
814 次 |
| 最近记录: |