【问题标题】:Python nested for loop behaviourPython 嵌套的 for 循环行为
【发布时间】:2013-08-09 02:57:39
【问题描述】:

我在嵌套 for 循环中遇到了这种奇怪的行为,我无法解释这一点。这是特定于 python 的事情还是我只是在监督一些事情?

这是我正在运行的代码:

for i in range(16):
    if i == 0:
        for j in range(8):
            print 'i is (if) ' + str(i)
            i = i + 1
    else:
        print 'i is (else)' + str(i)

这是我得到的输出:

i is (if) 0
i is (if) 1
i is (if) 2
i is (if) 3
i is (if) 4
i is (if) 5
i is (if) 6
i is (if) 7
i is (else)1
i is (else)2
i is (else)3
i is (else)4
i is (else)5
i is (else)6
i is (else)7
i is (else)8
i is (else)9
i is (else)10
i is (else)11
i is (else)12
i is (else)13
i is (else)14
i is (else)15

这是我期待的输出:

i is (if) 0
i is (if) 1
i is (if) 2
i is (if) 3
i is (if) 4
i is (if) 5
i is (if) 6
i is (if) 7
i is (else)8
i is (else)9
i is (else)10
i is (else)11
i is (else)12
i is (else)13
i is (else)14
i is (else)15

看起来外部 for 循环中的 i 和内部 for 循环中的 i 是不同的变量,尽管这对我来说似乎完全违反直觉。

任何输入(我对 python 还很陌生,但找不到这方面的文档)

【问题讨论】:

  • +1个关于理解python中变量范围的聪明问题

标签: python for-loop nested-loops


【解决方案1】:

for 循环每次循环迭代都会为i 分配一个 值,即从循环可迭代中获取的下一个值(在本例中为range(16)

您可以在循环本身中修改i,但这不会改变正在使用的可迭代for

如果你想改变循环迭代,那么你必须这样做直接在迭代:

loop_iterable = iter(range(16))
for i in loop_iterable:
    if i == 0:
        for j in range(8):
            print 'i is (if) ' + str(i)
            i = next(loop_iterable)
    else:
        print 'i is (else)' + str(i)

在这里,我们使用iter() functionrange(10) 序列创建一个iterator objectfor 语句在底层做了完全相同的事情,但现在我们可以直接处理迭代器。 next() function 将迭代器推进到下一个值,就像 for 循环所做的那样。

不过,改用while 循环可能更容易:

i = 0
while i < 16:
    if i == 0:
        for j in range(8):
            print 'i is (if) ' + str(i)
            i = next(loop_iterable)
    else:
        print 'i is (else)' + str(i)
    i += 1

要记住的是,Python for 循环语句没有类似于 C 或 Java 或 JavaScript for 循环。它是Foreach looprange() 只是生成要循环的数字序列,而不是 C 风格的 for 循环,它结合了初始赋值 (i = 0)、测试 (i &lt; 16)) 和循环增量器 (i += 1)成一个语句。

【讨论】:

  • 作为更详细的解释,据我了解,发生的事情是 range 函数返回一个可迭代的,即可以变成列表的东西,所以你在循环中所做的事情正在过去列表中的每个值。因此,您可以对该变量执行任何操作,因为当您再次迭代循环时,它只会从 range 函数提供的“列表”中的下一个“索引”中获取值。
  • @Amndeep7:在 Python 2 中,range() 返回一个列表,在 Python 3 中或使用 xrange() 时返回一个专用范围对象。列表和范围对象都是可迭代的(它们是序列),但它们不是迭代器
  • @Amndeep7:在列表或范围对象上调用iter()会返回一个专门的迭代器对象,该对象知道如何处理这两种类型,每次请求下一个值时都会保持当前位置提前.
  • @MartijnPieters,首先,我没有提到我在谈论 Python3,第二,我不认为我说 range 函数是一个迭代器。我说过您可以使用for 对可迭代对象(在本例中为范围对象)进行迭代。为了进一步澄清,我不应该使用“即”。因为列表是返回的范围,但通常是其使用的最终结果。
猜你喜欢
  • 1970-01-01
  • 2012-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多