由numpy数组组成的字典真的比单个ndarray占用内存更少吗?
问题原因解答
首先明确核心结论:你观测到的内存差异完全是因为sys.getsizeof的统计逻辑限制导致的假象,字典方案的实际总内存开销远高于单个numpy二维数组。
1. sys.getsizeof的统计规则
sys.getsizeof()仅统计Python对象自身占用的内存,不会递归统计该对象引用的其他对象的内存开销:
- 对于numpy数组,因为它的实际数据存储在数组对象自身关联的连续内存块中,
sys.getsizeof会把这部分数据内存+数组元数据内存统一计算,所以你得到的4000112字节是完整开销:100010004(float32单元素大小) + 112字节(numpy数组元数据:形状、dtype、步长等属性),完全符合预期。 - 对于字典
b,sys.getsizeof(b)返回的36968字节仅仅是字典容器本身的哈希表开销,用来存储1000个键值对的引用,完全没有统计你存入的1000个一维numpy数组的内存,更没有统计这些数组对应的数据内存。
2. 字典方案的真实内存开销
你存入字典的每个a[:,ii]都是原二维数组的视图对象:
- 每个视图本身是独立的numpy一维数组对象,有自己的元数据开销(约100字节/个),1000个视图的元数据总开销就超过100KB
- 所有视图共享原数组的4MB数据块,当你删除原数组
a后,因为这些视图仍然持有数据块的引用,所以数据块不会被垃圾回收,这部分内存始终存在,只是sys.getsizeof(b)不会统计到这部分
你可以执行以下代码验证真实总开销:
import sys import numpy as np a = np.zeros((1000,1000), dtype=np.float32) b = {} for ii in range(1000): b[f'{ii}']=a[:,ii] # 统计字典+所有值的总内存 total_size = sys.getsizeof(b) + sum(sys.getsizeof(v) for v in b.values()) print(f"字典方案的统计到的可见开销:{total_size} 字节") # 加上共享的4MB数据块,总开销约为4MB + 36KB + 100KB = 4132KB左右,远高于单数组的4000KB
3. 实践建议
你看到的内存更小是错误统计带来的假象,实际把二维数组拆成字典存一维视图的方案,总内存开销更高,访问效率也会因为多了一层字典查找和视图解析比直接访问原数组更低。如果要做内存高效的存储,优先保持单numpy数组结构,如果需要按名称访问列,可以搭配pandas DataFrame使用,底层仍然是连续块存储,额外开销远低于字典方案。
内容的提问来源于stack exchange,提问作者morepenguins
相关产品推荐
相关产品推荐

