我正在研究Python的itertools
模块,并遇到了itertools.product
函数,该函数返回的内容与((x,y) for x in A for y in B)
相同。我发现这是减少列表理解可能不足的复杂for-loops
中嵌套的一种真正好方法。但是,在继续之前,我想检查一下其他方法的效果。这是我进行的一些测试。使用Jupyter Notebook的内置%%timeit
来衡量性能。
%%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)
已删除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)
%%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)
%%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)
但是,我想文档的this部分声称比普通的for
循环具有更好的性能。另外,case-2是否应该比case-1快?在case-3和case-4中,itertools.product
的性能差异随着可迭代项的大小增加而变差。这里发生了什么?另外,请添加一些示例,其中itertools.product
可能比listcomp或嵌套for循环更好。
您正在比较不同的事物:
[(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与此处的第二个理解属于同一类别,因此它们本质上较慢。