In Python, what are the consequences of using 'is' instead of '=='

Question:

Both forms below return True , but what are the consequences for more complex code?

>>> a = '2'
>>> a is '2'  
>>> True
>>> a == '2' 
>>> True

Answer:

The consequences depend on the purpose of the code. is and == are not synonymous, and cannot simply be swapped as if they were.

What happens is that, in many situations, the two return the same value when substituted, giving the erroneous illusion that they behave in the same way, but the nature of the comparisons is completely different.

  • is checks whether the two names point to the same object stored in memory

    (Maria and Joana live in the same house, so they have the same address)

  • o == compares the content stored under each of the two names, regardless of whether they point to the same object or to different objects.

    (Maria's house is identical to José's house, same furniture, same color, etc.)

It is very important that the differences between the two operators are taken into account, so that the code behaves as expected. For this, a slightly more detailed explanation of each one follows:

The operator is :

In Python, the is operator is the object instance comparer, not values .

For example:

>>> x = [2, 3, 4]
>>> y = [2, 3, 4]
>>> x is y

Returns

False

because although the values ​​are the same, they are completely different objects.

is and strings

Don't be fooled by this example:

>>> x = "string"
>>> y = "string"
>>> x is y
True
>>> z = "str"+"ing"
>>> a is z
True

In this case, despite the impression that the comparison with is behaves identically to the one made with == , what is happening here is something else. Python is "smart" enough not to allocate repeated string values ​​multiple times, so it points the new object's name to the previously stored string , effectively leveraging the already allocated data.

Strings should normally be compared to == unless you know exactly what you are doing.

is and some integers

Look at the following example:

>>> x = 256
>>> y = 256
>>> x is y
True

>>> x = 257
>>> y = 257
>>> x is y
False

This is due to an implementation-driven quirk: when you use numbers from -5 to 256, Python already has an internal storage table whose objects are already created natively and its ID is leveraged.

The operator == :

The == is the value comparer, as in most languages. The object can be different, what matters for the comparison is the value:

>>> x = 1278
>>> y = 1278
>>> x == y

Returns:

True

The id() function:

If there is a need to debug a situation where the is does not behave as expected, you can use the id() function to obtain the internal ID of the objects, as in the following example:

>>> x = 257
>>> y = 257
>>> id(x)
12686128
>>> id(y)
12686140

Comparing to None :

None is a special object in Python, and represents the absence of a value, somewhat like the null in some languages. Because this is an absence object, not a value itself, you should always use x is None and x is not None , and never x == None and x != None .

Attention with this special case:

if ( x is None ):

In this case, a programmer experienced in other languages ​​might be tempted to simply use if ( x ) , thinking that None would already be considered false. Just as value comparison should not be used with None , in if the verification also requires is None or is not None

Implementing class comparison:

The methods that implement the is and == comparison in Python are respectively __is__ and __eq__ , in which case the programmer should be fully aware of the differences mentioned above. Roughly speaking, it's something along these lines:

# O exemplo foi simplificado demasiadamente ;)
class X(object):
    def __eq__(self, other):
        return self.value == other
    def __is__(self, other):
        return self.value is other 
Scroll to Top