我对在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
它只对外循环的第一个值执行内循环,为什么会发生这种情况?如何让它循环遍历第一个和第二个变量的所有组合?
答案 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()
documentation的iterator 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这样的简单情况下,列表很短,你知道你将遍历所有元素,因此使用列表简单而有效。