Как выборочно переопределить поведение «==» в Python? - PullRequest
0 голосов
/ 16 мая 2019

Среда: Python 2.7 (возможно, это как-то связано с этим.)

Сначала я понимаю, что '==' реализовано следующим образом ( source ):

  1. если
    • type(b) - класс в новом стиле,
    • type(b) является подклассом type(a)
    • type(b) переопределено __eq__

тогда результат b.__eq__(a)

  1. Если
    • type(a) переопределено __eq__ (то есть type(a).__eq__ не 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....

1 Ответ

0 голосов
/ 16 мая 2019

Я уверен, что вы спрашивали об этом раньше и отвечали на него, но, похоже, вам нужно, чтобы класс попытался отложить свой собственный псевдоним для __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
...