Circular (Cyclical) References in Python with Example
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.
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.