迭代时修改列表

Xol*_*lve 54 python iterator loops list

l  = range(100)                         
for i in l:                         
    print i,                         
    print l.pop(0),                  
    print l.pop(0)
Run Code Online (Sandbox Code Playgroud)

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

请解释.

Ale*_*lli 53

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

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

i = 0
while i < len(some_list):
    print i,                         
    print some_list.pop(0),                  
    print some_list.pop(0)
Run Code Online (Sandbox Code Playgroud)

  • @maq没必要.`pop`实际上删除了元素.所以你继续看元素'0'然后弹出它.按预期工作. (3认同)
  • 迭代器不拥有也不拥有任何项 - 它每次都需要为`next提供一个值时,它到达列表中(在迭代器的当前索引处***索引是迭代器拥有和保持的一件事) `(并在此之后还增加其内部迭代器). (3认同)
  • 等等,你应该在循环中增加 i 吗? (2认同)

Ewa*_*odd 42

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

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

mylist = [i for i in range(100)]
for i in mylist[::3]:
    print(i)
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • 如果需要列表对象,`list(range(100))`比这个徒劳的列表理解更快,更直接.此外,`for in in range(100)[:: 3]:`有效. (14认同)
  • 另外,如果你只想迭代整数,最好还是使用`range(0,100,3)`或甚至`xrange(0,100,3)`(后者不会在ram中创建完整列表) . (4认同)
  • @wsysuper尝试打印你的建议,你会明白为什么它不好:) (4认同)

Pau*_*sik 11

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

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


Han*_*Gay 8

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

for i in xrange(0, 100, 3):
    print i
Run Code Online (Sandbox Code Playgroud)

xrange.

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

小智 8

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

while array:
    value = array.pop(0)
    # do some calculation here
Run Code Online (Sandbox Code Playgroud)

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

  • 只需确保在每个循环中始终至少弹出一次. (3认同)