Python中map与列表推导式读取整数列表耗时对比结果波动疑问
测试操作的核心问题
- 你写的
timeit逻辑根本没有执行实际的整数列表转换操作:传入stmt参数的内容只是def定义函数的代码,跑10000次等价于重复定义了10000次同名函数,完全没有触发函数内部的读取、转换逻辑,你测的是函数定义的速度,不是你要的读取整数列表的速度,出现随机波动是必然结果。 - 就算你修改配置执行了
read函数,用stdin作为输入源也会导致每次测试的输入不一致:第一次调用stdin.readline()会读取标准输入的内容,后续没有新输入的情况下调用readline会直接返回空字符串,转换空列表和转换有内容的列表耗时本来就存在差异,结果自然不稳定。 - 0.01秒以内的测试结果受系统进程调度、CPU缓存、后台任务等外部因素影响极大,本身不具备参考性,测试时应该增加执行次数把总耗时拉到0.1秒以上再做对比。
正确的测试方案
你可以用固定的测试字符串替代stdin,排除输入波动的影响,同时让stmt直接执行转换逻辑:
from timeit import timeit # 固定测试输入,模拟从stdin读取到的一行数字字符串 setup = ''' test_str = "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15" ''' # 列表推导式写法 stmt1 = '[int(x) for x in test_str.split()]' # map转列表写法 stmt2 = 'list(map(int, test_str.split()))' # 执行100万次再统计耗时,降低随机误差 print(timeit(setup=setup, stmt=stmt1, number=1000000)) print(timeit(setup=setup, stmt=stmt2, number=1000000))
Python 3.10下的性能差异解释
用正确方案测试后,通常list(map(int, ...))的速度会比列表推导式快10%~20%,原因如下:
map接收内置函数int作为参数时,整个迭代调用逻辑是在C层面完成的,不需要每次迭代都承担Python层面的名称查找、函数调用开销- 列表推导式的
int(x)在每次迭代时,都需要在当前作用域查找int的指向,再执行Python级别的函数调用,额外开销更高
内容的提问来源于stack exchange,提问作者Diego FC
相关产品推荐
相关产品推荐

