Python中Tuple、List与Array的内存占用对比疑问
列表/元组与array.array存储float的内存差异及sys.getsizeof的疑问
核心结论
- 列表和元组确实存储指向PyFloatObject的指针,而
array.array直接存储C语言原始的float/double值,不存在指向Python对象的指针。 - 测试结果与预期的差异,核心原因是
sys.getsizeof()的特性:它仅返回当前对象自身占用的内存,不会递归计算其引用的其他对象的内存。
详细解释
先回顾《流畅的Python》中的描述:
这就是float数组比float元组紧凑得多的原因:数组是存储float原始值的单个对象,而元组由多个对象组成——元组本身以及其中每个float对象。
这句话的核心是总内存占用,而非sys.getsizeof()直接返回的单个对象内存:
- 元组/列表的内存构成:
- 元组/列表本身是一个Python对象,底层C结构包含指向PyObject的指针数组,每个指针指向独立的
PyFloatObject实例(即Python中使用的float对象)。 sys.getsizeof(tuple)返回的是元组结构体+指针数组的内存大小,但每个PyFloatObject自身还要占用额外内存(Python 3.11 64位环境下,一个float对象约占48字节)。要计算元组的总内存,需将元组本身的大小加上所有元素float对象的内存总和。
- 元组/列表本身是一个Python对象,底层C结构包含指向PyObject的指针数组,每个指针指向独立的
- array.array的内存构成:
array.array('d')(存储双精度float)的底层是一块连续内存缓冲区,直接存储C语言的double值(每个占8字节),无额外Python对象开销。sys.getsizeof(array)返回的是数组结构体加上所有原始float值的内存总和,无需额外计算其他对象的内存。
测试结果差异的原因
如果仅对比sys.getsizeof()返回的元组和数组大小,可能会觉得元组的大小没大多少(比如包含10个float的元组,sys.getsizeof返回40 + 108 = 120字节;而array.array('d')返回数组结构体(约96字节) + 108 = 176字节),这看似和“数组更紧凑”的结论矛盾,但这是因为你只计算了元组本身的内存,没算每个float对象的内存。
若计算总内存:
- 元组总内存:120 + 10*48 = 600字节
- 数组总内存:176字节
此时就能体现出数组的紧凑性,与书中描述一致。
底层结构确认
你提到的结论是正确的:Python列表和元组的底层C结构确实是存储指向PyObject的指针数组,每个float元素都是独立的PyFloatObject实例;而array.array直接存储原始数值,没有中间的Python对象层。
内容的提问来源于stack exchange,提问作者Andrey
相关产品推荐
相关产品推荐

