Fundamentals 12 min read

Understanding Python Object Memory Management and Garbage Collection

This article explains Python's memory management, covering object references, identity via id(), reference counting, caching of small objects, the use of the is operator, handling of reference cycles with objgraph, manual reference deletion, and the generational garbage collection mechanism including thresholds and cycle detection.

Python Programming Learning Circle
Python Programming Learning Circle
Python Programming Learning Circle
Understanding Python Object Memory Management and Garbage Collection

Memory management is a crucial aspect of language design, directly affecting performance. Using Python as an example, this article explores how a dynamic, object‑oriented language handles memory.

In Python, assignment creates a reference to an object rather than copying the object itself. For instance, the integer a = 1 creates an integer object 1 and a reference a that points to it. The built‑in id() function returns the object's identity, which corresponds to its memory address:

a = 1
print(id(a))
print(hex(id(a)))

Python caches small integers and short strings, so multiple variables assigned the same small value actually reference the same object. This can be observed with the is operator:

# True
a = 1
b = 1
print(a is b)

# True
a = "good"
b = "good"
print(a is b)

# False
a = "very good morning"
b = "very good morning"
print(a is b)

# False
a = []
b = []
print(a is b)

Each object in Python maintains a reference count. The sys.getrefcount() function reveals this count, noting that passing the object as an argument temporarily increments the count by one:

from sys import getrefcount
a = [1, 2, 3]
print(getrefcount(a))
b = a
print(getrefcount(b))

Container objects (lists, dictionaries, etc.) store references to their elements rather than the elements themselves. A custom class can also hold references to other objects:

class from_obj(object):
    def __init__(self, to_obj):
        self.to_obj = to_obj

b = [1, 2, 3]
a = from_obj(b)
print(id(a.to_obj))
print(id(b))

When an object is referenced multiple times, its reference count increases accordingly:

a = [1, 2, 3]
print(getrefcount(a))
b = [a, a]
print(getrefcount(a))

Reference cycles—objects that reference each other—can create complex topologies. The third‑party objgraph package can visualize these relationships:

x = [1, 2, 3]
y = [x, dict(key1=x)]
z = [y, (x, y)]
import objgraph
objgraph.show_refs([z], filename='ref_topo.png')

Removing references reduces the reference count. The del statement can delete a variable or an element inside a container:

from sys import getrefcount
a = [1, 2, 3]
b = a
print(getrefcount(b))

del a
print(getrefcount(b))

# Delete an element from a list
a = [1, 2, 3]
del a[0]
print(a)

Reassigning a reference also decreases the original object's count:

from sys import getrefcount
a = [1, 2, 3]
b = a
print(getrefcount(b))
a = 1
print(getrefcount(b))

Python employs a garbage collector that activates when the number of allocated objects exceeds a threshold. The gc.get_threshold() function shows these values (default (700, 10, 10) ), and they can be adjusted with gc.set_threshold() :

import gc
print(gc.get_threshold())

gc.set_threshold(700, 10, 5)

Python’s garbage collection uses a generational strategy, dividing objects into three generations (0, 1, 2). New objects start in generation 0; objects that survive collections are promoted to older generations. The thresholds control how often collections of older generations occur (e.g., every 10 collections of generation 0 trigger a generation 1 collection).

Reference cycles pose a challenge because reference counting alone cannot reclaim them. Python’s collector breaks cycles by temporarily copying reference counts ( gc_ref ) and decrementing them for each referenced object, then freeing objects whose adjusted count reaches zero.

a = []
b = [a]
a.append(b)

del a

del b

In summary, Python separates objects from their references, uses reference counting as the primary memory‑management mechanism, caches small immutable objects, and supplements counting with a generational garbage collector to handle cycles and control memory usage efficiently.

Memory ManagementPythonGarbage CollectionReference CountingGenerational GC
Python Programming Learning Circle
Written by

Python Programming Learning Circle

A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.