Python manages memory with two mechanisms working together, not one. The primary mechanism is reference counting: every object tracks how many references point to it, and the moment that count hits zero, CPython frees the object immediately — no separate collection pass, no pause, no scheduling involved.

Reference counting alone has one well-known blind spot: reference cycles. If object A holds a reference to object B, and object B holds a reference back to object A, their reference counts never reach zero even after nothing outside the cycle can reach either of them — each is still referencing the other. A pure reference-counting system would leak that memory forever.

That's what Python's second mechanism, the generational cycle collector, exists to catch. It runs periodically, independent of reference counting, and specifically looks for groups of objects that reference each other but aren't reachable from anywhere else in the program — exactly the cycle case reference counting can't resolve on its own.

"Generational" describes how the collector prioritizes its work: new objects start in generation 0, and any object that survives a collection pass gets promoted to the next generation. Generation 0 is collected most frequently, generation 2 least frequently, on the assumption — true for most real programs — that most objects are short-lived, so scanning young objects often and old objects rarely is more efficient than scanning everything on every pass.

This two-mechanism design is why Python code rarely needs to think about memory management directly, but it also explains a specific and sometimes surprising gotcha: an object's __del__ method isn't guaranteed to run at any predictable moment if that object is part of a reference cycle, since it's freed whenever the cycle collector happens to run, not the instant it becomes unreachable. Code relying on precise __del__ timing for cleanup is generally safer using a context manager instead.

Python's own documentation covers both mechanisms directly — the gc module documentation for controlling and inspecting the cycle collector, and the C API documentation on reference counting for the lower-level mechanics — for anyone who wants the tunable thresholds and full behavior beyond this overview.