object().__eq__ returns the NotImplemented singleton:
print(object().__eq__(3))
NotImplemented
By the reflexive rules of rich comparisons, when NotImplemented is returned, the "reflected" operation is tried. So if you have an object on the RHS that returns True for that comparison, then you can get a True response even though the LHS did not implement the comparison.
class EqualToEverything(object):
def __eq__(self,other):
return True
ete = EqualToEverything()
ete == object() # we implemented `ete.__eq__`, so this is obviously True
Out[74]: True
object() == ete # still True due to the reflexive rules of rich comparisons
Out[75]: True
python 2 specific bit: if neither object implements __eq__, then python moves on to check if either implement __cmp__. Equivalent reflexive rules apply here.
class ComparableToEverything(object):
def __cmp__(self,other):
return 0
cte = ComparableToEverything()
cte == object()
Out[5]: True
object() == cte
Out[6]: True
__cmp__ is gone in python 3.
In both python 2 and 3, when we exhaust all of these comparison operators and all are NotImplemented, the final fallback is checking identity. (a is b)
__eq__with a sentinel. If you want to check if something is the sentinel, python already provides theisoperator which cannot be overloaded and thus it's the perfect choice for checking these kind of things. Use==only when you don't really care for identity, but for equality (and this is not generally true when using a sentinel value...)class MySentinel(): pass, but just realized that I could probably justMySentinel = object(). Thanks @Marcin and @Buttons840 for confirming my idea.