0

Environment: Python 2.7 (It just might have something to do with this.)

First I understand the '==' is implemented as following (source):

  1. if
    • type(b) is a new-style class,
    • type(b) is a subclass of type(a)
    • type(b) has overridden __eq__

then the result is b.__eq__(a)

  1. If
    • type(a) has overridden __eq__ (that is, type(a).__eq__ isn't object.__eq__)

then the result is a.__eq__(b)

  1. If
    • type(b) has overridden __eq__

then the result is b.__eq__(a).

  1. If none of the above are the case, repeats the process above, but looking for __cmp__. If it exists, the objects are equal if it returns zero.

  2. As a final fallback, Python calls object.__eq__(a, b), which is just testing if a and b are the same object.

.

Now I want to override __eq__ of an object, but falls back to the mechanism above when object has no custom __eq__ defined. How to achieve this?

I can't just save the original __eq__ method because '==' actually involves a complex mechanism described above.

Example Code (with target not achieved):

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....
Sajuuk
  • 2,667
  • 3
  • 22
  • 34
  • 1. What do you mean under "new style class"? 2. What is the difference between `b.__eq__(a)` and `a.__eq__(b)`? 3. Why to not override such as behaviour in each type. As I interpret your problem in my head .. there should not be a problem, just declare classes and override methods properly. – Olvin Roght May 16 '19 at 09:58
  • *Why* would you want to override `__eq__` for a single object? This sounds like a design problem. – chepner May 16 '19 at 11:15
  • @chepner I have different sets of functions to tweak objects produced by same class, potentially adding attributes to them. I want to compare objects tweaked by the same set of functions. – Sajuuk May 16 '19 at 11:26
  • Then you probably want separate subclasses, rather than hacking objects of the same class. – chepner May 16 '19 at 12:01

1 Answers1

0

I'm sure you've asked this before and had it answered, but it seems what you are looking for is to have the class to try to defer to your own alias for __eq__ since this method cannot be overridden at the instance level.

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)

Output:

False
False
False
After override
True
True
False
quamrana
  • 37,849
  • 12
  • 53
  • 71
  • if you try your code in python2.7, you will get an error : AttributeError: 'super' object has no attribute '__eq__' (even if substitue `super().__eq__` to `super(self.__class__).__eq__` – Sajuuk May 16 '19 at 11:03
  • Yes, sorry, I'm running python 3. – quamrana May 16 '19 at 11:08
  • and btw how is using `super().__eq__` can achieve the same effect of that complex mechanism described in my question? – Sajuuk May 16 '19 at 11:14
  • I don't know. I am simply following the code that you post. – quamrana May 16 '19 at 11:16