tuple更省内存,因其对象头更轻、无allocated字段、小元组缓存及内存布局紧凑;但不可变性限制其适用场景,需权衡是否真不变。

tuple 对象头更轻,没有 allocated 字段
list 在 CPython 底层是 PyListObject,必须维护 ob_size(当前元素数)和 allocated(已分配指针槽数)两个字段——哪怕只存 1 个元素,也大概率预分配了 4 或 8 个指针位置。tuple 是 PyTupleObject,没有 allocated 字段,只存刚好够用的元素指针,对象头本身也少几个字节。
实测:空 list 占 56 字节,空 tuple 占 40 字节;3 元素 list 约 88 字节,同长度 tuple 约 72 字节。差额主要来自这部分元数据和冗余空间。
小元组被缓存,避免重复分配
CPython 对长度为 0–20 的元组做了单例缓存(_PyTuple_Ready 阶段完成),相同内容的小元组在多次创建时会复用同一块内存。比如 (1, 2) 出现在代码多处,实际只有一份实例。
list 没有这种机制——每次 [1, 2] 都是新对象,哪怕内容完全一样。这在循环或高频构造场景下会明显拉高内存压力。
- 缓存仅限小元组,长度超过 20 就不生效
- 缓存基于地址比较,不是值比较;
(1, 2)和(1+0, 2)可能不命中(取决于编译期是否折叠)
不可变性让内存布局更紧凑
list 存储的是指向元素的指针数组,每个指针在 64 位系统占 8 字节,还要预留扩容空间;tuple 的元素指针直接紧挨着存,没有“间隙”,也没有额外的指针数组管理开销。
更关键的是:tuple 不需要支持 append、pop、insert 等操作所需的运行时状态位或检查逻辑,整个结构更“扁平”。这也意味着 CPU 缓存行利用率更高,尤其在遍历时更友好。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
示例对比:
import sys lst = list(range(1000)) tup = tuple(range(1000)) print(sys.getsizeof(lst)) # 9080 字节左右 print(sys.getsizeof(tup)) # 8040 字节左右
为什么不能无脑全用 tuple?
节省内存的前提是数据真的不变。一旦你需要 .append()、.remove() 或解包后重新组装,强行用 tuple 只会增加转换成本:每次修改都得 list(tup) → 修改 → tuple(new_list),反而更慢更耗内存。
还有两个硬限制容易被忽略:
-
tuple元素必须全部可哈希才能作为dict键或set成员,含list、dict的 tuple 直接报TypeError: unhashable type - 嵌套 tuple 中某一层是 list,整个结构就失去不可变性保障,徒有其表
真正省内存的点,不在“写死一个 tuple”,而在“确认它从创建到销毁都不会变”——这个判断比语法选择更重要。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










