+ 3
[Solved. Garbage collection.] Why first id() again?
I don't understand this behavior. Does anyone else? Please cite sources if possible. https://sololearn.com/compiler-playground/c968j9DmVWid/?ref=app
5 Answers
+ 6
As far as I know functions are objects in Python.
https://realpython.com/lessons/object-value-vs-object-identity/#:~:text=In%20Python%2C%20every%20object%20that,in%20which%20their%20lifetimes%20overlap.
"In Python, every object that is created is given a number that uniquely identifies it. It is guaranteed that no two objects will have the same identifier during any period in which their lifetimes overlap."
https://www.digitalocean.com/community/tutorials/python-id
"Two objects with non-overlapping lifetimes may have the same id() value."
From this I conclude that the first function is swallowed by the garbage collector after the same function has been created a third time.
If the first function still existed in memory, the third function would otherwise have to be given a new id.
However, I find the question of why all three functions are not given the same id more interesting.
+ 5
# an extended version
for i in range(10):
def fun():
pass
print(f"{i} -- {id(fun)}")
I could imagine that Python 1. puts the new definition in memory and then 2. checks if there is a collision with another function (and then overwrites the reference). That would explain why there are 2 different ids.
+ 4
We should also consider that we tested a rather simple case, so it may not be as reliable in larger or more complex programs.
+ 3
Denise RoĂberg ,
Gotcha.
I think for all three objects to have the same id, garbage collection would have to interrupt the assignment, delete the previous object, garbage collect it, make the memory available again, and continue the assignment. That kind of oversight would require a constantly running "watcher" routine capable of interrupting any operation, which would slow everything down.
However, I modified Lisa's loop to add an explicit del() statement (which removes one reference, the only reference in this case), and it reused the same id all 10 times as you were imagining. Garbage collection was able to make the no-longer-referenced memory available again between the del statement and the next loop iteration without needing to interrupting any operation.
# reuse same id
for i in range(10):
def fun():
pass
print(f"{i} -- {id(fun)}")
del(fun)
+ 2
Lisa ,
Thanks for the extended test. I see that the two id numbers keep getting reused.
That proves that, at least in the CPython implementation (used by Sololearn, Pydroid 3, and probably the majority of places), garbage collection is both fast and efficient.
From what I had previously read on python.org, I thought garbage collection was unreliable, and I didn't even think to consider it.
"An implementation is allowed to postpone garbage collection or omit it altogether â it is a matter of implementation quality how garbage collection is implemented, as long as no objects are collected that are still reachable." -- https://docs.python.org/3/reference/datamodel.html#objects-values-and-types
Now I know it's good in CPython.