-1

In this example, I am trying to assign new __eq__, __lt__ and __gt__ methods and invoke them by comparing the object to the literal 3. Why is bar(...) never called?

class Foo:
    def __init__(self):
        self.__eq__ = self.bar
        self.__lt__ = self.bar
        self.__gt__ = self.bar

    def bar(self, other):
        print("bar called.")

a = Foo()
a == 3
a < 3
a > 3

In this answer I found the hint you can't assign new __eq__ to the object. I can't find any official source for this statement though.

Any hints and help is appreciated!

Edit: I am aware that there is the option of defining __eq__ in the object itself, but this questions is specifically about assigning it after instance creation.

Community
  • 1
  • 1
jojonas
  • 1,634
  • 14
  • 24

1 Answers1

5

Special Method Lookup:

implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary.

If the goal is to use bar for comparisons, assign it at the class level, not per instance (which will also save memory by not bloating the per instance attribute dictionary):

class Foo:
    def bar(...):
        ...
    __eq__ = __lt__ = __gt__ = bar
ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • I am not sure why I am being downvoted, I don't think it's such a trivial question. But thank you for your answer! – jojonas Sep 10 '15 at 13:20
  • I suspect because this sort of question gets asked a lot (I basically copied my answer from a comment I made on a similar question about `__call__`). I didn't downvote, but people often downvote what they view as redundant questions. – ShadowRanger Sep 10 '15 at 13:27
  • Obviously I tried searching, but I didn't find any information on it on SO. But true, I didn't think of trying to assign `__call__`, maybe I could have found more info. – jojonas Sep 10 '15 at 13:29
  • If you need to be able to override per instance, then define some other method (e.g. `_realeq`) and define `__eq__` (at class level) to call it. You can then assign instances their own `_realeq` which, not being a special method, will be called as you expect. – ShadowRanger Sep 10 '15 at 13:29
  • I was researching for [this question](http://stackoverflow.com/questions/32501397/object-that-raises-exception-when-used-in-any-way) when I stumbled about this problem. I tried replacing all the methods listed by `dir(...)` on an instance, but apparently the underscore methods failed. – jojonas Sep 10 '15 at 13:34