如何在Python中有选择地覆盖'=='行为?

时间:2019-05-16 09:43:55

标签: python override

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

首先,我了解到'=='的实现方式如下(source):

  
      
  1. 如果      
        
    • type(b)是一种新型的类
    •   
    • type(b)type(a)的子类
    •   
    • type(b)已覆盖__eq__
    •   
  2.   
     

那么结果就是b.__eq__(a)

     
      
  1. 如果      
        
    • type(a)已覆盖__eq__(即type(a).__eq__不是object.__eq__
    •   
  2.   
     

那么结果就是a.__eq__(b)

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

那么结果就是b.__eq__(a)

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

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

  4.   

现在,我想覆盖对象的__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....

1 个答案:

答案 0 :(得分:0)

我确定您之前已经问过这个问题并得到了回答,但是看来您正在寻找的是让该类尝试为__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