Garbage Collection and Cyclic References

RoadmapsPython

Overview

Python manages memory automatically using reference counting. Every object keeps a count of how many labels point to it, and when the count drops to zero, the object is immediately destroyed. Think of reference counting as returning a library book as soon as you finish reading it, and the garbage collector as the librarian sweeping the building at night for abandoned books. A cyclic reference occurs when objects point to each other (e.g., node `A` points to `B`, and `B` points to `A`). Reference counting cannot clean these up because their counts never reach zero even when no external variables point to them. To solve this, a background process called the garbage collector (using the `gc` module) periodically scans for unreachable cycles and destroys them. When testing memory management, you can use `sys.getrefcount()` to inspect an object's current reference count. Be aware of this common debugging trap: the count is always one higher than you expect because passing the object to the function creates a temporary reference. import sys my_list = [1, 2, 3] # Returns 2, not 1. The 'my_list' argument creates a temporary reference! print(sys.getrefcount(my_list))

It prevents memory leaks in long-running applications without requiring developers to manually allocate and free memory.

Where used: FastAPI background tasks, Celery workers, Data processing scripts

Why learn this

Code walkthrough

import sys

x = []
print(sys.getrefcount(x))
y = x
print(sys.getrefcount(x))

del y
print(sys.getrefcount(x))

Focus: del y

Common mistakes

Glossary

reference counting
A method of memory management where Python keeps track of how many times an object is being used. Example: `sys.getrefcount(obj)`
memory leaks
When a program fails to release memory that it no longer needs, eventually causing the system to run out of memory. Example: storing unused data in a global cache.

Recall questions

Understanding checks

What is the output of this code?

True

When `a` and `b` are deleted, their reference counts drop to `1` (because they point to each other). `gc.collect()` finds this unreachable cycle, cleans it up, and returns the number of collected objects, which is greater than `0`.

If you delete a variable using `del x`, does it immediately free the memory?

Not necessarily. It only decrements the reference count.

`del x` removes the label `x` and decrements the object's reference count by `1`. The object is only destroyed and its memory freed if that count reaches `0`.

Practice tasks

Break a cycle

The provided code creates a cyclic reference between a `parent` and `child` node. Modify the code to manually break the cycle before the end of the script so that reference counting alone can clean them up.

Challenge

Analyze Reference Counts

Create a list `a` and append it to itself. Then delete the label `a`. This creates a cyclic reference. Use the `gc` module to force a collection and print the number of collected objects.

Continue learning

Previous: Object identity: id() and memory references

Previous: Mutable vs immutable objects

Return to Python Roadmap