在此代码中,Foo()个类的对象在创建新对象后仍然是活动的.我猜原因在于追加对象的List属性上的循环引用.那么,如何让垃圾回收器释放旧对象,而不需要手动调用gc.collect()呢?

import gc

class Foo():
    def __init__(self):
        self.functions = []
        print('CREATE', self)

    def some_func(self):
        for i in range(3):
            self.functions.append(self.print_func)
        print(self.functions)

    def print_func(self):
        print('I\'m a test')

    def __del__(self):
        print('DELETE', self)


foo = Foo()
foo.some_func()
foo = Foo()

# gc.collect()

input = input()

最后的input()只是为了保持程序运行.有此问题的实际项目包含While循环,因此保留旧的未使用的对象可能会导致内存泄漏. 现在,输出:

CREATE <__main__.Foo object at 0x000002747001D850>
[<bound method Foo.print_func of <__main__.Foo object at 0x000002747001D850>>, <bound method Foo.print_func of <__main__.Foo object at 0x000002747001D850>>, <bound method Foo.print_func of <__main__.Foo object at 0x000002747001D850>>]
CREATE <__main__.Foo object at 0x000002746FD0BB90>

呼叫gc.collect()时的输出:

CREATE <__main__.Foo object at 0x0000021E45F0D8E0>
[<bound method Foo.print_func of <__main__.Foo object at 0x0000021E45F0D8E0>>, <bound method Foo.print_func of <__main__.Foo object at 0x0000021E45F0D8E0>>, <bound method Foo.print_func of <__main__.Foo object at 0x0000021E45F0D8E0>>]
CREATE <__main__.Foo object at 0x0000021E45CDBB90>
DELETE <__main__.Foo object at 0x0000021E45F0D8E0>

这是一个结果,我想要得到,但不用gc

推荐答案

您可以使用weakref.WeakMethod来避免在list属性中创建对self.print_func方法的强引用.

请注意,要调用弱引用方法,您必须先通过在调用实际方法之前调用弱引用来取消对它的引用:

from weakref import WeakMethod

class Foo():
    def __init__(self):
        self.functions = []
        print('CREATE', self)

    def some_func(self):
        for i in range(3):
            self.functions.append(WeakMethod(self.print_func))
        print(self.functions)

    def print_func(self):
        print('I\'m a test')

    def __del__(self):
        print('DELETE', self)


foo = Foo()
foo.some_func()
foo.functions[0]()()
foo = Foo()
input()

这会产生以下结果:

CREATE <__main__.Foo object at 0x0000018F0B397150>
[<weakref at 0x0000018F0B18E0A0; to 'Foo' at 0x0000018F0B397150>, <weakref at 0x0000018F0B18E1F0; to 'Foo' at 0x0000018F0B397150>, <weakref at 0x0000018F0B18E490; to 'Foo' at 0x0000018F0B397150>]
I'm a test
CREATE <__main__.Foo object at 0x0000018F0B397190>
DELETE <__main__.Foo object at 0x0000018F0B397150>

演示:https://replit.com/@blhsing1/LightheartedTurquoiseChord

Python相关问答推荐

带有pandas的分区列上的过滤器的多个条件read_parquet

如何在telegram 机器人中发送音频?

Polars Select 多个元素产品

如何匹配3D圆柱体的轴和半径?

从 struct 类型创建MultiPolygon对象,并使用Polars列出[list[f64]列

已删除的构造函数调用另一个构造函数

PyQt5如何将pyuic 5生成的Python类添加到QStackedWidget中?

在for循环中仅执行一次此操作

使用pandas、matplotlib和Yearbox绘制时显示错误的年份

如何处理嵌套的SON?

使用polars .滤镜进行切片速度比pandas .loc慢

具有多个选项的计数_匹配

如何使用symy打印方程?

从收件箱中的列中删除html格式

Python虚拟环境的轻量级使用

当递归函数的返回值未绑定到变量时,非局部变量不更新:

使用groupby方法移除公共子字符串

在Google Drive中获取特定文件夹内的FolderID和文件夹名称

根据客户端是否正在传输响应来更改基于Flask的API的行为

如何过滤组s最大和最小行使用`transform`'