为什么在迭代时修改列表会导致跳过元素?

17 投票
8 回答
8785 浏览
提问于 2025-04-15 11:06

我现在正在用Python开发一个程序,最近发现语言中的foreach循环或者列表结构好像有点问题。为了简单起见,我就用一个通用的例子来说明我的问题,因为我在我的程序和这个例子中都遇到了同样的错误:

x = [1,2,2,2,2]

for i in x:
    x.remove(i)

print x        

问题很简单,我原以为这段代码是用来清空列表中所有元素的。但是执行后,我发现列表里总是剩下两个元素。

我哪里做错了呢?提前谢谢大家的帮助。

补充:我并不是想清空一个列表,这只是一个例子……

8 个回答

6

我觉得,简单来说,当你写:

for x in lst:
    # loop body goes here

在背后,Python 大概是这样工作的:

i = 0
while i < len(lst):
    x = lst[i]
    # loop body goes here
    i += 1

如果你把 lst.remove(x) 放在循环的主体里,也许你就能明白为什么会得到这样的结果?

其实,Python 是用一个移动的指针来遍历列表的。这个指针一开始指向第一个元素。然后你删除了第一个元素,这样第二个元素就成了新的第一个元素。接着,指针移动到新的第二个元素,也就是之前的第三个元素。然后继续这样下去。(如果你用 [1,2,3,4,5] 作为示例列表,可能会更清楚一些,而不是 [1,2,2,2,2])

10

当你删除一个元素时,循环会自动跳到下一个位置,这样就会漏掉一个元素。

可以试着从后往前删除。或者请说出你真正遇到的问题。

38

在Python中,有一个很明确的规则,就是在遍历一个列表的时候,不应该去修改这个列表。你可以试试下面的方法:

for i in x[:]:
    x.remove(i)

这里的[:]是用来获取x的一个“切片”,这个切片包含了x的所有元素,所以实际上就是x的一个副本。

撰写回答