page contents

请解释一下 Python 中的垃圾回收机制!

在 Python 里垃圾回收这块,说白了就是“谁来管内存释放”的问题。正常写业务代码的时候,你不会手动去释放内存,都是解释器自己搞定的,但背后其实有一套机制,不懂的话有时候遇到内存泄漏就一脸懵。

attachments-2025-09-mW9QcrWx68d0a6e39c19d.png在 Python 里垃圾回收这块,说白了就是“谁来管内存释放”的问题。正常写业务代码的时候,你不会手动去释放内存,都是解释器自己搞定的,但背后其实有一套机制,不懂的话有时候遇到内存泄漏就一脸懵。

引用计数是核心Python 默认用的是“引用计数”,简单点说就是:一个对象被多少地方引用了,它心里就有个小本本记着。比如你创建个列表 a = [1,2,3],那这个列表的引用计数就是 1,如果你再来一句 b = a,那引用计数就变成 2。只有当引用计数降到 0 的时候,Python 才会把内存释放掉。

import sys

a = []

print(sys.getrefcount(a))  # 比你想的多1,因为传给了 getrefcount

b = a

print(sys.getrefcount(a))

del b

print(sys.getrefcount(a))

但是呢,这玩意有个大坑,就是循环引用。最典型的情况:对象 A 引用 B,B 又引用回 A,哪怕外面没人用了,它俩互相抱着,引用计数永远不是 0,这就麻烦了。

分代回收机制为了处理循环引用,Python 又补了一套垃圾回收器,叫 分代回收。对象会被分到三代里,刚创建的是“年轻代”,每次垃圾回收没被干掉的,就升级一代。越老的对象越可能是“常驻”的,比如全局变量,所以垃圾回收器会对年轻代更频繁地扫描,对老年代不常动,算是一种“代价均衡”。

你可以直接看垃圾回收器的状态:

import gc

print(gc.get_stats())  # 看三代的收集统计信息

手动干预大多数时候你不需要管它,但要是内存占用特别高,或者你做的是短平快的任务(比如脚本跑完就退出),你可以主动调一下回收。

import gc

gc.collect()  # 强制触发一次垃圾回收

有时候你会在服务里发现内存不降,明明对象已经不用了,这时候先看看是不是循环引用没被回收,再考虑用 gc.collect() 强刷。

一些常见场景我自己遇到过一个情况,代码里搞了个“事件订阅”的东西,listener 对象里引用了 event,event 又保存了 listener 的引用,结果它们俩互相锁死,引用计数一直大于 0。后来只能加 weakref,用弱引用打破这种关系。

import weakref

class A:

    pass


a = A()

b = weakref.ref(a)  # b 不增加 a 的引用计数

所以总结下:Python 的垃圾回收是“引用计数为主,分代回收为辅”,绝大部分情况你不用管,但写底层框架或者长时间跑的服务,就得考虑循环引用、弱引用、手动回收这些问题。

你要不要我给你写个小 demo,演示一下循环引用导致内存不释放,然后再用 gc.collect() 把它搞掉?

更多相关技术内容咨询欢迎前往并持续关注好学星城论坛了解详情。

想高效系统的学习Python编程语言,推荐大家关注一个微信公众号:Python编程学习圈。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Python入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2022-05-rLS4AIF8628ee5f3b7e12.jpg

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
小柒
小柒

2204 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 2204 文章
  3. Pack 1375 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章