Python 垃圾回收
CPython 引用计数 + 分代循环垃圾回收;理解循环引用与 gc 模块边界。
#type / concept
#status / growing
#tech / dev
#resource / python
#tech / lang / python
[!info] 关联笔记
Python 垃圾回收
这个概念为什么出现
两个对象互相引用时,引用计数无法归零。CPython 引入循环检测 GC。不懂会在排查“内存不降”时误判。
[!abstract] 一句话理解 多数对象靠引用计数即时回收;容器循环由分代 GC 检测;
gc模块可观察与调试,而非日常手动 free。
最小可观察示例
场景:构造循环引用并手动收集
# cycle_gc_demo.py
# 业务意图:演示循环引用与 gc.collect。
# 教学点:循环需要 GC;实现细节。
import gc
class Node:
def __init__(self, name: str) -> None:
self.name = name
self.ref = None
def main() -> None:
gc.collect()
a, b = Node("a"), Node("b")
a.ref, b.ref = b, a # 循环
del a, b
n = gc.collect()
print("collected unreachable cycles approx:", n)
if __name__ == "__main__":
main()
建议运行:
python cycle_gc_demo.py
期望输出:collected unreachable cycles approx: 后为非负整数(具体数目因版本/其他对象而异)。
结合场景再看三个关注点
- del 名字不等于立刻解开循环。
- collect 返回收集统计相关值。
- 生产应避免不必要循环或使用弱引用。
核心概念与准确模型
- 引用计数
- 分代回收
- 可调阈值(高级)
__del__与周期回收的复杂交互
边界情况与反直觉行为
__del__复活对象- 关闭 GC 仅极端场景
- 原生内存 不在 gc 管理
常见误区
[!warning] 常见误区:Python 没有 GC 只有计数 错误理解:单机制。
正确模型:计数 + 循环 GC(CPython)。
工程实践
- 缓存用弱引用/显式上限
- 排查泄漏:对象增长曲线
- 不要在业务里频繁玩 gc 旋钮
本节总结
GC 是安全网。设计上仍应管理对象生命周期与缓存边界。
自测题
- 循环引用为何难倒纯引用计数?
__del__为何危险?
参考答案
- 互相持有导致计数永不为 0。
- 与回收顺序/复活交互复杂,可拖住收集。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| gc | 文档 | 模块 |
| Supporting Cyclic GC | C-API | 实现向 |