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

Python中小集合内存存储:为何空集合仅占用216字节?

为什么Python空集合的sys.getsizeof返回216字节而非预期的344字节?

先观察元素数量低于50k的集合扩容行为:

>>> import sys
>>> s = set()
>>> seen = {}
>>> for i in range(50_000):
...     size = sys.getsizeof(s)
...     if size not in seen:
...         seen[size] = len(s)
...         print(f"{size=} {len(s)=}")
...     s.add(i)
... 
size=216 len(s)=0
size=728 len(s)=5
size=2264 len(s)=19
size=8408 len(s)=77
size=32984 len(s)=307
size=131288 len(s)=1229
size=524504 len(s)=4915
size=2097368 len(s)=19661

这个扩容模式符合集合填充至3/5时后备存储容量四倍扩容的逻辑,结合PySetObject的固定开销,可通过计算验证:

>>> for i in range(9, 22, 2):
...     print(2**i + 216)
... 
728
2264
8408
32984
131288
524504
2097368

更大的集合会将扩容因子从四倍改为两倍,逻辑一致。

但这里存在疑问:新建空集合按说在首次扩容前有8个可用槽位,计算内存占用应为16*8 + 216 = 344字节,但sys.getsizeof(s)仅返回216字节,这是为什么?


核心原因:小集合的内部存储优化

你忽略了CPython对小集合的内存优化设计:

  1. 内置内部存储数组
    CPython 3.11+的PySetObject结构体本身预留了小型内部存储数组,可容纳最多4个元素。这部分内存已经包含在sys.getsizeof返回的216字节中,不需要额外分配外部堆内存。

  2. 外部数组延迟分配
    只有当集合元素数量超过内部数组容量(即添加第5个元素时),解释器才会分配外部哈希表数组(初始容量32槽位,大小为32*16=512字节)。此时sys.getsizeof会将结构体大小与外部数组大小相加,得到216+512=728字节,与实验结果完全匹配。

  3. 344字节计算的错误前提
    你假设空集合会分配8槽位的外部数组,但实际上空集合和元素数量≤4的集合根本不会分配外部数组,而是使用结构体内部的预留空间。这部分空间已计入PySetObject的基础大小,因此不会额外增加内存占用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 03:25:19