Search code examples
pythonpython-3.xgarbage-collectioncircular-reference

Python garbage collection with nested class/circular references/reference cycle


I have the following nested structure:

#!/usr/bin/env python3

class InnerClass:
    def __init__(self, outer_class):
        self.outer_class = outer_class

    def __del__(self):
        print("Inner class deleted")


class OuterClass:
    def __init__(self):
        self.inner_class = InnerClass(self)

    def __del__(self):
        print("Outer class deleted")


def scope():
    oc = OuterClass()
    # include this line to see garbage collection working as intended
    # del oc.inner_class


scope()
print("Left scope, but instances were not garbage collected")
input("About to terminate program, you will see garbage collection right after")

Is there any way to get a nested structure like this to work with garbage collection? Or should such structures always be avoided?

Edit: Added better keywords as suggested by LeventeSimofi.


Solution

  • With the suggestion from Levente Simofi to use weak references, this works as intended:

    #!/usr/bin/env python3
    
    import weakref
    
    
    class InnerClass:
        def __init__(self, outer_class):
            self._outer_class_wr = weakref.ref(outer_class)
            print(f"Initialized inner class with outer class {outer_class}")
    
        @property
        def out_class(self):
            return self._outer_class_wr()
    
    
        def __del__(self):
            print("Inner class deleted")
    
    
    class OuterClass:
        def __init__(self):
            self.inner_class = InnerClass(self)
    
        def __del__(self):
            print("Outer class deleted")
    
    
    def scope():
        ic = OuterClass()
    
    scope()
    print("Left scope, you should have seen garbage collection")
    input("About to terminate program")