← Back to Chapters

Python Memory Management

? Python Memory Management

? Quick Overview

Python manages memory for you using a combination of heap allocation, reference counting, and a garbage collector for cleaning up unused objects. Understanding how memory works helps you write faster, safer programs and avoid memory leaks.

? Key Concepts

  • Objects on the heap – every value in Python is an object stored on a managed heap.
  • Names are references – variables are labels pointing to objects, not the objects themselves.
  • Reference counting – Python tracks how many references point to an object.
  • Garbage collection – the gc module cleans up unreachable objects (e.g., reference cycles).
  • Mutability – lists, dicts, sets are mutable; ints, floats, strings, tuples are immutable.
  • Memory leaks – can happen when references to unused objects are accidentally kept alive.

? Syntax and Theory

Important tools for inspecting and controlling memory in Python:

  • id(obj) – returns a unique identifier for the object (often its memory address).
  • sys.getrefcount(obj) – shows how many references point to an object.
  • gc.collect() – manually trigger a garbage-collection run.
  • del name – remove a reference (name) to an object.
? View Code Example – Objects and References
import sys

a = [1, 2, 3]
b = a           # b references the same list object
c = a           # c also references the same list

print(id(a), id(b), id(c))      # all ids are the same
print(sys.getrefcount(a))       # reference count (a, b, c + internal temp refs)

del b                           # remove one reference
print(sys.getrefcount(a))       # reference count decreases

del a
del c                           # after this, the list has no references and can be freed
? View Code Example – Garbage Collection
import gc

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

# create a reference cycle
a = Node()
b = Node()
a.ref = b
b.ref = a

# break all external references
del a
del b

# the two Node objects reference each other,
# so reference counting alone can't free them.
# gc.collect() finds and frees them.
collected = gc.collect()
print("Unreachable objects collected:", collected)

? Live Output / Explanation

? What the examples show

  • The first example demonstrates that multiple variables can point to the same list object. Deleting a name only removes that reference, not the object itself.
  • sys.getrefcount() reveals how many active references exist for a given object.
  • The second example creates a reference cycle: two objects pointing to each other.
  • gc.collect() forces a garbage-collection pass that detects and frees such cycles.

? Tips and Best Practices

  • Reuse existing objects when possible instead of creating many short-lived large objects.
  • Close files, network connections, and database cursors promptly (use with blocks).
  • Avoid creating unnecessary global variables that live for the entire program lifetime.
  • Be careful with large lists or dictionaries that grow without being cleared.
  • Use tools like tracemalloc and profilers to investigate memory usage in large projects.

? Try It Yourself

  • Write a script that creates a large list (e.g., one million integers) and prints its size using sys.getsizeof().
  • Create two custom classes that reference each other, then break all external references and call gc.collect() to see how many objects are collected.
  • Experiment with tracemalloc to track which lines of code allocate the most memory in a small program.