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

12

The two forms below return True , but what are the consequences of this in a more complex code?

>>> a = '2'
>>> a is '2'  
>>> True
>>> a == '2' 
>>> True
    
asked by anonymous 24.10.2014 / 23:44

3 answers

20

The consequences depend on the purpose of the code. is and == are not synonyms, and can not simply be changed as if they were.

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

  • The 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)

  • == compares the content stored in 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 to take into account the differences between the two operators, so that the code behaves as expected. For this, a more detailed explanation on each one follows:


The is operator:

In Python, the is operator is the instance comparator of objects, not values .

For example:

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

Returns

False

Although the values are the same, they are completely different objects.


is and strings

Do not be fooled by this example:

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

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

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 a certain implementation-specific quirk: when you use numbers from -5 to 256, Python already has an internal storage table, whose objects are already natively created and their ID is taken advantage of.


The == operator:

== is the comparator of values, as in most languages. The object may be different, what matters for the comparison is the value:

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

Return:

True

The function id() :

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

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


Comparing with None :

None is a special object in Python, and represents the absence of value, in a way like null of some languages. Because it is an object that represents absence, not a value per se, you should always use x is None and x is not None , and never x == None and x != None .

Warning 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 ) , imagining that None would already be considered false. Just as value comparison should not be used with None , in if 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 must be fully aware of the differences mentioned above. Roughly, 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 
    
25.10.2014 / 00:42
7

Bacco's answer is supercomplete, but for anyone who wants a more concise answer:

The is is to compare if two things are exactly the same object in the computer's RAM.

While == compares in depth to the content of objects. So if two objects in different places in memory have the same content, == will detect equality, while is will not.

    
25.10.2014 / 02:09
2

A code is worth a thousand words.

class Pessoa(object):
    def __init__(self, nome, idade):
        self.nome = nome
        self.idade = idade

joao = Pessoa("João Bom de Python", 16) # 0x1
alex = Pessoa("Alex Java", 23) # 0x2
clone_alex = alex # 0x2

print joao is alex # 0x1 == 0x2
print clone_alex is alex # 0x2 == 0x2

One more, I'm excited:

>>> x = [1, 2, 3] # 0xC
>>> y = [1, 2, 3] # 0x18
>>> x is y # 0xC == 0x18
False
>>> x = y
>>> x is y # 0x18 == 0x18
True

Note: The addresses are explanatory.

    
25.10.2014 / 06:35