带有嵌套类/循环引用/引用循环的 Python 垃圾收集

问题描述

我有以下嵌套结构:

#!/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 具有分代垃圾收集以及引用计数。它在后台自动执行(这里我手动调用)。此代码段表明,如果您不使用弱引用,您的对象也将被删除(稍后,当需要时),它们不会造成内存泄漏。

搜索分代垃圾收集并阅读文章,如果您想知道它什么时候发生,或者它是如何工作的。它基本上是一种算法,它摆脱了循环引用和自引用,这是引用计数无法解决的。