CPython uses a mix of reference counting and a cyclic garbage collector.
1. Reference counting: Each object tracks how many references point to it. When the count hits zero, the object is deallocated immediately. 2. Cyclic GC: Reference counting alone cannot free reference cycles (a.x = b; b.y = a). The gc module periodically finds and collects unreachable cycles. 3. Allocators: Small objects often come from pymalloc arenas; larger allocations go to the system allocator. Free lists may reuse some object types (e.g. small ints historically, some containers). 4. Interning / caching: Some immutable values are shared (see interned strings / small ints).
import gc
import sys
a = []
b = []
a.append(b)
b.append(a)
del a, b
collected = gc.collect()
print("cycles collected:", collected)
x = "lakebench"
print(sys.getrefcount(x)) # includes temporary ref from the callImplications
- Most objects die promptly when references disappear.
- Long-lived caches and cycles can retain memory until GC runs.
__del__finalizers complicate cycle collection; avoid relying on them for critical resource cleanup (prefer context managers).
Other Python implementations (PyPy, Jython) may use different GC strategies.