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?
 
    
    - 1
- 1
 
    
    - 11,414
- 4
- 32
- 37
- 
                    7At 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
- 
                    3Yep 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
- 
                    5But 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 Answers
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.
 
    
    - 104,512
- 31
- 200
- 194
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).
 
    
    - 17,058
- 3
- 60
- 75
- 
                    1I 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
- 
                    7While 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
- 
                    1Oh 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
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.
 
    
    - 51,770
- 36
- 127
- 149
- 
                    1And in MYSQL, you can even have values that are `NULL` and `NOT NULL` at the same time!!!1! (I consider that a design bug of MySQL though) – Has QUIT--Anony-Mousse Feb 26 '12 at 20:31