python如何优化条件列表推导

Jea*_*bre 13 python performance list-comprehension

在Python中没有[]读过关于列表理解的内容,所以现在我知道了

''.join([str(x) for x in mylist])
Run Code Online (Sandbox Code Playgroud)

比...更快

''.join(str(x) for x in mylist)
Run Code Online (Sandbox Code Playgroud)

因为"列表推导得到高度优化"

所以我认为优化依赖于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])
Run Code Online (Sandbox Code Playgroud)

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])"))
Run Code Online (Sandbox Code Playgroud)

收益率(如预期):

3.11010817019474
3.3457350077491026
Run Code Online (Sandbox Code Playgroud)

有条件:

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)"))
Run Code Online (Sandbox Code Playgroud)

收益率:

2.7942209702566965
3.0316467566203276
Run Code Online (Sandbox Code Playgroud)

所以条件listcomp仍然更快.

use*_*ica 12

列表推导不会预先确定列表的大小,即使它们完全可以.您假设存在未实际完成的优化.

列表理解更快,因为所有迭代器机制以及进入和退出genexp堆栈帧的工作都有成本.列表理解不需要支付该费用.

  • 那么,在预先分配清单方面会有实质性的收获吗?正如@ Jean-François所指出的那样,如果列表很大并且条件过滤掉了99%的元素,这可能会很糟糕",但是如果条件过滤掉只有1%的元素,它可能会很好*! (2认同)