为什么Python3的timeit参数setup能大幅提升代码测速效率?
未使用setup参数的timeit测速耗时更长的原因
首先贴出对应的测试代码:
import timeit # 写法1:使用setup参数 print(timeit.timeit( setup = "M=range(100);f=lambda x: x*2", stmt = "[f(m) for m in M]")) # 写法2:未使用setup参数 print(timeit.timeit( stmt = "[(lambda x:x*2)(m) for m in range(100)]")) # 输出结果 17.038363554 26.128148989000003
两者耗时差距的核心来自timeit的运行机制和两段代码的资源初始化逻辑差异:
- 首先明确
timeit的执行规则:setup参数的代码仅在正式测速前执行1次,不会计入总耗时;stmt参数的代码会默认重复执行100万次,总耗时就是这部分重复执行的时间总和。 - 写法1(带setup)的额外开销极低:
range(100)对象和lambda函数f都在setup阶段仅创建1次,不会占用测速时间- 每次执行
stmt时,直接复用已经创建完成的M和f,仅需要完成遍历、函数调用的核心逻辑,没有额外的对象创建销毁开销
- 写法2(无setup)存在大量重复无效开销:
- 所有逻辑都放在
stmt中,每次执行stmt都需要重新创建range(100)对象,单次开销极低但重复百万次后累计开销不可忽略 - 列表推导的每一轮迭代都需要临时创建一个新的lambda匿名函数,调用完成后立刻销毁该函数,反复创建销毁函数对象的开销远高于直接调用已有的固定函数,是耗时拉长的核心原因。
- 所有逻辑都放在
如果把写法2调整为把lambda和range的初始化放到stmt开头,即stmt = "f=lambda x:x*2;M=range(100);[f(m) for m in M]",耗时仍然会高于写法1,因为初始化逻辑还是会随stmt重复执行百万次,而非只执行1次。
内容的提问来源于stack exchange,提问作者user3112576
相关产品推荐
相关产品推荐

