itertools.product 和循环之间的区别

Difference between itertools.product and loops

提问人:mohamednegm 提问时间:9/13/2023 最后编辑:user4157124mohamednegm 更新时间:9/14/2023 访问量:175

问:

使用更好吗:

for i, j in itertools.product(range(3), range(3)):
    #code here

或:

for i in range(3):
    for j in range(3):
        #code here

Sourcery.ai 重构建议将嵌套循环更改为 to 。它有更好的性能吗?range()itertools.product()

性能 循环 python-itertools

评论


答:

-1赞 Shah Wali 9/13/2023 #1

itertools.product和 Python 中的普通循环都用于从多个输入序列生成元素组合,但它们在便利性、内存使用和性能方面有所不同。

  1. 便利性

    • itertools.product是一个 Python 库函数,它提供了一种简单简洁的方法来生成笛卡尔乘积组合。它消除了显式编写嵌套循环的需要,使代码更具可读性,更不容易出错。
    • 普通循环要求显式编写嵌套循环,这可能容易出错且更难读取,尤其是在处理多个输入序列时。
  2. 内存使用情况

    • itertools.product延迟生成组合,这意味着它不会一次创建所有组合并将它们存储在内存中。相反,它会在您迭代每个组合时动态生成它们。在处理大量组合时,这可以节省内存。
    • 如果要构建列表或其他数据结构来保存所有组合,则正常循环可能需要将所有组合存储在内存中,这可能会导致大型输入的内存使用率过高。
  3. 性能

    • itertools.product在 C 语言中实现,并针对性能进行了高度优化。它可能比手动编写嵌套循环更快,尤其是对于大型输入序列。
    • 普通循环虽然灵活,但可能不像 那样优化,它们的性能可能取决于实现它们的特定方式。itertools.product

下面是一个简单的示例来说明其中的区别:

用:itertools.product


    from itertools import product
    
    a = [1, 2]
    b = ['a', 'b']
    
    combinations = list(product(a, b))
    print(combinations)

使用普通循环:


    a = [1, 2]
    b = ['a', 'b']
    
    combinations = []
    for x in a:
        for y in b:
            combinations.append((x, y))
    
    print(combinations)

这两种方法都会得到相同的结果,但使用的代码更简洁、更节省内存,尤其是在处理较大的输入序列时。因此,对于涉及笛卡尔乘积或多个输入序列组合的任务,通常是首选。itertools.productitertools.product

评论

1赞 DavidW 9/15/2023
您能解释一下为什么 itertools 需要更少的内存吗?在你给出的例子中,它们几乎是一样的。
1赞 DavidW 9/15/2023
实际上这不是真的 - itertools 使用稍微多一点的内存,因为它会复制并且何时启动。ab
1赞 sjking 9/13/2023 #2

如果要避免循环嵌套,或者要生成某些可迭代对象的笛卡尔积,则使用它非常有用。在这种情况下,可以提高代码的可读性,而不是嵌套的for循环。itertools.productitertools.product

在内存消耗方面,使用嵌套的 for 循环不再有任何实际优势。Python 3 中的 A 使用常量内存,无论它表示的范围大小如何。它只需要存储开始、停止和步进值,并生成延迟循环迭代所需的值。itertools.productrangerange

就运行时性能而言,我做了一个简单的测试,嵌套的for循环使用似乎比在紧密循环中更快:rangeitertools.product

>>> def loop():
...   for i in range(1000):
...     for j in range(1000):
...       pass
... 
>>> timeit.timeit(loop, number=300)
2.2965646009997727
>>> def itertools_product():
...   for i, j in itertools.product(range(1000), range(1000)):
...     pass
...
>>> timeit.timeit(itertools_product, number=300)
2.8750368439996237

评论

0赞 Kelly Bundy 9/15/2023
“在内存消耗方面,使用 itertools.product 而不是嵌套的 for 循环没有实际优势”——为什么是“不再”?曾经有过吗?
0赞 sjking 9/15/2023
@KellyBundy 在 Python 2 中,a 被急切地评估为列表。看这个问题:stackoverflow.com/questions/23221025/...range
0赞 Kelly Bundy 9/16/2023
是的,但也要这样做。(好吧,不是列表,而是元组,但这需要大约相同的内存。itertools.product