Python 的 list 为什么能装下任何类型?拆开 PyObject* 数组,以及它让你多付了多少内存

简介: list 能装下任何类型,是因为它存的是 PyObject* 指针数组:类型信息挂在对象自己头上。代价是每元素 8 字节指针加完整对象头——实测 100 万个整数,list 总内存约 34.3MB,是 array 的 9 倍。本文用 sys.getsizeof 一格格量给你看,并给出什么时候该换 array/numpy 的判断标准

先看一个几乎所有人都用过、但很少人想过的事:

a = [1, "hello", 3.14, [1, 2], None, {
   "k": 1}]

整数、字符串、浮点、列表、None、字典——六种完全不同的东西,塞进同一个 list,Python 一点都不抗议。

Java 的 ArrayList<Integer> 装不进 String,C 的数组更不用说。为什么 Python 的 list 可以?

答案只有一句:list 里存的从来不是值,是指针。

拆开看:一块连续的 PyObject*

CPython 的 list 在内存里是两个东西:

  1. 一个 PyListObject 头(引用计数、类型指针、长度、已分配容量)
  2. 一块连续的数组,每个元素槽 8 个字节(64 位系统),里面放的是 PyObject* 指针

用 sys.getsizeof 就能看出这个 8 字节的槽:

import sys
print(sys.getsizeof([]))      # 56
print(sys.getsizeof([1,2,3])) # 88
print((88 - 56) / 3)          # 10.67 —— 不是 8?

等等,10.67 不是 8。因为 list 会预分配:创建一个 3 元素的 list 时,实际容量是 4,所以 56 + 4×8 = 88。

真正的槽宽验证要看扩容那一刻:

