GC (garbage collection) and reference counters in Python

This is a personal note on some useful notations for using python. I’m not going to cover the basics, and I’m limiting this to things I’ve found useful.

github

  • The jupyter notebook format file on github is here.

google colaboratory

  • If you want to run it on google colaboratory here 009/009_nb.ipynb)

Author’s environment

sw_vers
ProductName: Mac OS X
ProductName: Mac OS X
ProductVersion: 10.14.6
BuildVersion: 18G103
Python -V
Python 3.8.5

GC and getrefcount

I had a chance to do a lot of work on GC conditions, so I’ll leave this as a note.

Basically, python uses garbage collection, which means that objects that are no longer needed are automatically released without explicitly releasing memory like in C and C++. The reference counter is what makes this possible. Every object has a reference counter built in, and when there is a reference from another object to that object, the reference counter is incremented. When a reference from another object to that object is received, the reference counter is incremented, and when the reference is deleted, it is decremented, and when the counter reaches zero, the object is released.

I’ve never paid much attention to the reference counter, but this time I analyzed a lot of things based on this number, so I’ll just record the summary.

import sys

class A():
  def __init__(self, a, b):
    self.a = a
    self.b = b

The object is created and also referenced from sys.getrefcount, so the reference counter is 2.

a = A('a', 1)
sys.getrefcount(a)
2

This is 3 because it is also referenced by b.

b = a
sys.getrefcount(a)
3

Remove b to get 2.

b = None
sys.getrefcount(a)
2

References to instance variables are not incremented.

c = a.b
sys.getrefcount(a)
2

GC

Normally, GC does gc.collet() explicitly after del. However, the value is not removed from memory after del, it’s just not available to python.

import gc

b = A('b', 2)
del b

print(gc.get_stats()[2])
gc.collect()
print(gc.get_stats()[2])
{'collections': 3, 'collected': 664, 'uncollectable': 0}
{'collections': 4, 'collected': 810, 'uncollectable': 0}

After gc, you can’t get the reference counter.

sys.getrefcount(b)
---------------------------------------------------------------------------

NameError Traceback (most recent call last)

<ipython-input-31-e0d8d1240a7d> in <module>
----> 1 sys.getrefcount(b)


NameError: name 'b' is not defined

Reference article