Skip to main content
๐Ÿ“œ WAYPOINT LESSON

Refcounting, cycles, weakref

โญโญโญ advancedโณ 20 min read๐Ÿ“ Lesson 136 of 169

Explain and diagnose memory behavior instead of fearing it.

Reference counting and the garbage collector

CPython's primary memory management is refcounting: every object counts its references; hitting zero frees it immediately (hence the instant __del__-less determinism CPython is known for).

Refcounting alone cannot free cycles (aโ†’bโ†’a). A supplementary cycle detector โ€” the generational gc module โ€” periodically scans container objects for unreachable cycles:

import gc, sys

class Node:
    def __init__(self):
        self.partner = None

a, b = Node(), Node()
a.partner, b.partner = b, a
del a, b                       # refcounts never hit zero โ€” cycle!
gc.collect()                   # cycle detector frees them

Practitioner takeaways:

  • sys.getrefcount(x) shows the count (always +1 for the argument itself).
  • Most "memory leaks" in Python are reference leaks: caches, registries, closures, or loggers holding objects forever. Find them with gc.get_referrers(obj) โ€” who still points at this?
  • gc.garbage collects objects the collector could not free (usually __del__-bearing cycles) โ€” its growth is a design smell.
  • weakref lets a cache reference objects without keeping them alive โ€” the standard fix for registry-induced leaks.
  • gc.disable() can speed allocation-heavy batch jobs slightly, at the cost of cycle leaks โ€” measure before adopting.

โšก Now practice

Ready to Code
Memory PracticeWeakrefs that let go: a cache that never leaks, verified with gc counts.
1 challenge ยท ยท ~20 min