Itertools而不是嵌套循环

时间:2017-04-10 20:51:29

标签: python python-3.x loops itertools

list_a = [] 
for color in [True,False]:
    for piece in range(1,7):
        list_a = list_a + function(piece,color)

这里function(piece,color)返回一个列表,我想加入并最终返回长列表,可以在这里使用itertools.chain吗?因为我觉得它可能会更快。我只显示一个示例,但在我的实际代码中,循环运行大约100,000次,这就是为什么我在寻找更快的方法。

4 个答案:

答案 0 :(得分:5)

我将回答你应该问的问题; - )

此:

list_a = list_a + function(piece,color)

在执行次数上花费时间二次。每次都会创建一个全新的列表对象,复制旧的list_a和新列表。

因此,如果它被执行了很多次,你可以通过改变它来获得巨大的改进:

list_a.extend(function(piece,color))

然后list_a尽可能“延伸”到位;在封面下,可能需要不时地复制到更大的存储区域,但总体而言,摊销时间在执行的次数上是线性的。

答案 1 :(得分:2)

如果确实想要使用itertools.chain

>>> from itertools import product, chain
>>> list_a = list(chain.from_iterable(function(piece, color) for piece, color in product([True, False], range(1, 7))))

当然,如果你使用list_a += function(piece, color),这可能会同样快(也许更快?)。

list_a = list_a + function(piece, color)的问题是该行在其输入中是二次,因为它构建了一个全新的列表,而list_a += function(piece, color)相当于使用{{1}对于Python列表,它是分摊的常量时间,因此内部部分保持线性而不是二次。

答案 2 :(得分:1)

yield from似乎是这里的简单解决方案。

def generator():
    for color in [True,False]:
        for piece in range(1,7):
            yield from function(piece,color)

答案 3 :(得分:0)

您可以使用itertools.starmap,虽然您仍然拥有循环,但您无法逃脱它们:

result_generator = starmap(function, ((piece, color) for piece in range(1,7) for color in [True,False]))

list_a = list(result_generator)

然后,像这样使用itertools.product

result_generator = starmap(function, product(range(1,7), [True,False]))