迭代时修改列表

时间:2009-10-28 14:56:31

标签: python list iterator loops

l  = range(100)                         
for i in l:                         
    print i,                         
    print l.pop(0),                  
    print l.pop(0)

上面的python代码给出了与预期完全不同的输出。我想循环遍历项目,以便我可以在循环时跳过项目。

请解释。

7 个答案:

答案 0 :(得分:50)

永远不要改变你正在循环的容器,因为那个容器上的迭代器不会被告知你的改动,正如你所注意到的那样,很可能产生一个非常不同的循环和/或一个不正确的循环。在正常情况下,循环容器的副本会有所帮助,但在您的情况下很明显您想要那个,因为容器在循环的50个循环之后将是空的,如果你那么尝试再次弹出你会得到一个例外。

什么是明确的,你想要达到什么样的行为,如果有的话?!也许你可以用while ......来表达自己的欲望?

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

答案 1 :(得分:40)

我曾经被(别人的)“聪明”代码咬过,试图在迭代时修改列表。我决定在任何情况下都不会这样做。

您可以使用切片运算符mylist[::3]跳过列表中的每个第三项。

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

关于我的示例的其他要点与python 3.0中的新语法有关。

  • 我使用列表推导来定义mylist,因为它适用于Python 3.0(见下文)
  • print是python 3.0中的一个函数
  

Python 3.0 range()现在的行为类似于xrange(),但它适用于任意大小的值。后者不再存在。

答案 2 :(得分:11)

一般的经验法则是,在迭代它时不要修改集合/数组/列表。

使用辅助列表存储您要操作的项目,并在初始循环后循环执行该逻辑。

答案 3 :(得分:8)

试试这个。它避免了改变你正在迭代的东西,这通常是代码味道。

for i in xrange(0, 100, 3):
    print i

请参阅xrange

答案 4 :(得分:8)

使用while循环检查数组的真实性:

while array:
    value = array.pop(0)
    # do some calculation here

它应该没有任何错误或有趣的行为。

答案 5 :(得分:1)

我想这就是你想要的:

l  = range(100)  
index = 0                       
for i in l:                         
    print i,              
    try:
        print l.pop(index+1),                  
        print l.pop(index+1)
    except:
        pass
    index += 1

当要弹出的项目数是运行时决策时,编码非常方便。 但它的运行效率非常低,代码难以维护。

答案 6 :(得分:0)

此切片语法会复制列表并执行您想要的操作:

l  = range(100)  
for i in l[:]:  
    print i,  
    print l.pop(0),  
    print l.pop(0)