Python 嵌套 class/circular references/reference 循环的垃圾回收

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

我有以下嵌套结构:

#!/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")

有什么方法可以让这样的嵌套结构与垃圾回收一起工作吗?或者应该避免这样的结构总是

编辑:根据 LeventeSimofi 的建议添加了更好的关键字。

根据 Levente Simofi 的建议使用弱引用,这按预期工作:

#!/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")

很高兴你成功了!

我得到了相同的解决方案,以及这个不太实用的替代方案:

import gc  # importing the garbage collector module

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()
    input("Press enter to unscope")

scope()
print('Collecting...')
n = gc.collect()

Python 具有世代 垃圾收集 以及重新计数。它在后台自动执行(这里我手动调用)。此代码段显示,如果您不使用 weakrefs,您的对象也将被删除(稍后,当需要时),它们不会造成内存泄漏。

搜索 generational garbage collection 并阅读文章,如果您想知道它什么时候发生,或者它是如何工作的。它基本上是一种算法,摆脱了循环引用和自引用,无法用 引用计数.

解决