我没想到这会起作用,因为我正在修改被迭代的对象,但我没想到它会以这种方式失败。我实际上预计会引发异常。
>>> x = [1, 2, 3]
>>> for a in x:
... print a, x.pop(0)
...
1 1
3 2
>>> x
[3]
范围稍大:
>>> x = [1, 2, 3, 4]
>>> for a in x:
... print a, x.pop(0)
...
1 1
3 2
>>> x
[3, 4]
还有点大一点:
>>> x = [1, 2, 3, 4, 5]
>>> for a in x:
... print a, x.pop(0)
...
1 1
3 2
5 3
>>> x
[4, 5]
就像for循环是从列表中创建一个生成器,但比较"索引"到列表的长度来决定何时迭代结束。
看起来这仍然会产生异常,而不是这种奇怪的行为。是否有某种原因它没有引发异常?
答案 0 :(得分:0)
正如您所知,for
循环在内部使用索引,在每次迭代时将其递增1,并在索引超出列表长度时停止。这就是为列表定义迭代的方式。它以其他方式为其他类型定义,您可以通过实现__iter__
为自己的类定义它。
在迭代时修改列表是合法的,并且一旦了解了它的工作原理就可以预测。删除一个或多个项目后,项目向下移动到较低的索引,如果删除的项目的索引小于或等于循环的当前索引,则在循环递增时最终跳过项目指数。
有许多解决方案:以相反顺序迭代,遍历副本,制作要删除的索引列表并单独执行,构建新列表而不是修改现有列表,使用{{1如果你有条件地删除项目,则循环而不是while
语句......也可能有其他方法。