array模块比list省内存,通常降至1/4~1/8;因list存PyObject指针而array是连续原始字节块,但仅适用于类型确定、批量读写的场景。

array模块比list省多少内存?先看实际差距
直接用 array 替换 list 处理纯数值时,内存占用通常能降到 1/4~1/8。比如存一千万个 int:用 list 约占 80MB,用 array('i')(32位有符号整数)约 40MB,用 array('b')(字节)存 0–255 范围数据只要 10MB。差距来自 list 存的是 PyObject 指针,而 array 是连续的原始字节块。
但别急着全换——array 不支持 append() 以外的动态操作,也不能存混合类型或嵌套结构。它只适合「类型确定、批量读写、不频繁插入删除」的场景,比如传感器采样序列、图像灰度值、日志时间戳数组。
选对 typecode 是省空间的关键
array 的压缩效果完全取决于你选的 typecode。选大了浪费空间,选小了会溢出或静默截断。常见组合:
-
'b'/'B':单字节有/无符号整数(-128~127 或 0~255),适合状态码、像素值 -
'h'/'H':2 字节整数(±32768 或 0~65535),适合音频样本、短整型 ID -
'i'/'I':4 字节整数(平台相关,通常 ±21 亿),最常用,兼容性好 -
'f':4 字节浮点(IEEE 754),比floatlist 省一半内存,精度够用时优先选 -
'd':8 字节浮点,和 Pythonfloat一致,精度高但省不了多少空间
错误示范:array('i', [256, 512]) 没问题,但 array('b', [256, 512]) 会变成 array('b', [0, 0])——超出范围不报错,直接模 256 截断。
立即学习“Python免费学习笔记(深入)”;
从文件读写 array 要绕开 pickle,用二进制流
pickle 序列化 array 会失去内存优势,因为加了大量元信息。正确做法是用原生二进制 I/O:
import array
# 写入
a = array.array('f', [1.1, 2.2, 3.3])
with open('data.bin', 'wb') as f:
a.tofile(f)
<h1>读取(必须知道 typecode 和长度)</h1><p>b = array.array('f')
with open('data.bin', 'rb') as f:
b.fromfile(f, 3) # 显式指定元素个数如果不知道长度,得提前存一个 header(比如前 4 字节存 int 表示元素数),或者用 os.path.getsize() 除以 array.itemsize 推算。别用 fromfile(f, -1)——它不会自动停在 EOF,可能崩溃。
和 NumPy 比,什么时候该坚持用 array?
如果你只需要「紧凑存储 + 简单遍历/索引」,且不想引入 NumPy 这个重量依赖,array 就够用。但一旦要切片、广播、向量化计算,立刻卡住:a[::2] 返回新 array 但不支持 a[a > 0.5] 这种布尔索引;没有 .mean()、.reshape() 这类方法。
折中方案:用 array 做 IO 缓冲或中间传输,需要计算时转成 NumPy:np.frombuffer(a, dtype=np.float32)(零拷贝,极快)。注意 dtype 必须和 typecode 对应,比如 'f' → np.float32,'i' → np.int32。
真正容易被忽略的是边界校验——array 不做运行时类型检查,越界写入、长度误算、typecode 错配,往往到读取时才暴露为乱码或 NaN,很难 debug。


















