In general, as soon as you use an integer or a string or any other literal, Python creates a new object in memory for you. It is guaranteed to have the same id
for the lifetime of the object, that is, while its reference count is not zero.
When you write something like:
>>> id(1000)
140497411829680
Python creates the integer 1000 and returns its id
(the memory address of the object in CPython). After this is done, the reference count of the integer object 1000 is zero and it is deleted. This ensures that you cannot keep filling memory just by writing id(something)
(and not binding any variable name to the object).
Typically, you cannot predict when reuse will happen, but in my Python shell it happens quite consistently:
>>> id(1000)
140697307078576
>>> id(1001)
140697307078576
>>> id(1002)
140697307078576
>>> id(1003)
140697307078576
You can see that the same memory address get used again and again when each new integer is created. However, if you prevent the reference count from dropping to zero, you can see that new memory is used instead:
>>> a = 1000
>>> id(a)
140697307078576
>>> b = 1001
>>> id(b)
140697306008368
In CPython, the integers -5 through to 255 are special cases in that they always exist (and so always have the same id
during a Python runtime). This is an optimisation to avoid repeated creation and destruction of commonly-used integers.