在迭代时修改列表

77 投票
7 回答
157339 浏览
提问于 2025-04-15 15:27
l  = range(100)                         
for i in l:                         
    print i,                         
    print l.pop(0),                  
    print l.pop(0)

上面的Python代码的输出结果和我预期的差别很大。我想在循环中遍历这些项目,这样我就可以在循环的时候跳过某个项目。

请解释一下。

7 个回答

20

一般来说,规则是你在遍历一个集合、数组或列表的时候,不要去修改它。

可以使用一个额外的列表来存放你想要处理的项目,然后在第一次遍历结束后,再用一个循环来执行你的操作。

79

在循环的时候,千万不要修改你正在遍历的容器,因为这个容器里的迭代器不会知道你做的修改。正如你所发现的,这样很可能会导致循环的结果完全不同或者出现错误。在正常情况下,遍历容器的一个副本是有帮助的,但在你的情况中,很明显你想这样,因为在循环进行到50次的时候,容器会变空,如果你再尝试去取出元素,就会出现错误。

不过,有一点是非常不清楚的,那就是你到底想要实现什么样的行为?如果有的话,或许你可以用一个while循环来表达你的需求?

i = 0
while i < len(some_list):
    print i,                         
    print some_list.pop(0),                  
    print some_list.pop(0)
51

我之前遇到过别人写的“聪明”的代码,它在遍历一个列表的时候试图修改这个列表,结果让我很受伤。所以我下定决心,无论如何都不再这样做了。

你可以使用切片操作符 mylist[::3] 来跳过列表中的每三个项目,直接取出每第三个元素。

mylist = [i for i in range(100)]
for i in mylist[::3]:
    print(i)

我这个例子中的其他内容跟 Python 3.0 的新语法有关。

  • 我用列表推导式来定义 mylist,因为它在 Python 3.0 中可以用(见下面的内容)
  • 在 Python 3.0 中,print 变成了一个函数

在 Python 3.0 中,range() 的行为和以前的 xrange() 一样,不过它可以处理任意大小的数值。而 xrange() 已经不再存在了。

撰写回答