You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么不同方式创建的Python列表__sizeof__()返回值不同,元组却一致?

结论

列表的创建方式确实会影响__sizeof__()的计算结果,该差异来自CPython中列表的动态数组过度分配机制;而元组作为不可变类型不存在该特性,因此不同创建方式返回的大小一致。

核心前提说明

__sizeof__()方法返回的是Python对象自身占用的内存字节数,不统计对象内部引用的其他元素的内存开销。

列表大小差异原因

列表本质是动态数组,为了减少频繁新增元素带来的内存重新申请、数据拷贝开销,CPython会在列表扩容时额外分配一部分预留空间(过度分配),不同创建方式能提前获取的元素总数信息不同,因此过度分配的程度不一样:

  • 字面量直接创建:Python解析字面量时可以直接确定列表长度为10,不会额外分配预留空间,仅分配存储10个元素指针所需的最小空间,因此内存占用最小,测试结果为120字节。
  • 生成器转列表:传入list构造器的生成器是惰性迭代对象,构造器无法提前预知最终元素总数,只能边迭代边按照动态扩容规则增加空间,迭代完成后剩余的预留空间比字面量创建的列表多,因此测试结果为136字节。
  • 列表推导式创建:列表推导式在CPython实现中会先获取可迭代对象(此处为range(10))的长度做预分配,同时采用了更激进的过度分配策略,因此预留的空间最多,测试结果为168字节。

注意:上述测试的字节数值仅对应特定版本、特定架构的CPython实现,不同环境下数值会有区别,但大小差异的逻辑是通用的。

元组大小一致原因

元组是不可变类型,一旦创建完成就不支持新增、删除元素,不需要预留扩容空间。不管用什么方式创建,只要最终包含的元素数量相同,就只会分配刚好够用的内存,因此两种创建方式返回的__sizeof__()结果完全一致。

你提供的测试代码验证了上述逻辑:

# 列表演示
>>> l1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> print(l1.__sizeof__())
120
>>> l2 = list(i for i in range(10))
>>> print(l2.__sizeof__())
136
>>> l3 = [i for i in range(10)]
>>> print(l3.__sizeof__())
168

# 元组演示
>>> t1 = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
>>> print(t1.__sizeof__())
104
>>>
>>> t2 = tuple(i for i in range(10))
>>> print(t2.__sizeof__())
104

内容的提问来源于stack exchange,提问作者sumixam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 05:51:00