Why does __ne__ exist?

```Whoops, premature send. Picking up from the last paragraph.

This is good. This is correct. For inequalities, you can't assume that
>= is the exact opposite of < or the combination of < and == (for
example, sets don't behave like numbers, so "x <= y" is very different
from "x < y or x == y"). But the one that confuses me is != or __ne__.
If you don't create it, you get default behaviour:

>>> class Ham:
...     def __eq__(self, other):
...         print("%s equals %s" % (self, other))
...         return True
...
>>> Ham() == 1
<__main__.Ham object at 0x7fb7557c0278> equals 1
True
>>> 2 == Ham()
<__main__.Ham object at 0x7fb7557c0278> equals 2
True
>>> Ham() != 3
<__main__.Ham object at 0x7fb7557c0278> equals 3
False
>>> 4 != Ham()
<__main__.Ham object at 0x7fb7557c0278> equals 4
False
>>> x = Ham()
>>> x == x
<__main__.Ham object at 0x7fb7557b80f0> equals <__main__.Ham object at
0x7fb7557b80f0>
True
>>> x != x
<__main__.Ham object at 0x7fb7557b80f0> equals <__main__.Ham object at
0x7fb7557b80f0>
False

Under what circumstances would you want "x != y" to be different from
"not (x == y)" ? How would this make for sane behaviour? Even when
other things go weird with equality checks, that basic parallel is
always maintained:

>>> z = float("nan")
>>> z == z
False
>>> z != z
True

Python gives us a "not in" operator that uses __contains__ and then
negates the result. There is no way for "x not in y" to be anything
different from "not (x in y)", as evidenced by the peephole optimizer:

>>> dis.dis("x not in y")