Reputation: 24133
If I compare two variables using ==
, does Python compare the identities, and, if they're not the same, then compare the values?
For example, I have two strings which point to the same string object:
>>> a = 'a sequence of chars'
>>> b = a
Does this compare the values, or just the ids?:
>>> b == a
True
It would make sense to compare identity first, and I guess that is the case, but I haven't yet found anything in the documentation to support this. The closest I've got is this:
x==y
callsx.__eq__(y)
which doesn't tell me whether anything is done before calling x.__eq__(y)
.
Upvotes: 3
Views: 146
Reputation: 121975
For user-defined class instances, is
is used as a fallback - where the default __eq__
isn't overridden, a == b
is evaluated as a is b
. This ensures that the comparison will always have a result (except in the NotImplemented
case, where comparison is explicitly forbidden).
This is (somewhat obliquely - good spot Sven Marnach) referred to in the data model documentation (emphasis mine):
User-defined classes have
__eq__()
and__hash__()
methods by default; with them, all objects compare unequal (except with themselves) andx.__hash__()
returns an appropriate value such thatx == y
implies both thatx is y
andhash(x) == hash(y)
.
You can demonstrate it as follows:
>>> class Unequal(object):
def __eq__(self, other):
return False
>>> ue = Unequal()
>>> ue is ue
True
>>> ue == ue
False
so __eq__
must be called before id
, but:
>>> class NoEqual(object):
pass
>>> ne = NoEqual()
>>> ne is ne
True
>>> ne == ne
True
so id
must be invoked where __eq__
isn't defined.
You can see this in the CPython implementation, which notes:
/* If neither object implements it, provide a sensible default
for == and !=, but raise an exception for ordering. */
The "sensible default" implemented is a C-level equality comparison of the pointers v
and w
, which will return whether or not they point to the same object.
Upvotes: 6
Reputation: 11372
In addition to the answer by @jonrsharpe: if the objects being compared implement __eq__
, it would be wrong for Python to check for identity first.
Look at the following example:
>>> x = float('nan')
>>> x is x
True
>>> x == x
False
NaN is a specific thing that should never compare equal to itself; however, even in this case x is x
should return True
, because of the semantics of is
.
Upvotes: 3