【问题标题】:Different ways of Iterating over a list迭代列表的不同方法
【发布时间】:2016-05-14 09:50:09
【问题描述】:

谁能告诉我这段代码有什么区别:

x = [1, 2, 3, 4, 5, 6, 7]
for i in x[:]:
    if i == 5:
        x.insert(0, i)

还有这段代码:

x = [1, 2, 3, 4, 5, 6, 7]
for i in x:
    if i == 5:
        x.insert(0, i)

为什么第二个不起作用?我知道 Python 教程中提到了它,但我不太明白。

【问题讨论】:

  • 为什么需要循环?只需 x.insert(0, 5) 就可以在这个例子中使用
  • 这不是重点,我正在尝试了解机制

标签: python list slice


【解决方案1】:

在第一个版本中,您创建一个副本(通过从头到尾分割列表),在第二个版本中,您将遍历原始列表。

如果您迭代一个容器,它的大小在迭代期间不能改变,这是有充分理由的(见下文)。但是由于您调用x.insert,您的列表大小会发生变化。


如果你执行第二个版本,它实际上并没有立即抛出错误,而是无限期地继续,越来越多的 5s 填满列表:

一旦您位于列表索引 4(因此 i 为 5),您将在列表的开头插入 5:

[5, 1, 2, 3, 4, 5, 6, 7]

然后继续循环,隐式将索引增加到 5,现在又是 5,因为由于您的插入,整个列表向右移动了一位,因此将再次插入 5:

[5, 5, 1, 2, 3, 4, 5, 6, 7]

这会“永远”持续下去(直到出现MemoryError)。

【讨论】:

  • 好的,但是如果我在最后添加“print(x)”,它会显示修改后的 x(x[0] 为 5),这表明 x 的大小确实实际改变
  • 另外 OP 应该注意这两种方法在 Python 3.x 中都不起作用
  • @kmario23 两者都在 Python 3 中工作,就像在 Python 2 中一样。
  • @JohnnyJohansson 在第二种情况下,您可以编辑x,因为您实际上并不是在迭代它,而是在一个副本上。
  • @kmario23 第一种方法似乎适用于 Python 3.5
猜你喜欢
  • 2015-01-20
  • 2018-02-02
  • 2016-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-12
  • 2012-05-03
  • 2018-10-13
相关资源
最近更新 更多