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

Python预分配列表赋值比append慢的反直觉问题求解

Python预分配列表比append慢的原因

我们先重述测试用到的两个实现:

def funcA(data):
    A = []
    for d in data:
        A.append(d)
    return A

def funcB(data):
    A = [None] * len(data)
    i = 0
    for d in data:
        A[i] = d
        i += 1
    return A

实测funcB比funcA慢30%的核心原因有以下几点:

  • CPython对append方法的底层优化抵消了扩容开销
    列表的动态扩容是指数级策略(每次扩容为原大小的1.125倍+固定常量),针对10万元素的列表,全程仅需要扩容不到10次,内存重分配的总开销非常小。且append是纯C实现的内置方法,调用时几乎没有Python层面的额外开销,单次循环仅需执行一次append操作。
  • funcB的Python层面操作开销远大于预分配节省的内存开销
    funcB的单次循环需要完成3个操作:索引赋值A[i] = d、索引变量自增i += 1、遍历取元素d。其中i += 1是Python层面的整数运算,每次都要做类型校验、对象操作,累计开销远高于append的调用开销。同时索引赋值需要额外做边界检查,也会增加耗时。
    另外[None] * len(data)的初始化操作本身就要遍历一次列表写入所有None引用,后续赋值又要再写一次所有元素的引用,相当于对列表的引用数组做了两次写操作,而append仅需要写一次,这部分也是额外开销。
  • 字节码指令数量差异明显
    用dis模块拆解两个函数的字节码可以看到,funcA的循环体仅4条指令,funcB的循环体有7条指令,指令数多了近75%,运行速度自然更慢。

如果追求最高性能的列表拷贝,直接使用内置的list(data)或者切片data[:]即可,二者都是纯C实现的逻辑,性能比上述两种手动实现高3~5倍。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 10:57:01