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

为何Python列表推导比预初始化大小的列表更快?

为什么列表推导式比预分配大小的列表初始化更快?

先看三个测试用的Python函数:

def without_initialising_size():
    x = []
    for i in range(100_000):
        x.append(i)
    return x

def with_initialise_size():
    x = [None] * 100_000
    for i in range(100_000):
        x[i] = i
    return x

def list_comprehension():
    return [i for i in range(100_000)]

已知with_initialise_size比without_initialising_size更快,原因是预先确定列表大小后,Python无需在列表增长时反复寻找更大的内存块。但为什么list_comprehension比with_initialise_size快得多?

以下是使用timeit.timeit(number=1000)的基准测试结果:

  • without_initialising_size:3.85671530000036
  • with_initialise_size:3.0115716999971482
  • list_comprehension:2.278098400001909

是不是因为with_initialise_size多了为每个列表元素加载None的步骤,还是有其他被忽略的因素?


核心原因解析

主要有两个关键因素导致列表推导式更快:

  1. 避免预填充None的双重赋值开销
    [None] * 100_000会先创建一个所有元素都是None的列表,这一步需要遍历整个内存块写入None的引用。之后的for循环还要把每个位置的None替换成i,等于对每个列表位置执行了两次赋值操作——先写None,再写目标值。而列表推导式是直接将i一次性写入对应位置,完全没有这层额外的预填充步骤。

  2. 列表推导式的底层优化更彻底
    列表推导式是Python专门优化的语法,它的执行逻辑在解释器底层直接完成,规避了普通for循环的不少额外开销:

    • 不需要在每次循环中查找调用append方法,或者执行列表下标赋值的字节码操作;
    • 推导式的变量查找、循环迭代逻辑都做了内联优化,减少了Python解释器在字节码层面的调度成本;
    • 推导式可以直接获取range的长度,预先分配刚好足够的内存,既不需要像append那样预留额外空间,也不需要预填充None。

简单来说,列表推导式把循环和列表构建的逻辑合并成了更紧凑、更贴近底层的操作,而预分配列表的方式还多了一层预填充和二次赋值的成本,自然速度会落后。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 22:15:39