gpt4 book ai didi

python - 生成器与列表理解

转载 作者:太空宇宙 更新时间:2023-11-04 09:06:15 26 4
gpt4 key购买 nike

在下面的代码中,使用列表推导式还是生成器更好?

from itertools import izip
n=2
l=izip(xrange(10**n), xrange(10**n))
print 3 not in [x[0] for x in l]
#or
#print 3 not in (x[0] for x in l)

在这些测试中,如果列表很大,则生成器速度更快,如果列表较短,则列表理解显然更快。
这是因为理解只是计算机一次吗?
对于大型列表:generatorlistcomp
对于小列表:generatorlistcomp

最佳答案

in 针对生成器表达式将使用 __iter__() 方法并迭代表达式直到找到匹配项,使其在 general case 而不是列表推导式,后者在扫描结果以寻找匹配项之前首先生成整个列表。

您的特定示例的替代方法是使用 any(),以使测试更加明确。我发现这更具可读性:

any(x[0] == 3 for x in l)

您必须考虑到 in 确实转发了生成器;如果您还需要在其他地方使用生成器,则不能使用此方法。

至于你具体的时序测试;您的“简短”测试存在致命缺陷。 izip() 生成器的第一次迭代将完全耗尽,使其他 9999 次迭代针对 生成器进行测试。您正在测试在那里创建一个空列表和一个空生成器之间的区别,放大了创建成本的差异。

此外,您应该使用 timeit module运行测试,确保测试是可重复的。这意味着您也必须在每次迭代时创建一个新的 izip() 对象;现在对比度大得多:

>>> # Python 2, 'short'
...
>>> timeit.timeit("l = izip(xrange(10**2), xrange(10**2)); 3 not in (x[0] for x in l)", 'from itertools import izip', number=100000)
0.27606701850891113
>>> timeit.timeit("l = izip(xrange(10**2), xrange(10**2)); 3 not in [x[0] for x in l]", 'from itertools import izip', number=100000)
1.7422130107879639
>>> # Python 2, 'long'
...
>>> timeit.timeit("l = izip(xrange(10**3), xrange(10**3)); 3 not in (x[0] for x in l)", 'from itertools import izip', number=100000)
0.3002200126647949
>>> timeit.timeit("l = izip(xrange(10**3), xrange(10**3)); 3 not in [x[0] for x in l]", 'from itertools import izip', number=100000)
15.624258995056152

在 Python 3 上:

>>> # Python 3, 'short'
...
>>> timeit.timeit("l = zip(range(10**2), range(10**2)); 3 not in (x[0] for x in l)", number=100000)
0.2624585109297186
>>> timeit.timeit("l = zip(range(10**2), range(10**2)); 3 not in [x[0] for x in l]", number=100000)
1.5555254180217162
>>> # Python 3, 'long'
...
>>> timeit.timeit("l = zip(range(10**3), range(10**3)); 3 not in (x[0] for x in l)", number=100000)
0.27222433499991894
>>> timeit.timeit("l = zip(range(10**3), range(10**3)); 3 not in [x[0] for x in l]", number=100000)
15.76974998600781

在所有情况下,生成器变体都快得多;您必须将“短”版本缩短为只有 8 个元组,列表理解才能开始获胜:

>>> timeit.timeit("n = 8; l = izip(xrange(n), xrange(n)); 3 not in (x[0] for x in l)", 'from itertools import izip', number=100000)
0.2870941162109375
>>> timeit.timeit("n = 8; l = izip(xrange(n), xrange(n)); 3 not in [x[0] for x in l]", 'from itertools import izip', number=100000)
0.28503894805908203

在 Python 3 上,生成器表达式和列表推导式的实现更加接近,在列表推导式获胜之前,您必须减少到 4 项:

>>> timeit.timeit("n = 4; l = zip(range(n), range(8)); 3 not in (x[0] for x in l)", number=100000)
0.284480107948184
>>> timeit.timeit("n = 4; l = zip(range(n), range(8)); 3 not in [x[0] for x in l]", number=100000)
0.23570425796788186

关于python - 生成器与列表理解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20542849/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com