Python list 的扩容策略对性能的影响
技术百科
舞夢輝影
发布时间:2026-01-20
浏览: 次 Python列表扩容采用几何增长策略,新容量≈当前容量×1.125,摊销时间复杂度O(1),但会引发偶发延迟与内存浪费。
Python 列表(list)的扩容策略直接影响频繁 append() 操作的性能表现。它不是每次添加一个元素就重新分配内存,而是采用“几何增长”策略——当空间不足时,分配比当前容量更大的新数组,从而摊销单次追加的平均时间复杂度为 O(1)。但这个策略在特定场景下仍会带来可观测的延迟和内存开销。
扩容不是等量增长,而是按比例扩大
CPython 实现中,列表扩容时的新容量计算公式大致为:
- 新容量 = 当前容量 + 当前容量 // 8 + (3 if 当前容量
- 也就是说,容量越大,每次扩大的绝对值越大(例如从 1024 → 1152,再 → 1300+),但增长率逐渐趋近于约 12.5%
- 这种设计平衡了内存浪费与重分配频率:太激进(如翻倍)浪费内存,太保守(如+1)导致频繁拷贝
扩容瞬间会造成明显的延迟尖峰
虽然均摊是 O(1),但每次扩容需执行三步操作:申请新内存、复制旧元素、释放旧内存。当列表已含数万甚至百万元素时,一次扩容可能耗时毫秒级:
- 例如向一个 50 万元素的 list 追加第 500001 个元素,若触发扩容,需拷贝全部 50 万个对象引用(注意:只复制引用,不深拷贝对象本身)
- 在对延迟敏感的场景(如实时数据采集、高频事件循环)中,这种“偶发卡顿”可能影响响应性
- 可通过
sys.getsizeof(my_list)观察实际分配容量,对比len(my_list)发现冗余空间
预分配可彻底规避动态扩容开销
如果你事先知道最终长度(或上限),用 [None] * n 或 list.__init__() 预分配能完全消除 append 过程中的扩容行为:
-
推荐写法:
result = [None] * expected_size,然后用索引赋值:result[i] = x - 避免写
result = []; for i in range(n): result.append(x)—— 即使 n 固定,也会触发多次扩容 - 若长度不确定但有合理上界,也可先预分配再用
del result[actual_len:]截断
其他常见误判点
有些直觉性理解容易误导优化方向:
-
list 扩容不涉及元素内容复制:只复制
指针(PyObject*),无论元素是 int、str 还是自定义对象,成本相同
- insert(0, x) 始终是 O(n):和扩容无关,但会移动所有后续元素,应避免在大列表头部频繁插入
- 小列表(:扩容开销微乎其微,过早优化反而降低代码可读性
# 如果你
# 在对
# 也会
# python
# 翻倍
# 自定义
# 越大
# app
# 更大
# 再用
# 循环
# 对象
# if
# int
# 指针
# 事件
# 不确定
# len
# for
# append
# 微乎其微
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Win11怎么更改电脑密码_Windows 11修
- Win11怎么设置虚拟键盘_打开Win11屏幕键盘
- PHP主流架构怎么部署到Docker_容器化流程【
- 如何使用Golang包导出规则_控制函数和变量可见
- 如何在Golang中定义接口_抽象方法和多态实现
- 怎么将XML数据可视化 D3.js加载XML
- 如何将竖排文本文件转换为横排字符串
- windows如何修改文件默认打开方式_windo
- Mac电脑进水了怎么办_MacBook进水后紧急处
- Python对象生命周期管理_创建销毁解析【教程】
- php怎么捕获异常_trycatch结构处理运行时
- 如何使用Golang反射创建map对象_动态生成键
- php增删改查报错1054怎么办_字段名错误排查修
- c++ namespace命名空间用法_c++避免
- PythonWeb前后端整合项目教程_FastAP
- Win10文件历史记录怎么用 Win10开启自动备
- PHP 中如何在函数内持久修改引用变量所指向的目标
- Win11怎么关闭自动调节亮度_Windows11
- Win11无法识别耳机怎么办_解决Win11插耳机
- PythonPandas数据分析教程_数据清洗与处
- Python数据抓取合法性_合规说明【指导】
- 如何使用Golang实现微服务事件驱动_使用消息总
- windows如何禁用驱动程序强制签名_windo
- Windows蓝屏错误0x00000018怎么处理
- Windows10如何更改计算机工作组_Win10
- Win11文件夹预览图不显示怎么办_Win11缩略
- Win11怎么关闭搜索历史_Win11清除设备上的
- php嵌入式日志记录怎么实现_php将硬件数据写入
- Python数据挖掘核心算法实践_聚类分类与特征工
- MAC怎么设置程序窗口永远最前_MAC窗口置顶插件
- C#怎么使用委托和事件 C# delegate与e
- Win11怎么开启智能存储_Windows11存储
- Python对象生命周期管理_创建销毁说明【指导】
- Win11怎么关闭右下角弹窗_Win11拦截系统通
- c++如何利用doxygen生成开发文档_c++
- Win11怎么恢复出厂设置_Win11重置此电脑保
- Python性能剖析高级教程_cProfileLi
- Windows10电脑怎么设置防火墙出站规则_Wi
- PythonDocker高级项目部署教程_多容器管
- Win11怎么制作U盘启动盘_Win11原版系统安
- 企业SEO优化选择网站建设模板的技巧
- Win11怎么设置麦克风权限_允许应用访问Win1
- Win10怎么限制单程序CPU占用上限_Win10
- MySQL 中使用 IF 和 CASE 实现查询字
- Win10任务栏天气和资讯怎么关闭 Win10禁用
- Python邮件系统自动化教程_批量发送解析与模板
- Win11怎么设置默认邮件应用_Windows11
- 如何提升Golang程序I/O性能_Golang
- Django密码修改后会话失效的解决方案
- 如何将文本文件中的竖排字符串转换为横排字符串


QQ客服