Python中列表乘标量、相加、extend自复制的性能差异原因
Python列表自复制三种写法的性能差异原因
实现长度100万元素的列表自复制(拼接得到原内容重复2次的列表)时,三种常见写法的执行速度差距非常明显,其中l * 2的速度远高于另外两种。
三种实现代码
- 方案1(执行速度最快)
l = [1,2,3,...1000000] return l * 2
- 方案2(执行速度较慢)
l = [1,2,3,...1000000] return l + l
- 方案3(执行速度较慢)
l = [1,2,3,...1000000] l.extend(l) return l
性能测试截图
速度差异的底层原因(基于CPython实现)
l * 2走的是列表乘法的专门优化路径:执行时会直接算出最终列表总长度是len(l)*2,一次性申请好对应大小的连续内存,之后直接批量把原列表的元素引用循环拷贝2次,全程没有中途扩容、重复边界校验的额外开销,连续内存批量写入的效率非常高。l + l走的是通用列表拼接逻辑:它不会提前判断加号两边是不是同一个列表,只会先按第一个列表的长度预分配新列表内存,追加第二个列表的元素时,会触发多次扩容检查,拷贝也是分两段完成,比一次性批量拷贝的开销大很多。l.extend(l)是原地修改列表的逻辑:执行时一开始不会提前计算追加完成后的总长度,只能边遍历源列表(也就是正在被修改的l本身)边追加元素。遍历过程中列表不断变长,会触发多次内存重分配、全量元素拷贝,还要额外加校验防止遍历因为列表变长陷入死循环,额外开销是三个方案里最高的。
内容的提问来源于stack exchange,提问作者Ravi
相关产品推荐
相关产品推荐



