Open AI - Opting Out
Open AI - Opting Out

Reputation: 24133

Does comparing using `==` compare identities before comparing values?

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 calls x.__eq__(y)

which doesn't tell me whether anything is done before calling x.__eq__(y).

Upvotes: 3

Views: 146

Answers (2)

jonrsharpe
jonrsharpe

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) and x.__hash__() returns an appropriate value such that x == y implies both that x is y and hash(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

publysher
publysher

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

Related Questions