python如何优化条件列表理解



我在Python中读到了没有[]的List理解,所以现在我知道

''.join([str(x) for x in mylist])

比快

''.join(str(x) for x in mylist)

因为"列表理解是高度优化的">

因此,我假设优化依赖于对for表达式的解析,查看mylist,计算其长度,并使用它来预分配精确的数组大小,这节省了大量的重新分配。

当使用''.join(str(x) for x in mylist)时,join盲目地接收生成器,并且必须在事先不知道大小的情况下构建其列表。

但现在考虑一下:

mylist = [1,2,5,6,3,4,5]
''.join([str(x) for x in mylist if x < 4])

python是如何决定列表理解的大小的?它是根据mylist的大小计算的,并在迭代完成时缩小(如果列表很大,条件过滤掉99%的元素,这可能会非常糟糕),还是会恢复到"事先不知道大小"的情况?

编辑:我做了一些小的基准测试,似乎证实了有一个优化:

无条件:

import timeit
print(timeit.timeit("''.join([str(x) for x in [1,5,6,3,5,23,334,23234]])"))
print(timeit.timeit("''.join(str(x) for x in [1,5,6,3,5,23,334,23234])"))

收益率(如预期):

3.11010817019474
3.3457350077491026

条件:

print(timeit.timeit("''.join([str(x) for x in [1,5,6,3,5,23,334,23234] if x < 50])"))
print(timeit.timeit("''.join(str(x) for x in [1,5,6,3,5,23,334,23234] if x < 50)"))

收益率:

2.7942209702566965
3.0316467566203276

因此条件listcomp仍然更快。

列表理解不会预先调整列表大小,即使它们完全可以。你假设存在一个实际上没有完成的优化。

列表理解更快,因为所有的迭代器机制以及进入和退出genexp堆栈框架的工作都有成本。列表理解不需要为此付出代价。

最新更新