In [1]: a = 5
In [2]: b = a
In [3]: a is b
Out[3]: True
In [4]: c = 5
In [5]: a is c
Out[5]: True
They behave differently when they are inside a tuple:
In [6]: a = (5,)
In [7]: c = (5,)
In [8]: a is c
Out[8]: False
In [9]: a == c
Out[9]: True
Similar behaviour for strings:
In [10]: 'foo' is 'foo'
Out[10]: True
In [11]: a, c = 'foo', 'foo'
In [12]: a is c
Out[12]: True
In [13]: a, c = ['foo'], ['foo']
In [14]: a is c
Out[14]: False
In [15]: a == c
Out[15]: True
is
compares the actual memory locations, so if they are indeed the
same object, they will be equal. Whereas if they are merely equal,
they will won't be.
In [16]: id(a) == id(c)
Out[16]: False
In [17]: id(a), id(c)
Out[17]: (140582292221704, 140582291823496)
In [18]: a, c = 'foo', 'foo'
In [19]: id(a) == id(c)
Out[19]: True
In [20]: id(a), id(c)
Out[20]: (140582907670120, 140582907670120)
In [21]: 1.2 is 1.2
Out[21]: True
In [22]: a, c = 1.2, 1.2
In [23]: a is c
Out[23]: False
In [24]: id(a), id(c)
Out[24]: (140582332253240, 140582332253336)
In [25]: b = a
In [26]: a is a
Out[26]: True
Floats behave more reasonably, this is because int
and str
are
optimised to always be represented by the same memory location if the
values are equal. So two completely unrelated integers, if they are
both 5, then they will pass the is
-test. Similarly for floats, when
two identical "literals" are compared (as in line 21 above), they are
again represented by the same memory location and pass the test, but
fail when they are compared after assigning to variables (line 22-23).