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
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
The consequences depend on the purpose of the code. is
and ==
are not synonyms, and can not simply be changed as if they were.
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:
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.
==
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
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
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
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
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.
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.