1

I guess I am missing something here, but when I am doing forcefully garbage collection using gc.collect(), I shouldn't be able to access id(10) since that is not being referenced by any of the variable and even if i assume that id(10) call is creating the variable, is it creating at the same location? that is wierd

import gc
import time

x = 10
y = x
print('10 id is: ', id(10))
print('x id is: ',id(x))
print('y id is: ',id(y))

x = x+1
y = 11
print('x id is: ',id(x))
print('y id is: ',id(y))
# above is justified
gc.collect(generation=2)
time.sleep(2)
print(id(10))
# but how come is above statement giving the value of id(10) as earlier?

When I run this snippet:

line1: 10 id is:  140709303001776
line2: x id is:  140709303001776
line3: y id is:  140709303001776
line4: x id is:  140709303001808
line5: y id is:  140709303001808
line6: 140709303001776

so how come in line6, i am able to get the id(10) as the same I had allocated earlier, since now x and y are pointing to different memories and I have garbage collected before printing line6

Please help me in this snippet as to how is the memory allocation working as this got me confused.

Tushar Seth
  • 563
  • 7
  • 15
  • Small integers are cached (unique). See e.g. https://stackoverflow.com/questions/15171695/whats-with-the-integer-cache-maintained-by-the-interpreter . If you try with bigger numbers, you should see the id changing. – Demi-Lune Feb 05 '20 at 10:18

2 Answers2

1

Maybe the python interpreter itself or an imported module also has a variable with the value 10. So there some more references to to the value 10. I extended your snippet to prove that:

import gc
import time
import sys

x = 10
y = x
print('10 id is: ', id(10))
print('x id is: ',id(x))
print('y id is: ',id(y))
print("References to 10:", sys.getrefcount(10))

x = x+1
y = 11
print('x id is: ',id(x))
print('y id is: ',id(y))

gc.collect(generation=2)
time.sleep(2)
print("References to 10:", sys.getrefcount(10))
print(id(10))

Output on my machine:

10 id is:  140076230383168
x id is:  140076230383168
y id is:  140076230383168
References to 10: 20
x id is:  140076230383200
y id is:  140076230383200
References to 10: 18
140076230383168
bb1950328
  • 1,403
  • 11
  • 18
  • thanks @sadap that is one logical reason which i could also reproduce in my machine. But when I tried with random large numbers, or random long strings, its always giving refcount as 3. . This seems very wierd as if I am creating a lot of different strings, and at some point I decide to garbage collect the strings used till some point, i would not be able to do that – Tushar Seth Feb 05 '20 at 10:51
0

For efficiency Python has small integers (from -5 to 256 inclusive) in a cache, so they are never allocated again when needed. You can read about it in this question and its accepted answer: What's with the integer cache maintained by the interpreter?

One good way to check if the value is cached is doing a is (a - 1 + 1), it will be True only if value of a is cached.

  • by which I mean CPython from python.org, other implementations might do things differently, especially something gc related which doesn't affect usual Python code semantics.