I was fiddling around with id recently and realized that (c?)Python does something quite sensible: it ensures that small ints always have the same id.
>>> a, b, c, d, e = 1, 2, 3, 4, 5
>>> f, g, h, i, j = 1, 2, 3, 4, 5
>>> [id(x) == id(y) for x, y in zip([a, b, c, d, e], [f, g, h, i, j])]
[True, True, True, True, True]
But then it occurred to me to wonder whether the same is true for the results of mathematical operations. Turns out it is:
>>> nines = [(x + y, 9) for x, y in enumerate(reversed(range(10)))]
>>> [id(x) == id(y) for x, y in nines]
[True, True, True, True, True, True, True, True, True, True]
Seems like it starts failing at n=257…
>>> a, b = 200 + 56, 256
>>> id(a) == id(b)
True
>>> a, b = 200 + 57, 257
>>> id(a) == id(b)
False
But sometimes it still works even with larger numbers:
>>> [id(2 * x + y) == id(300 + x) for x, y in enumerate(reversed(range(301)))][:10]
[True, True, True, True, True, True, True, True, True, True]
What’s going on here? How does python do this?
Python keeps a pool of
intobjects in certain numbers. When you create one in that range, you actually get a reference to the pre-existing one. I suspect this is for optimization reasons.For numbers outside the range of that pool, you appear to get back a new object whenever you try to make one.
Source
emphasis mine