pythonpython-2.7containment

Does the 'in' operator use "==" or "is" for comparisons?


In a Python expression like str in [str1, str2, str3] or 1 in [1, 2, 3], does the in operator use == or is to compare the first object with the objects in the list?


Solution

  • It depends on the object how in is executed; it is not the in operator that makes the comparison, it is the object.__contains__ method that does the work.

    For the Python standard container types (list, tuple, set, dict, etc.) both identity and equality are used. See the Membership test operations section of the Expressions reference documentation:

    For container types such as list, tuple, set, frozenset, dict, or collections.deque, the expression x in y is equivalent to any(x is e or x == e for e in y).

    is is faster to test for, and objects having the same identity implies they are also equal.

    Custom types are free to implement whatever test they want to do in their __contains__ method.

    Next, if no __contains__ method is defined, but there is a __iter__ method or a __getitem__ method, then an iterative search is preformed where the values produced are tested for both identity and equality again. See the above linked documentation for details; the documentation is not that explicit about the identity test but the implementation still uses identity because using it is a performance boost.

    You can see this when you use float('nan'), which is never equal to itself or anything else:

    >>> nan = float('nan')
    >>> nan == nan
    False
    >>> nan is nan
    True
    >>> nan in [nan]  # tests for identity first
    True
    >>> nan in iter([nan])  # an iterator, only __iter__ is defined
    True
    

    float('nan') is an exception to the normal expectation that identity implies equality; see What is the rationale for all comparisons returning false for IEEE754 NaN values? for why that is.