Reputation: 160377
I recently started reading The Python Language Reference, Release 2.7.10.
In Section 3.4: Special Method Names and particularly regarding the comparison operators object.__eq__(self, other)
and object.__ne__(self, other)
it states the following which has lead to some confusion:
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.
What exactly does this statement mean? How can the truth of x==y
not automatically and without question translate to a false value of x!=y
?
Upvotes: 1
Views: 83
Reputation: 530843
Here's a contrived example that demonstrates one possible use of decoupling the two.
class Z7(object):
def __init__(self, x):
self.x = x
def __eq__(self, other):
return self.x == other.x
def __ne__(self, other):
return self.x % 7 != other.x % 7
This lets us make a three-way distinction between two objects: numbers that are exactly equal (==
returns True
), numbers that are equal modulo 7 (==
and !=
return False
), and numbers that are unequal modulo 7 (!=
returns True
).
if x == y:
# E.g. Z7(3) == Z7(3)
print("x and y are identical)"
elif x != y:
# E.g. Z7(3) != Z7(5)
print("x and y are unalike")
else:
# Neither are true, so thy must be similar
# E.g. Z7(3) and Z7(10)
print("x and y are similar")
This doesn't use the 4th possibility, where ==
and !=
both return True
, which I cannot think of a good use for.
Upvotes: 1
Reputation: 76184
"no implied relationships" means that when you use "!=", if you haven't implemented __ne__
, it's not going to instead call __eq__
and negate the result. It will use the __ne__
method inherited from its parent. Most of the time, this will resolve to object.__ne__
which only checks for referential equality.
>>> class Fred:
... def __eq__(self, other):
... print "eq was called!"
... return False
...
>>> x = Fred()
>>> print x == 23
eq was called!
False
>>> #if eq and ne had an implied relationship,
>>> #we'd expect this next line to also print "eq was called!"
>>> print x != 23
True
>>> #... but it doesn't.
It also means that you're free to define __eq__
and __ne__
in ways that seem mathematically contradictory. Python won't hold your hand.
>>> class Fred:
... def __eq__(self, other):
... return True
... def __ne__(self, other):
... return True
...
>>> x = Fred()
>>> print x == 23
True
>>> print x != 23
True
Although it does suggest that you should implement them in a mathematically sensible way. The above code block is legal, but not wise.
Upvotes: 3