Circular (Cyclical) References in Python with Example

Table of Contents

Introduction

When we create any object in memory Python memory manager keeps track of number of references to those objects.

As soon as reference count becomes zero to any object, Python memory manager destroys that object and reclaims memory. To know more about this read: Reference Counting.

BUT!

Tracking reference count and destroying object as soon as count becomes zero does not always work as expected due to circular references.

Example

Circular references is a situation in which variable in object A is referencing object B & variable in object B is referencing back to object A.

Circular References in Python
Figure: Circular References in Python

Python Source Code: Circular References


class A:
    def __init__(self):
        self.var_a = B(self)
        print("A: {0}, var_a: {1}".format(id(self), id(self.var_a)))

class B:
    def __init__(self, obj):
        self.var_b = obj
        print("B: {0}, var_b: {1}".format(id(self), id(self.var_b)))

var = A()

Output

B: 2040344747528, var_b: 2040345400200
A: 2040345400200, var_a: 2040344747528

Observe id of A, B, var_a and var_b

In this case, reference counting is not going to destroy object A and object B beacause their reference count is non-zero and this is known as Circular References.

Python memory manager cannot destroy these objects leading to Memory Leak.

And, that is where Garbage Collector comes into play. Garbage collector is able to detect circular references and cleans them up eliminating memory leak.