Python垃圾回收机制_引用计数解析【教程】

13次阅读

python通过引用计数管理内存,对象引用计数为0时立即回收;但无法处理循环引用,需依赖gc模块的可达性分析来清理。

Python垃圾回收机制_引用计数解析【教程】

Python 主要靠引用计数来管理内存,对象被引用一次,计数就加一;引用被删除或离开作用域,计数就减一;当计数降为 0,对象立刻被回收。

引用计数怎么工作的?

每个 Python 对象内部都维护一个 ob_refcnt 字段,记录当前有多少变量、容器、参数等直接指向它。比如:

  • a = [1, 2, 3] → 列表对象引用计数变为 1
  • b = a → 同一个列表被 b 引用,计数变成 2
  • del aa = None → 计数减为 1
  • del b → 计数归零,列表对象立即释放,内存返还给解释器

哪些操作会改变引用计数?

不只是赋值和 del,这些常见动作都会影响计数:

  • 函数传参:func(x) 会让 x 指向的对象计数 +1(形参也持有一份引用)
  • 放入容器:my_list.append(obj)my_dict['key'] = obj 都会使 obj 计数 +1
  • 属性绑定:inst.attr = obj 同样增加引用
  • 临时变量:for 循环中迭代、with 语句里的 as 变量,也会在作用期间增加计数

怎么查看和验证引用计数?

标准库 sys.getrefcount() 可以查,但要注意:调用它本身就会让目标对象计数临时 +1(因为参数传递),所以结果比实际多 1:

立即学习Python免费学习笔记(深入)”;

import sys a = [] print(sys.getrefcount(a))  # 输出通常是 2(实际是 1,+1 来自 getrefcount 的参数传递)

真正想看原始计数,可用 ctypes 直接读内存(仅用于调试,不推荐生产使用):

import ctypes def get_refcount(obj):     return ctypes.c_long.from_address(id(obj)).value

引用计数的局限在哪?

它高效及时,但解决不了循环引用问题。例如两个对象互相持有对方的引用:

class node:     def __init__(self):         self.ref = None 

a = Node() b = Node() a.ref = b b.ref = a

此时 a 和 b 的引用计数都不为 0,但已无法从外部访问 → 内存泄漏

这种情况下,Python 会启用第二道防线:**循环垃圾回收器(gc 模块)**,定期扫描并清理不可达的循环引用组。它不依赖引用计数,而是基于对象的可达性分析。

text=ZqhQzanResources