嵌套for循环:为什么内循环只执行一次?

时间:2017-04-23 14:48:19

标签: python loops for-loop nested reverse

我对在python中使用double for循环感到困惑,这是我的代码:

import numpy as np

range1 = np.linspace(1,6,10)
range2 = reversed(np.linspace(1,6,10))

for t1 in range1:
    print t1
    for t2 in range2:
        print t1,t2

输出是这样的:

1.0
1.0 6.0
1.0 5.44444444444
1.0 4.88888888889
1.0 4.33333333333
1.0 3.77777777778
1.0 3.22222222222
1.0 2.66666666667
1.0 2.11111111111
1.0 1.55555555556
1.0 1.0
1.55555555556
2.11111111111
2.66666666667
3.22222222222
3.77777777778
4.33333333333
4.88888888889
5.44444444444
6.0

它只对外循环的第一个值执行内循环,为什么会发生这种情况?如何让它循环遍历第一个和第二个变量的所有组合?

3 个答案:

答案 0 :(得分:10)

reversed()生成迭代器;一旦到达迭代器的末尾,就无法重复使用它:

>>> it = reversed([1, 2, 3])
>>> list(it)
[3, 2, 1]
>>> list(it)
[]

为嵌套循环创建一个新的迭代器:

for t1 in range1:
    print t1
    for t2 in reversed(range1):
        print t1,t2

reversed() documentationiterator glossary entry链接:

  

当没有更多数据可用时,会引发StopIteration异常。 此时,迭代器对象已用尽,对其__next__()方法的任何进一步调用再次引发StopIteration

大胆强调我的。

答案 1 :(得分:4)

在每个尊重pythons数据模型的实现中,reversed的结果只能耗尽一次(因为它应该返回在第一次遍历后耗尽的迭代器)。在迭代器耗尽之后,它将不再yield任何项目。但你可以使用切片简单地反转你的数组:

range2 = np.linspace(1,6,10)[::-1]

for t1 in range1:
    print t1
    for t2 in range2:
        print t1,t2

numpy.array的基本切片非常高效,甚至不需要复制原始文件。

鉴于您使用array,您应该知道迭代它们是一个非常慢的操作,因为在迭代期间每个值都需要取消装箱。如果您确实需要来迭代一维array(提示:您通常不会),则应将它们转换为list s:

range1 = np.linspace(1,6,10).tolist()
range2 = np.linspace(1,6,10)[::-1].tolist()

tolist - 循环中的(隐式)拆箱相比,for在拆箱时效率更高。

答案 2 :(得分:2)

reversed返回一个迭代器。迭代器只能被使用一次。

在第一次迭代期间使用该迭代器。

要多次使用迭代器,可以将其存储在list

import numpy as np

range1 = np.linspace(1,6,10)
range2 = list(reversed(np.linspace(1,6,10)))  # store in list

for t1 in range1:
    print t1
    for t2 in range2:
        print t1,t2

迭代器的一个好处是永远不会计算整个列表。您可以迭代超过一百万个元素而无需创建整个[0, 1, ..., 1000000]列表,如果您的算法在条件满足时希望突破循环,则会更好。

在OP这样的简单情况下,列表很短,你知道你将遍历所有元素,因此使用列表简单而有效。