首页 > 解决方案 > 如何选择性地覆盖 Python 中的“==”行为?

问题描述

环境:Python 2.7(可能与此有关。)

首先,我了解“==”的实现方式如下(来源):

  1. 如果
    • type(b)是新式班,
    • type(b)是一个子类type(a)
    • type(b)已覆盖__eq__

那么结果是b.__eq__(a)

  1. 如果
    • type(a)已被覆盖__eq__(即type(a).__eq__is not object.__eq__

那么结果是a.__eq__(b)

  1. 如果
    • type(b)已覆盖__eq__

那么结果是b.__eq__(a)

  1. 如果以上都不是,重复上述过程,但寻找__cmp__. 如果存在,则如果返回零,则对象相等。

  2. 作为最后的后备,Python 调用object.__eq__(a, b),它只是测试 a 和 b 是否是同一个对象。

.

现在我想覆盖__eq__一个对象,但是当对象没有自定义定义时,我会退回到上面的机制__eq__如何做到这一点?

我不能只保存原始__eq__方法,因为 '==' 实际上涉及上述复杂机制。

示例代码(未达到目标):

class A(object):
    def __eq__(self, other):
        try:
            self.___eq___
            return self.___eq___(other)
        except AttributeError:
            # trying to save default behaviour (Goal)

def custom_eq_bound_method(self, other):
    return True

# overriding __eq__
a1 = A()
a1.___eq___ = MethodType(custom_eq_bound_method, a1, A)

# not overriding __eq__
a2 = A()

# comparing a1 == a2 in business logic....

标签: pythonoverriding

解决方案


我敢肯定你之前已经问过这个问题并得到了回答,但似乎你正在寻找的是让类尝试推迟到你自己的别名,__eq__因为这个方法不能在实例级别被覆盖。

from types import MethodType
class A(object):
    def __eq__(self, other):
        try:
            self._eq
            return self._eq(other)        # defer to _eq
        except AttributeError:
            return super().__eq__(other)  # Here is the default behaviour

def custom_eq_bound_method(self, other):
    return True

a1 = A()
a2 = A()
a3 = A()

print(a1==a2)
print(a1==a3)
print(a2==a3)

a1._eq = MethodType(custom_eq_bound_method, a1)
print('After override')

print(a1==a2)
print(a1==a3)
print(a2==a3)

输出:

False
False
False
After override
True
True
False

推荐阅读