CPython "internalizes" small integers and small strings as an optimization. AFAIK, this is not a part of the language, but of this specific implementation.
When CPython starts, a range of integers objects will be created even though your program hasn't referenced them.
So every time you say e.g. s = 5
, the s
variable just becomes a reference to the pre-allocated integer object 5
.
For example:
In [14]: for i in range(10):
...: print(i, id(i))
...:
0 34375408656
1 34375408688
2 34375408720
3 34375408752
4 34375408784
5 34375408816
6 34375408848
7 34375408880
8 34375408912
9 34375408944
These ID's stay the same, even in different CPython sessions. (This is on 64-bit UNIX; the numbers might be different on other machines. But even there they should be the same in different CPython sessions)
Compare:
In [1]: s = "hello there"
Out[1]: 'hello there'
In [2]: id(s)
Out[2]: 34513947376
In [3]: id("hello there")
Out[3]: 34517432752
In [4]: id("hello there")
Out[4]: 34527873968
In [5]: id("hello there")
Out[5]: 34518225712
In [6]: id("hello there")
Out[6]: 34512957808
Apparently, the string hello there
is too long for this internalization mechanism, so every instance is a new one.