位图是用单个比特存储布尔值的紧凑结构,Python中可用bytearray手动位操作或bitarray库实现;list[bool]因每个bool占28字节导致内存浪费,而位图100万位仅需125KB,压缩比超220:1。

位图(Bitmap)不是图像格式,而是用单个比特存储布尔值的紧凑结构——Python 里最直接、零依赖的实现是 bytearray 或 array.array('B') 手动位操作;第三方库 bitarray 更安全易用,但需额外安装。
为什么不用 list[bool] 存海量开关状态?
Python 的 bool 实际是 int 子类,每个占 28 字节(CPython 3.12),100 万个布尔值约耗 28 MB 内存;而位图只需 ⌈1000000 / 8⌉ = 125000 字节,压缩比超 220:1。更关键的是,list 的随机访问是 O(1),但位图的位级访问本身也是 O(1),且缓存局部性更好。
常见误判:以为 numpy.bool_ 能省空间——其实它仍是每元素 1 字节(8 倍于理论下限),且带完整 NumPy 开销。
手写位图:用 bytearray 实现 set_bit() 和 get_bit()
核心是把逻辑索引 i 拆成字节偏移 i // 8 和位偏移 i % 8,再用位运算读写:
bitmap = bytearray((n_bits + 7) // 8) # 分配足够字节数 <p>def set_bit(i): byte_idx, bit_idx = i // 8, i % 8 bitmap[byte_idx] |= (1 </p><p>def get_bit(i): byte_idx, bit_idx = i // 8, i % 8 return (bitmap[byte_idx] >> bit_idx) & 1</p>
注意点:
librosa 是一个用于音频和音乐分析的 Python 库。它提供了特征提取、频谱分析、节拍跟踪、起始检测和音频可视化的工具,基于 NumPy 和 SciPy 构建,用于科学音频计算。
- 索引
i必须 ≥ 0 且 assert 0 - 右移后必须
& 1,否则高位残留可能返回非 0/1 整数 - 写入时用
|=而非=,避免覆盖同字节其他位 - 初始化用
bytearray(size)得到全 0,比bytes可变
用 bitarray 库替代手写(推荐生产环境)
bitarray 是 C 扩展,支持切片、序列协议、内存视图,且自动处理大小端、边界对齐:
from bitarray import bitarray a = bitarray(1000000) # 默认全 False a[42] = True a[100:200] = True # 批量赋值 print(a[42]) # True print(a.buffer_info()) # 查看底层 bytes 地址和长度
安装与陷阱:
-
pip install bitarray—— Windows 用户若报编译错误,优先用conda install bitarray - 不要用
bitarray('101')初始化字符串,它会逐字符转 ASCII 码;要用bitarray('101', endian='big')或先转list[bool] - 与 NumPy 互操作需通过
.tobytes()或bitarray(buffer=...),不支持直接np.array(a)
位图压缩的隐藏成本:CPU vs 内存权衡
位图节省内存,但每次读写都多一层计算(除法、取模、位移),在热点路径中可能比 list[bool] 慢 2–3 倍。是否值得,取决于场景:
- 数据量 > 10 万且长期驻留内存 → 位图明显优势
- 频繁随机读写 + CPU 敏感 → 测量实际性能,别只看理论压缩比
- 需要原子操作(如并发 set/get)→
bitarray不提供线程安全,得自己加锁;bytearray的单字节写是原子的,但跨字节位操作不是 - 后续要序列化传输 →
bitarray.tobytes()直接得紧凑二进制,比 JSON/picklelist[bool]小两个数量级
真正容易被忽略的是位序:多数人默认“第 0 位是最低位”,但某些协议或硬件要求最高位优先(MSB-first),bitarray 默认是 LSB-first,需显式传 endian='big'。没对齐这点,跨系统解析就会全错。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