lst = []
prev = sys.getsizeof(lst)
for i in range(1, 20):
    lst.append(i)
    cur = sys.getsizeof(lst)
    if cur != prev:
        print(len(lst), cur, "槽数:", (cur - 56) // 8)
        prev = cur
# 1 88 槽数: 4
# 5 120 槽数: 8
# 9 184 槽数: 16

槽宽恒为 8 字节。这就对了——64 位指针。

最直接的一个证据:

x = object()
lst = [x]
print(lst[0] is x)   # True

list 里那个位置和 x 是同一个对象,不是副本。所以 list 存的就是引用本身。

类型信息存在对象里,不在变量里

这就引出 Python 类型系统的核心设计:类型不属于变量,属于对象。

每个 Python 对象头上都有一个 PyObject_HEAD(引用计数 + 类型指针)。list 的槽里放的指针指过去,读一下类型指针就知道这是什么东西。

所以 list 根本不需要"元素类型一致"这个前提。它只要保证每个槽是一个合法的 PyObject* 就行。

代价也很直接:

print(sys.getsizeof(1))     # 28
print(sys.getsizeof("a"))   # 42

一个 Python 的 int 对象 28 字节,其中真正存数值的部分只占几个字节——剩下全是对象头。

这笔内存账有多贵

做个极端点的实验,存 100 万个整数:

import sys, array
N = 1_000_000
li = list(range(N))
ar = array.array('i', range(N))
print(sys.getsizeof(li))   # 8000056  (约 7.6 MB)
print(sys.getsizeof(ar))   # 4091948  (约 3.9 MB)

光看数组本身,list 是 array 的 2 倍:8 字节指针 vs 4 字节 int32。

但这只是"指针的钱",真正的开销在对象上——100 万个 int 对象,每个 28 字节:

list 数组本体   约  7.6 MB
100万个 int 对象 约 26.7 MB
---------------------------
合计            约 34.3 MB

array('i')      约  3.9 MB

约 9 倍。

这就是"能装任何类型"的价格:你为每一粒米都买了一个带包装的盒子。

那什么时候该换掉 list

先说结论:绝大多数业务代码不用管。一万、十万级别的数据,多出来的那点内存不值一提,list 的灵活性强太多。

但下面三种情况,换掉是实打实的收益:

1. 几百万级的数值数据 —— 用 array 模块(标准库,零依赖),或者 numpy:

from array import array
a = array('d', [1.0, 2.0, 3.0])   # 8 字节双精度,紧贴存储

2. 结构固定的记录 —— __slots__ 或者 dataclass(slots=True),别让每个对象都背一个 dict:

class Point:
    __slots__ = ('x', 'y')     # 去掉实例字典,省一大截
    def __init__(self, x, y): self.x, self.y = x, y

3. 只读的大序列 —— tuple 没有预分配,也没有扩容逻辑,内存比同长度 list 略省,还不可变。

一句话总结

list 能装下任何类型,是因为它装的是指针数组,类型信息挂在对象自己头上,而不是容器上。

这个设计换来的是极致的灵活性:异构容器、任意嵌套、引用语义共享,全都免费。

代价是每个元素多付一个指针(8 字节)外加一个完整对象头。存 100 万个整数时,这个代价是 9 倍内存。

所以真正的分界线不是"该不该用 list",而是:你这批数据,是"东西"还是"数字"。 是东西就用 list,是数字就该想想 array 和 numpy 了。

相关文章
|
云安全 安全 网络安全
|
3天前
|
JavaScript API iOS开发
DeepSeek Harness下载、安装、配置一篇搞定(2026整理,送常用插件)
DeepSeek Harness(DSH)是DeepSeek于2026年开源的MIT协议AI Agent框架,支持插件化组装模型、工具、沙箱与UI,兼容主流大模型。本文提供免Node.js的桌面端安装包(Win/macOS),含详细图文教程及热门插件推荐。
|
17天前
|
JSON 程序员 数据格式
最新版Notepad++下载、安装、配置保姆级教程(附官网安装包)
Notepad++ 是一款免费开源、轻量快速的 Windows 文本编辑器,支持多标签、语法高亮、代码折叠与宏录制,体积小、启动快、资源占用低,兼容 x64/x32/ARM 架构,是程序员和文字工作者的高效利器。
4004 1
|
9天前
|
JavaScript 安全 前端开发
Nodejs Brotli decoder 代码执行漏洞 (CVE-2026-111497)10629
Node.js发布安全更新修复Brotli解码器高危RCE漏洞(CVE-2026-111497),建议受影响版本用户立即升级。
2062 2
|
16天前
|
人工智能 API 开发工具
DeepSeek Harness 神插件:白嫖 13 家大厂模型
`dsh-our-free-model` 是 DeepSeek Harness 神级插件:零配置、零API Key、零账号,聚合13家大厂免费模型(含DeepSeek V4.1 Flash、Kimi K3等),支持本地网关、用量看板与自动降级,真正实现“白嫖即用”。
2650 46
|
3天前
|
iOS开发 Docker MacOS
【2026实测】Docker Desktop下载、安装、汉化、配置教程(附官网安装包)
Docker Desktop 是 Docker 官方推出的桌面容器管理工具,集成引擎、CLI、图形界面与 Kubernetes,支持 Win/macOS/Linux。2026 最新版 4.88.1 强化 ARM 原生运行、镜像加速及资源可视化,附中文汉化与国内镜像配置指南。
554 1
|
13天前
|
Web App开发 人工智能 前端开发
2026 年 AI 浏览器怎么选?Ego Lite、Tabbit、Chrome DevTools MCP 深度对比,开发者到底该用哪个?
2026年AI浏览器选型指南:Ego Lite专注多Agent协同(Mac优先),Tabbit国产首选,原生支持Windows与Codex控制;Chrome DevTools MCP非浏览器而是开发者利器,深度集成Console/Network/Performance调试能力,让AI真正“看懂并验证”前端代码。
1519 3
|
10天前
|
开发者 索引
DeepSeekHarness大肥鱼自带插件市场了?加个地址就能用
Open Plugin Market 是一个开放插件索引平台,收录800+优质DSH插件,支持分类浏览、智能推荐与随机发现。无需安装市场,粘贴索引地址即可一键接入,网页版直访 dshopen.org,助力小开发者被看见。(239字)
2103 1
DeepSeekHarness大肥鱼自带插件市场了?加个地址就能用
|
8天前
|
人工智能 Linux API
Magpie, 轻量本地AI网关!免费Token用不完!
Magpie 是开源AI编程模型调度网关,上线一月获1.8万Star。它通过本地高性能网关统一托管多平台API密钥、账号与免费额度,实现跨Agent的模型秒级切换、静默额度轮换与资源复用,显著降低碎片化管理成本。(239字)
Magpie, 轻量本地AI网关!免费Token用不完!

热门文章

最新文章