I have been playing with Python these days, and I realize some interesting way how Python assign id(address) to new instance (int and list).
For example, if I keep call id function with a number (or two different number), it return the same result. e.g.
>>> id(12345)
4298287048
>>> id(12345)
4298287048
>>> id(12345)
4298287048
>>> id(12342) #different number here, yet still same id
4298287048
Also when I declare the variable first and then call id() with it, the results are alternating like this.
>>> x = []; id(x)
4301901696
>>> x = []; id(x)
4301729448
>>> x = []; id(x)
4301901696
>>> x = []; id(x)
4301729448
Can someone please explain the Python work behind this? Also, is there a book or a site where I can read about this part of Python (assigning memory address, behind scene work, etc) since there is little I can find from python documentation
You are creating a new object without any other references and Python re-uses the memory location when the object is destroyed again after id()
is done with it. In CPython, the result of id()
happens to be the memory location of the object. From the id()
function documentation:
CPython implementation detail: This is the address of the object in memory.
The line id(12345)
creates a new int()
instance; because it is bound as an argument to id()
it has 1 reference to it. id()
determines the memory location, and returns that result. In returning, the arguments are cleaned up and the reference count to the int()
instance drops to 0, and Python cleans it up. The memory is freed.
The next line creates a new int()
instance. There is memory available at the same location, so it is reused.
When, instead, you first bind the new object no a name, you created an extra reference to the object and it is not cleared up. The memory is not freed, and a new object will have to use a new memory address.
This part too is documented, again from the id()
documentation:
This is an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same
id()
value.
Emphasis mine.
When rebinding (x = []
when x
is already set) Python first creates a new object, then rebinds x
to point to that new object. This unbinds the old list after the new list is created. This means the old memory location is still occupied when the new list object is created.
To map that out to specific steps:
id() == 4301901696
.4301901696
is bound to x
-> Reference count for 4301901696
is 1.id() == 4301729448
.4301901696
is unbound from x
. Reference count for 4301901696
drops to 0 and is cleared from memory.4301729448
is bound to x
. Reference count for 4301729448
is 1.4301901696
is empty so the new object gets id() == 4301901696
.4301729448
is unbound from x
. Reference count for 4301729448
drops to 0 and is cleared from memory.4301901696
is bound to x
. Reference count for 4301901696
is 1.This too is part of the documentation, the assignment statement documenation tells you what order assignment takes place in:
An assignment statement evaluates the expression list [...] and assigns the single resulting object to each of the target lists, from left to right.
where expression list is everything on the right-hand-side of the =
symbol.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With