【发布时间】:2020-08-09 18:47:10
【问题描述】:
我在探索 Python 的 itertools 模块时遇到了 itertools.product 函数,它的返回值与 ((x,y) for x in A for y in B) 相同。我发现它是减少复杂for-loops 中的嵌套的一种非常巧妙的方法,其中列表理解可能不足。但是,在继续之前,我想检查它使用替代方法的性能。这是我进行的一些测试。使用 Jupyter Notebook 内置的%%timeit 来衡量性能。
case-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)
case-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)
case-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)
case-4:使用 itertools.product 进行 for 循环
%%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 循环更适合。
【问题讨论】:
-
case1 与案例 1 的比较不公平,在案例 1 中,您更早地进行过滤,当不是
x%2==0时跳过内部循环,因此您不会迭代整个产品。无论如何,我不明白为什么您认为案例 3 和案例 4 应该不同。他们的表现似乎与我所期望的基本相同。 -
我怀疑
itertools.product的较差性能是由于它创建了它需要的辅助列表,因为它接受任何可迭代,包括迭代器,它们是单通道.
标签: python python-3.x loops functional-programming itertools