Python列表底层是动态指针数组,含引用计数与过量分配机制;append()平摊O(1)因扩容按new_allocated = (size >> 3) + (size
Python 列表不是“可变数组”的简单翻译,它的底层是动态指针数组 + 引用计数 + 过量分配(over-allocation)机制。直接操作
list时,你其实一直在和这套内存管理策略打交道。为什么
append()平摊时间复杂度是 O(1),但单次可能触发 O(n) 重分配?CPython 的
list在扩容时,并非每次只加 1 个槽位,而是按公式new_allocated = (size >> 3) + (size 增长(见 <a href="https://www.php.cn/link/4b7dc121caf2baf0963a047346fc8df6">listobject.c</a>)。这意味着:
- 小列表(如长度
- 大列表(如长度 1000)再
append(),可能新增约 125 个空位- 真正耗时的是
memcpy整块复制旧数据到新地址——这步不可省略,且发生在扩容瞬间- 所以连续调用 1000 次
append(),实际只重分配约 10–15 次,平摊下来接近常数
del lst[i]和lst.pop()的性能差异远不止“删尾 vs 删中”删除末尾元素(
pop())只需将ob_size减 1;而删除中间或开头元素(del lst[i])必须把i+1到末尾的所有指针向前挪一位——这是纯 C 级别的内存移动:import timeit lst = list(range(100000)) timeit.timeit(lambda: lst.pop(), number=100000) # ≈ 0.012s timeit.timeit(lambda: del lst[0], number=100000) # SyntaxError —— 正确写法是: timeit.timeit(lambda: lst.__delitem__(0), number=100000) # ≈ 2.8s(慢 200 倍以上)更隐蔽的坑:
lst.remove(x)先遍历找索引,再执行__delitem__,等价于 O(n) 查 + O(n) 移。立即学习“Python免费学习笔记(深入)”;
用
list.extend()替代循环append()不只是为了“写得短”假设你要合并两个列表:
for x in other: target.append(x)→ 每次append都可能触发检查、扩容、复制target.extend(other)→ C 层直接预估总长度,一次分配到位,再批量 memcpy- 若
other是生成器(如range(10**6)),extend仍能高效处理;而循环append会因反复扩容严重拖慢实测:向空列表添加 100 万个整数,
extend(range(10**6))比循环append快 3–5 倍。别依赖
id(lst)不变来判断“列表没重建”,它掩盖了真实风险看似安全的操作,比如:
lst = [1, 2, 3] original_id = id(lst) lst += [4, 5] # 原地修改,id 不变 lst *= 2 # 原地修改,id 不变 lst = lst + [6] # 创建新对象!id 已变问题在于:
+=和*=对list是就地操作(调用list_inplace_concat),但+和*总是新建对象。如果你在函数外持有原列表引用,又误用+赋值,就可能引发静默的引用失效。真正需要关注的不是
id,而是是否触发了底层realloc或指针复制——这些对上层透明,但影响缓存局部性和 GC 压力。
相关文章
Python 多进程场景下 logging 的正确初始化与隔离实践
Python生产环境多进程日志安全实践:解决fork导致的日志覆盖与重复问题
Python 多进程日志安全实践:解决 fork 场景下的日志重复与覆盖问题
Python 多进程场景下 logging 的正确实践:避免日志重复与状态污染
Python 多进程场景下 logging 的正确实践:避免日志重复与数据覆盖
相关标签:
本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门AI工具
相关专题
深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。
379
2026.04.23
在Python中,append()是列表对象的一个方法,用于向列表末尾添加一个元素。想了解更多append的更多内容,可以阅读本专题下面的文章。
1496
2023.11.14
本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。
60
2026.11.06
围绕Postman HTTP请求头配置展开,讲解Headers选项的具体使用方式,包括Key和Value参数填写、请求头信息添加、常见Header字段设置及请求头修改方法,帮助用户解决接口调试过程中遇到的请求头配置问题。
20
2026.11.06
详细介绍Postman接口请求的创建与发送方法,涵盖GET和POST请求、URL配置、请求参数、Headers请求头、Body请求体设置以及响应结果查看,帮助用户掌握Postman接口请求的完整操作流程。
20
2026.11.06
DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。
40
2026.11.05
DBeaver安全防护专题,围绕数据库连接安全、账号密码保护和访问权限管理展开,整理SSL/TLS加密连接、SSH隧道、数据库凭据保存及证书验证等配置方法,同时介绍敏感信息保护、远程连接风险和高权限账号使用等注意事项,帮助用户提高数据库日常管理的安全性。
40
2026.11.05
热门下载
相关下载
精品课程
共0课时 | 0人学习
共0课时 | 0人学习
共0课时 | 0人学习
最新文章












