简体   繁体   English

python如何优化条件列表推导

[英]How does python optimize conditional list comprehensions

I read about List comprehension without [ ] in Python so now I know that 在Python中没有[]读过关于列表理解的内容,所以现在我知道了

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

is faster than 比...更快

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

because "list comprehensions are highly optimized" 因为“列表推导得到高度优化”

So I suppose that the optimization relies on the parsing of the for expression, sees mylist , computes its length, and uses it to pre-allocate the exact array size, which saves a lot of reallocation. 所以我认为优化依赖于for表达式的解析,看到mylist ,计算它的长度,并使用它来预先分配精确的数组大小,这节省了大量的重新分配。

When using ''.join(str(x) for x in mylist) , join recieves a generator blindly and has to build its list without knowing the size in advance. 当使用''.join(str(x) for x in mylist)join盲目接收生成器,并且必须在不事先知道大小的情况下构建其列表。

But now consider this: 但现在考虑一下:

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

How does python decide of the size of the list comprehension? python如何决定列表理解的大小? Is it computed from the size of mylist , and downsized when iterations are done (which could be very bad if the list is big and the condition filters out 99% of the elements), or does it revert back to the "don't know the size in advance" case? 它是根据mylist的大小计算的,并且在迭代完成时缩小(如果列表很大并且条件过滤掉99%的元素可能非常糟糕),或者它是否会恢复为“不知道”提前大小“案例?

EDIT: I've done some small benchmarks and it seems to confirm that there's an optimization: 编辑:我做了一些小基准测试,似乎确认有一个优化:

without a condition: 没有条件:

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])"))

yields (as expected): 收益率(如预期):

3.11010817019474
3.3457350077491026

with a condition: 有条件:

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)"))

yields: 收益率:

2.7942209702566965
3.0316467566203276

so conditional listcomp still is faster. 所以条件listcomp仍然更快。

List comprehensions don't pre-size the list, even when they totally could. 列表推导不会预先确定列表的大小,即使它们完全可以。 You're assuming the presence of an optimization that isn't actually done. 您假设存在未实际完成的优化。

The list comprehension is faster because all the iterator machinery and the work of entering and exiting the genexp stack frame has a cost. 列表理解更快,因为所有迭代器机制以及进入和退出genexp堆栈帧的工作都有成本。 The list comprehension doesn't need to pay that cost. 列表理解不需要支付该费用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM