11

I was wondering about the reason of having a not equal operator in python.

The following snipped:

class Foo:
    def __eq__(self, other):
        print('Equal called')
        return True

    def __ne__(self, other):
        print('Not equal called')
        return True

if __name__ == '__main__':
    a = Foo()

    print(a == 1)
    print(a != 1)
    print(not a == 1)

outputs:

Equal called
True
Not equal called
True
Equal called
False

Doesn't this actually invite a lot of trouble by potentially saying:

A == B and A != B

can be correct at the same time. Furthermore this introduces a potential pitfall when forgetting to implement __ne__.

magu_
  • 4,766
  • 3
  • 45
  • 79
  • Optimization? And this is against contracts. – Willem Van Onsem Jun 11 '15 at 17:26
  • 9
    *"There are no implied relationships among the comparison operators. The truth of `x==y` does not imply that `x!=y` is false. Accordingly, when defining `__eq__()`, one should also define `__ne__()` so that the operators will behave as expected."* – Cory Kramer Jun 11 '15 at 17:27
  • @CoryKramer Where is it from? – vmonteco Jun 11 '15 at 17:28
  • 4
    This seems in line with Python's informal "we're all adults here" policy. If you want to shoot yourself in the foot by having inconsistent behavior for the two operators, then Python isn't going to stop you. (I know this doesn't really answer the question of "why have two different dunder methods in the first place?", but it's worth pointing out) – Kevin Jun 11 '15 at 17:28
  • you don't do any comparison in the operator? what are you expecting? – corn3lius Jun 11 '15 at 17:29
  • @CoryKramer. Thank you for the link. Without going into an opinion based discussion, but doesn't this introduce a lot of danger for only marginal gain? I mean sure I can life with the `we're all adults` statement but we have all this wonderful things like `contextmanager`, `it's better to ask for forgiveness than permission`, ... to actually make it easier to not shoot yourself in the foot. – magu_ Jun 11 '15 at 17:36
  • 1
    @magu_ I could see a strong argument either way, but I assume what they decided on was that Python should allow [many-valued logic](https://stackoverflow.com/questions/9452536/why-does-python-have-an-ne-operator-method-instead-of-just-eq) so the requirement of just returning `True` or `False` isn't imposed – Cory Kramer Jun 11 '15 at 17:41

3 Answers3

7

Depending on one's needs there are cases where equal and not equal are not opposite; however, the vast majority of cases they are opposite, so in Python 3 if you do not specify a __ne__ method Python will invert the __eq__ method for you.

If you are writing code to run on both Python 2 and Python 3, then you should define both.

Ethan Furman
  • 63,992
  • 20
  • 159
  • 237
  • NaN was my first thought too, but I just tested it and I can't come up with a circumstance where the two comparisons don't return opposite results. – Mark Ransom Jun 11 '15 at 17:50
  • Hm, I disagree. It should be defined by the library if NaN are equal to any number of not. I agree with the second point though, except when subclassing it is still a potential pitfall. – magu_ Jun 11 '15 at 17:51
  • @MarkRansom: Ah, right, thanks. Fixed that point. – Ethan Furman Jun 11 '15 at 17:53
  • @magu_: I removed the point about `NaN` as I was wrong, but in Python `NaN` is unequal to everything, including itself. For a library to do something else it would have to create it's own `NaN`-like object and use that. – Ethan Furman Jun 11 '15 at 17:56
  • "Explicit is better than implicit." – Greg Mueller Jun 12 '15 at 09:45
1

Per the data model documentation, which covers the "magic methods" you can implement on classes (emphasis mine):

There are no implied relationships among the comparison operators. The truth of x==y does not imply that x!=y is false. Accordingly, when defining __eq__(), one should also define __ne__() so that the operators will behave as expected.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • 1
    I'd love to see a practical example where it's useful to have `__eq__` and `__ne__` behave inconsistently. – Mark Ransom Jun 11 '15 at 17:56
  • 3
    @MarkRansom how about `numpy`, where `==` and `!=` on arrays create arrays of boolean element-wise comparison? `x != y` gives an array, `not x == y` gives a `ValueError`! – jonrsharpe Jun 12 '15 at 10:57
-2

Seems you are returning True instead of doing the comparison.

J_B
  • 185
  • 10