Python()

时间:2016-02-26 09:59:05

标签: python for-loop itertools

我正在调试编写代码的一部分,因此我使用了大量调用print来检查变量的值。我遇到过一种情况,当打印变量导致Python跳过for循环时。

import numpy as np
import itertools as itr
(...)

class myclass():
    def a_function_inside_a_class():
        print('-------------')
        current_size = self.get_current_size()
        current_size[dimension] += 1

        new_layer = [range(i) for i in current_size]
        new_layer[dimension] = [current_size[dimension]]
        print(new_layer)

        new_layer = itr.product(*new_layer)
        print(list(new_layer)) # THIS LINE CAUSES PROBLEMS

        for c in new_layer:
            print('for')
            print(list(c))
            (...)
            a_function_that_causes_some_error(c)

我创建一个列表,然后使用itertools创建此列表的组合,然后迭代它们。 如果我在上面调用a_function_inside_a_class()我没有打印for。不会发生错误。解释器不会进入循环。

(...)
-------------
[[2], range(0, 1), range(0, 1)]
[(2, 0, 0)]
-------------
[range(0, 1), [2], range(0, 1)]
[(0, 2, 0)]
(...)

但是,如果我注释掉#print(list(new_layer)) ,则执行for循环,我会收到由其他函数a_function_that_causes_some_error(c)引起的错误。

-------------
[[2], range(0, 1), range(0, 1)]
for
[2, 0, 0]
Traceback (most recent call last):
(...)

list(new_layer)不会更改new_layer对象本身,只会创建一个列表并将其传递给print()函数,是吗?

1 个答案:

答案 0 :(得分:5)

问题是itertools.product返回一个生成器。

当您致电print(list(new_layer))时,您正在构建一个来自生成器的列表,但不要在任何地方保存对该列表的引用。

生成器本身在将其转换为列表后会耗尽,因为list(some_generator)会在该生成器上调用__next__(或next,具体取决于Python版本),直到它升起{{1} }}

StopIteration

如您所见,构建列表一次后,生成器为空。

您可以使用

修复程序
>>> from itertools import product
>>> new_layer = product([1,2,3], [4,5,6])
>>> new_layer
<itertools.product object at 0x7f46e90349b0>
>>> print(list(new_layer))
[(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]
>>> print(list(new_layer))
[]

因为现在您将引用您从生成器创建的列表。