迭代时修改列表

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

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

请解释。

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

您可以使用切片运算符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()一样行为,除了可以处理任意大小的值。 后者不再存在。

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

什么是什么,但明确的是,你想达到什么样的行为,如果有的话? 也许你可以用一段whileexpression你的欲望…?

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

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

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

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

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

xrange

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

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

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

我想这是你想要的:

 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 

当要popup的项目的数量是一个运行时间决定时编写代码是非常方便的。 但是运行效率很差,代码难以维护。

这个切片语法使列表的副本,并做你想要的:

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