Reputation: 7411
Suppose I have the following program:
class A(object):
def __eq__(self, other):
return True
a0 = A()
a1 = A()
print a0 != a1
If you run it with Python the output is True
. My question is
__ne__
method is not implemented, does Python fall on a default one?__eq__
and then negate the result?Upvotes: 6
Views: 348
Reputation: 176
[if] the
__ne__
method is not implemented, does Python fall on a default one?
Generally speaking, yes, it does - but the point is: what the behavior of the default __ne__
is. And that depends on the version of Python (please read on).
if Python fall on a default method to determine whether two objects are equal or not, shouldn't it call
__eq__
and then negate the result?
self != other
, if no custom __ne__
is provided by self
or other
then only object identities are checked (so the effective behavior is equivalent to self is not other
).__ne__
calls __eq__
and negates the result (but on the technical level there are some subtleties, please read on).__ne__
returns NotImplemented
Each of the Python's “rich comparison” methods, including __ne__
, can either give a resolute answer (typically: True
or False
) or say I don't know! by returning a special singleton object, NotImplemented
(warning: not to be confused with NotImplementedError
!).
On self != other
, first self.__ne__(other)
is called, and if it returns NotImplemented
then Python tries other.__ne__(self)
(however, if the type of other
is a subclass of the type of self
but not the same type then the order is reverse: other.__ne__(self)
is called first, and only if it returns NotImplemented
the self.__ne__(other)
call is tried). If both calls returned NotImplemented
then Python falls back to an object-identity-based check (self is not other
).
The behavior related to ==
and __eq__
is analogous.
That's what is referred to by the docs in the fragment:
__eq__()
and__ne__()
are their own reflection
Note: this fragment should be understood as: __eq__()
is its own reflection and __ne__()
is its own reflection (each on its own, separately).
As Ami Tavory wrote, when it comes to the standard behavior and default implementations, there are no implied relationships between __ne__
and __eq__
.
From the docs:
For
__ne__()
, by default it delegates to__eq__()
and inverts the result unless it isNotImplemented
.
In other words, the behavior of object.__ne__
is (roughly) equivalent to:
def __ne__(self, other):
res = self.__eq__(other)
if res is NotImplemented:
return NotImplemented
return not res
Of course, object.__ne__
can be shadowed by another implementation provided by a subclass. That's why, when you implement a subclass of, for example, dict
, if you want to provide your customized __eq__
you also need to provide __ne__
(whose implementation can be just as in the above code snippet, or even shorter: return object.__ne__(self, other)
).
Upvotes: 1
Reputation: 76366
From the docs:
There are no implied relationships among the comparison operators. The truth of
x==y
does not imply thatx!=y
is false. Accordingly, when defining__eq__()
, one should also define__ne__()
so that the operators will behave as expected.
Upvotes: 12