40

The answer here gives a handwaving reference to cases where you'd want __ne__ to return something other than just the logical inverse of __eq__, but I can't imagine any such case. Any examples?

Community
  • 1
  • 1
Jegschemesch
  • 11,414
  • 4
  • 32
  • 37
  • 7
    At least for `>` and `<=` there are such cases. Namely `NaN < anything => false` and `NaN >= anything => false`. (Assuming python follows IEEE floating point logic) – CodesInChaos Feb 26 '12 at 11:04
  • 3
    Yep basically anything that doesn't have a [total order](http://en.wikipedia.org/wiki/Total_ordering) can fall into that category. Now those things are kinda rare for obvious reasons, but they do exist. NaNs are a nice example. – Voo Feb 26 '12 at 11:09
  • 5
    But even for `NaN` it holds at least in python: `NaN != NaN => True`, `NaN == NaN => False`. – Has QUIT--Anony-Mousse Feb 26 '12 at 11:37
  • The fact that `equals` (`__eq__`) _may not_ return a `Boolean` type and that `not equals` (`__ne__`) _may not_ be the opposite of equals... defies all intuition. -- I accept it as the Python way. I guess it has its benefits as explained by the answers. Yet, for newcomers to the language, this is eerie. – juanmirocks Nov 11 '16 at 09:31

3 Answers3

31

SQLAlchemy is a great example. For the uninitiated, SQLAlchemy is a ORM and uses Python expression to generate SQL statements. In a expression such as

meta.Session.query(model.Theme).filter(model.Theme.id == model.Vote.post_id)

the model.Theme.id == model.VoteWarn.post_id does not return a boolean, but a object that eventually produces a SQL query like WHERE theme.id = vote.post_id. The inverse would produce something like WHERE theme.id <> vote.post_id so both methods need to be defined.

Jochen Ritzel
  • 104,512
  • 31
  • 200
  • 194
30

Some libraries do fancy things and don't return a bool from these operations. For example, with numpy:

>>> import numpy as np
>>> np.array([1,2,5,4,3,4,5,4,4])==4
array([False, False, False,  True, False,  True, False,  True,  True], dtype=bool)
>>> np.array([1,2,5,4,3,4,5,4,4])!=4
array([ True,  True,  True, False,  True, False,  True, False, False], dtype=bool)

When you compare an array to a single value or another array you get back an array of bools of the results of comparing the corresponding elements. You couldn't do this if x!=y was simply equivalent to not (x==y).

Weeble
  • 17,058
  • 3
  • 60
  • 75
  • 1
    I can't follow that. Considering that `not` is defined on an array of bools in the obvious way, we still don't need `neq` instead of `not equals`. But clearly there's a performance and possible memory advantage there. – Voo Feb 26 '12 at 18:12
  • 7
    While a good argument could be made for a `__not__` special method to override the `not` operator, this does not currently exist in Python. – Weeble Feb 26 '12 at 18:50
  • 1
    Oh that's surprising.. yeah in that case it's not only a matter of performance. Thanks! – Voo Feb 26 '12 at 19:07
  • @Weeble Unary invert ([`__invert__`](https://docs.python.org/3/reference/datamodel.html#object.__invert__)) works: `~np.array([True, False])` -> `array([False, True])`. Though I'm not sure if it was the same back in 2012. – wjandrea Aug 04 '20 at 03:58
8

More generally, in many valued logic systems, equals and not equals are not necessarily exact inverses of each other.

The obvious example is SQL where True == True, False == False and Null != Null. Although I don't know if there are any specific Python examples I can imagine it being implemented in places.

Ben
  • 51,770
  • 36
  • 127
  • 149