1a = [1, 2]2b = a3del a4b = [3]5x = []; y = [x]6x.append(y)7del x, y8gc.collect()namesheapab[1, 2][3]xx's listyGCy's listfree(p)?never 0paused
Code card: the program; the highlighted line is the one runningNames and list objects; each list shows how many references point at itHeap: where objects live; arrows are referencesGC: the collector that finds and frees garbageEach step runs one line. A token hops from the line to the list it changes and the list's reference count crossfades; a list whose count reaches 0 fades away at once. Lines 5 to 7 leave two lists that refer only to each other: unreachable, yet each count stays at 1, until gc.collect() finds and frees the cycle. The last three steps rewind to line 7 in a tracing collector: no counts, mark what the roots can reach, sweep the rest. Reference counting is how CPython, the standard Python, works. Other Pythons differ: PyPy, for example, uses a tracing collector, so an object is not always freed the moment its last reference goes.

Giving memory back

  1. Line 1 makes a list. Python takes memory for it on the heap, the area that holds objects a program makes while it runs. The name a refers to it. Memory is limited, so it must be given back later.

Reference counting

Cycles

Mark and sweep

Try it in the Python prompt

;; step 1/12 · line 1: a = [1, 2]
>>> a = [1, 2]
>>> print(a)
[1, 2]
>>> import sys
>>> sys.getrefcount(a) - 1   # one reference: the name a
1

sys.getrefcount() reports one more than you might expect, because passing the object to the function adds a temporary reference. The counts in the figure subtract that one. Reference counting is how CPython, the standard Python, works. Other Pythons differ: PyPy, for example, uses a tracing collector, so an object is not always freed the moment its last reference goes.