You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CPython 3.11中sys.getrefcount()返回超大引用计数原因咨询

CPython 3.11中预缓存整数sys.getrefcount()返回极大值的原因

你观察到的现象确实和PEP 683 - 不朽对象(Immortal Objects):使用固定引用计数直接相关,下面具体解释:

现象回顾

在CPython 3.11中,-5到256区间的预缓存整数调用sys.getrefcount()会返回千万级别的数值,而非预缓存的整数(如-6、257)则保持正常计数:

Python 3.11.2 (tags/v3.11.2:878ead1, Feb  7 2023, 16:38:35) [MSC v.1934 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> for i in (-6, -5, 0, 255, 256, 257):
...    print(i, sys.getrefcount(i))
...
-6 5
-5 1000000004
0 1000000535
255 1000000010
256 1000000040
257 5

而CPython 3.10中这些预缓存整数的引用计数是正常的实际引用统计:

Python 3.10.8 (tags/v3.10.8:aaaf517, Oct 11 2022, 16:50:30) [MSC v.1933 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> for i in (-6, -5, 0, 255, 256, 257):
...    print(i, sys.getrefcount(i))
...
-6 5
-5 6
0 234
255 8
256 26
257 5

背后的原因

PEP 683的核心目标是优化GC性能,将一些全局不可变对象(包括-5到256的预缓存整数、None、True、False、部分字符串常量等)标记为"不朽对象"。

为了实现这一点,CPython给这类对象设置了一个固定的超大引用计数值(具体是2^30左右,也就是你看到的1000000000级别的数值)。这个数值的作用是让GC永远不会尝试回收它们——因为引用计数永远不会降到0,GC会直接跳过对这类对象的引用计数检查,从而减少GC的工作量。

在CPython 3.10及更早版本中,这些预缓存对象的引用计数是正常统计实际引用数量的,所以返回值是合理的小数值。

为什么文档没提及这个变化

这个现象属于PEP 683实现的附带行为,而非sys.getrefcount()本身的功能变更——sys.getrefcount()只是忠实地返回对象当前的引用计数值,而不朽对象的引用计数被人为设置成了超大值。官方文档可能因为这不是API的直接变更,所以没有单独在sys.getrefcount()或Python 3.11新特性文档中提及。

需要注意的是,这个超大引用计数对实际代码没有负面影响:这些对象本来就是全局缓存、不会被回收的,引用计数的具体数值在这里仅作为"不朽对象"的标识,不代表实际的引用数量。

内容的提问来源于stack exchange,提问作者Mark Tolonen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 16:27:31