2
>>> class Yeah(object):
...     def __eq__(self, other):
...         return True
...     
>>> class Nah(object):
...     def __eq__(self, other):
...         return False
...     
>>> y = Yeah()
>>> n = Nah()
>>> y == n
True
>>> n == y
False

The left guy wins because when python2 sees x == y it tries x.__eq__(y) first.

Is there any way to modify Nah so that he will win both times?

My use-case is making something like this:

class EqualsAnyDatetime(object):
    def __eq__(self, other):
        return isinstance(other, datetime)

It just works in python3 because real_datetime.__eq__(random_other_thing) raises NotImplemented, giving the other side a shot at the comparison. In python2 I can't seem to get the idea working.

icedwater
  • 4,701
  • 3
  • 35
  • 50
wim
  • 338,267
  • 99
  • 616
  • 750
  • Realistically, equality should be symmetric. – OneCricketeer Dec 31 '15 at 06:13
  • Of course it should. That's why I want `any_datetime = EqualsAnyDatetime()` to work on both sides, not just the left side. – wim Dec 31 '15 at 06:15
  • @wim Do you require `__eq__` in `Nah`, if not then removing that from the `Nah` will invoke the function in `Yeah` for both `y == n` and `n == y` – nu11p01n73R Dec 31 '15 at 06:34
  • Imagine you could do this by somehow specifying `Nah` as "preemptive" (so it gets first shot at the comparison). Now what do you think should happen if you do `Nah == Other` or `Other == Nah`, where `Other` is another object that also identifies itself as "preemptive". No matter what you do, there has to be a rule about what to do first. If you let objects say "me first", then you'll just have the same problem when two objects say "me first" at the same time. – BrenBarn Dec 31 '15 at 06:37
  • I would answer to have `Nah`'s `__eq__` to call `Yeah`'s, but I am afraid to be donwvoted. I have tried and it works, but maybe I haven't grasped the essence/constraints of the problem – Pynchia Dec 31 '15 at 06:47
  • @BrenBarn I had considered that. If both sides have implemented the "me first" feature, it is acceptable for the left side to win. – wim Dec 31 '15 at 07:00
  • 1
    Although it doesn't solve your problem, you might like to take a look at my Any wildcard object in the last codeblock of [this answer](http://stackoverflow.com/a/29867270/4014959). – PM 2Ring Dec 31 '15 at 07:25

2 Answers2

1

No, you cannot do that. The left-hand operand is always tried first. If it handles the operation, the right-hand operand never gets a chance to do anything.

BrenBarn
  • 242,874
  • 37
  • 412
  • 384
1

I've found a way that can give the right hand side the opportunity to say "me first". The trick is to inherit from the type(s) who you want to strong-arm the comparison against.

Example:

>>> from datetime import datetime
>>> class EqualsAnyDatetime(datetime):
...     def __eq__(self, other):
...         return isinstance(other, datetime)
...     
>>> now = datetime.now()
>>> any_datetime = EqualsAnyDatetime(1970, 1, 1)
>>> now == any_datetime
True
>>> any_datetime == now
True
>>> now.__eq__(any_datetime)
False
wim
  • 338,267
  • 99
  • 616
  • 750