一个由引用计数引起的Python内存管理小瑕疵

这个代码是在看了“码农高天”的视频照模仿的。

Python 的垃圾回收(Garbage Collection,以下简称 GC)算法是基于引用计数的方式实现的,即 Python 不会记录一个变量被哪几个变量所引用(函数也可以理解为一种变量),只会标记一个变量被引用了多少次
这种策略可以以极低的性能成本实现内存的自动回收功能,常在退出函数调用时使用,用于销毁其引用的所有变量。

这种策略虽然大幅增强 GC 算法的性能,但是一旦出现变量间的相互引用现象(即存在环路),那么基于引用计数的 GC 算法将无法有效识别出无用变量。也就无法实现实时的变量销毁功能。

以下是一段测试 GC 算法的样例代码,其中 __del__ 是 Python 定义的一个魔术方法,当一个对象将要被销毁时,GC 会自动调用该方法。该魔术方法常用于释放预先设置的系统资源。我们可以通过该魔术方法来观察对象何时被销毁。

from typing import Any, Optional
import gc


class Object:
    def __init__(self, name: str) -> None:
        self.obj: Optional[Any] = None
        self.name: str = name

    def __del__(self):
        print(f"{self.name} is deleted")


def main():
    a = Object("A")
    b = Object("B")

    a.obj = b
    b.obj = a


if __name__ == "__main__":
    main()
    print("start Garbage Collection")
    gc.collect()
    print("program end")

main 函数执行完成后,可以看到两个声明的变量A和B并没在main函数执行完成后销毁,而是在调用了 gc.collect() 之后才成功销毁。如下图所示:

实际上为了解决这一问题,Python还引入了循环垃圾检测(Cycle Detection)算法用于解决此类问题。该算法将会从根对象(全局变量容器)开始扫描并标记是否引用,然后再统一清除未引用的变量。不过由于该算法性能开销较大,因此触发该算法的条件较为苛刻,如使用内存快满了或手动调用 gc.collect() 时才会开始扫描。
分代回收算法则是循环垃圾检测的一种补充算法,在降低了性能开销的前提下,显著提升了垃圾回收效率。

posted @   乾坤盘  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 本地部署 DeepSeek:小白也能轻松搞定!
· 传国玉玺易主,ai.com竟然跳转到国产AI
· 自己如何在本地电脑从零搭建DeepSeek!手把手教学,快来看看! (建议收藏)
· 我们是如何解决abp身上的几个痛点
· 如何基于DeepSeek开展AI项目
点击右上角即可分享
微信分享提示