itertools.product & list 理解之间的性能差异



我在探索Python的itertools模块时,发现了返回与((x,y) for x in A for y in B)相同的itertools.product函数。我发现这是一种非常巧妙的方法,可以减少复杂for-loops中列表理解可能不足的嵌套。然而,在继续之前,我想检查一下它是如何使用其他方法执行的。以下是我进行的一些测试。使用Jupyter Notebook内置的%%timeit来衡量性能。

案例1:香草清单理解

%%timeit -n 50 -r 5
[(x,y) for x in range(1000) if x%2==0 for y in range(1000) if y%2==1]
>>> 35.8 ms ± 1.3 ms per loop (mean ± std. dev. of 5 runs, 50 loops each)

案例2:列表理解中的itertools.product

删除了itertools导入以避免此处显示导入时间。

%%timeit -n 50 -r 5
[(x,y) for (x,y) in itertools.product(range(1000), range(1000)) if x%2==0 and y%2==1]
>>> 62.1 ms ± 1.16 ms per loop (mean ± std. dev. of 5 runs, 50 loops each)

案例3:香草嵌套for循环

%%timeit -n 50 -r 5
lst = []
for x in range(1000):
for y in range(1000):
if x%2 == 0 and y%2 == 1:
lst.append((x,y))
>>> 72 ms ± 769 µs per loop (mean ± std. dev. of 5 runs, 50 loops each)

案例4:使用itertools.product进行循环

%%timeit -n 50 -r 5
lst = []
for x, y in itertools.product(range(1000),range(1000)):
if x%2==0 and y%2==1:
lst.append((x,y))
>>> 74.5 ms ± 2.13 ms per loop (mean ± std. dev. of 5 runs, 50 loops each)

然而,我想,这部分文档声称比普通的for循环具有更好的性能。此外,case-2是否应该比case-1更快?在case3case 4中,随着可迭代项的大小增加,itertools.product的性能差异变得更差。这是怎么回事?此外,请添加一些示例,其中itertools.product可能比listcomp或嵌套循环更好。

您正在比较不同的东西:

[(x,y) for x in range(1000) if x%2==0 for y in range(1000) if y%2==1]

与不同

[(x,y) for x in range(1000) for y in range(1000) if x%2==0 and y%2==1]

如果x%2 != 0,则第一个循环完全跳过第二个循环,第二个则循环通过所有1000 ** 2 == 1,000,000组合。案例2至4与这里的第二理解属于同一类别,因此它们天生较慢。

最新更新