array内存更小是因为其为连续c数组,只存原始数值,无python对象头和指针开销;而list存储对象指针,每个元素额外占8字节,且每个int对象本身约28字节。

用 array 替代 list 确实能显著降低内存占用,但前提是:你存的是同类型数值,且不需要 list 的动态方法(比如 append() 频繁混用、嵌套、存字符串或对象)。盲目替换反而可能出错或增重。
为什么 array 内存更小?关键在连续、定型、无指针
list 在 CPython 中本质是 PyObject* 指针数组,每个元素都带引用计数、类型信息、GC 标记 —— 即便存 100 万个 int,也要为每个分配一个完整 Python 对象;而 array.array('i', [...]) 是一块连续的 C int 内存,没额外元数据,纯数据。
- 存 100 万个 32 位整数:
list约占 8MB(64 位系统下每个指针 8 字节 × 100 万),array('i')只占 4MB(每个 int 4 字节) - 存浮点数更明显:
array('d')是 8 字节/元素,list仍要为每个float对象额外开销约 24 字节 - 注意:
array不支持None、字符串、嵌套结构 —— 它不是通用容器,是紧凑数值缓冲区
怎么选 typecode?别用错导致静默截断或爆内存
typecode 决定了底层 C 类型和内存布局,选错轻则精度丢失,重则溢出崩溃。比如用 'b'(signed char, -128~127)存 200,会变成 -56;用 'H'(unsigned short)存负数直接报 OverflowError。
- 整数优先用
'i'(C int,默认 32 位)或'q'(64 位 long long),别贪小用'B'/'H'除非你明确控制值域 - 浮点统一用
'd'(double),'f'(float)虽省一半内存但精度差、易累积误差,科学计算慎用 - 不确定范围时先用
array('i')+array.itemsize查实际字节数,比猜安全
常见误用场景:append 性能反不如 list?
array.append() 看似和 list.append() 一样,但底层 realloc 策略不同:list 有超额分配(over-allocation),append 100 万次平均 O(1);array 每次扩容都是 memcpy 整块内存,append 100 万次可能慢 3–5 倍。
- 正确做法:预估长度,初始化时指定容量,如
arr = array('i', [0]) * n或用array('i', range(n)) - 若必须动态增长,先用 list 收集,最后一次性转
array('i', my_list)—— 构造函数内部做了优化拷贝 - 别对 array 调用
+=或extend()大量小数据,每次都是全量复制
和 numpy.array 比谁更省?别混淆用途
单纯比内存:小规模(array 更轻(无 numpy 依赖、无 dtype 对象开销);大规模且需计算时,numpy.array 的内存效率接近,但多了向量化能力 —— 但如果你只存、只读、只序列化,array 就是更干净的选择。
-
array原生支持.tofile()/.fromfile()直写二进制文件,比 picklelist快 10 倍、体积小 3 倍 - 不能直接用
json.dumps(array)—— 它没实现__dict__或默认序列化协议,得先转list或手动array.tolist() - 多线程安全?
array本身无锁,但若多个线程同时append或修改同一实例,行为未定义 —— 和 list 一样,得自己加锁
真正省内存的关键不在“换模块”,而在确认你的数据确实是同构数值、访问模式以顺序读写为主、且生命周期内不频繁增删中间元素 —— 否则 list 的灵活性成本反而更低。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











