List 为什么要重复循环以删除列表中的项停止

List 为什么要重复循环以删除列表中的项停止,list,python-2.7,loops,indexing,List,Python 2.7,Loops,Indexing,Python新手,试图理解这个旨在从列表中删除所有项的迭代循环是如何处理列表中的索引的,以及为什么它会在哪里停止 为什么这个循环: foo = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] for i in foo: foo.remove(i) print foo 停在这里 ['b', 'd', 'f', 'h'] 而不是在这里 ['H'] 还有,这里的索引在“引擎盖下”发生了什么 在每次迭代中,Python都会跟踪下一个索引吗?同时,一

Python新手,试图理解这个旨在从列表中删除所有项的迭代循环是如何处理列表中的索引的,以及为什么它会在哪里停止

为什么这个循环:

foo = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
for i in foo:
    foo.remove(i)
    print foo
停在这里

['b', 'd', 'f', 'h']
而不是在这里

['H']
还有,这里的索引在“引擎盖下”发生了什么


在每次迭代中,Python都会跟踪下一个索引吗?同时,一旦一个项被删除,它就会将一个索引向左移动(这就是它跳过其他所有项的原因)

它从索引0开始,删除那里的“A”。然后移动到索引1,删除那里的“D”。(不是“C”,因为此时它在索引0处。)然后列表中只剩下两个项目,所以它不能继续移动到索引2,循环结束

也许可以使用持续到列表为空的
while
循环,而不是
for
循环

foo = ['A', 'C', 'D', 'E']
while foo:
    foo.pop(0)
    print foo
。。。或者,您可以在列表的副本上迭代,当您修改
foo
时,列表不会从下方更改。当然,这需要一点额外的内存

foo = ['A', 'C', 'D', 'E']
for i in foo[:]:
    foo.remove(i)
    print foo

它从索引0开始,删除那里的“A”。然后移动到索引1,删除那里的“D”。(不是“C”,因为此时它在索引0处。)然后列表中只剩下两个项目,所以它不能继续移动到索引2,循环结束

也许可以使用持续到列表为空的
while
循环,而不是
for
循环

foo = ['A', 'C', 'D', 'E']
while foo:
    foo.pop(0)
    print foo
。。。或者,您可以在列表的副本上迭代,当您修改
foo
时,列表不会从下方更改。当然,这需要一点额外的内存

foo = ['A', 'C', 'D', 'E']
for i in foo[:]:
    foo.remove(i)
    print foo

为了理解为什么会发生这种情况,让我们一步一步地看看内部发生了什么。

第1步:

>>> foo = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
>>> for i in foo:
>>> foo.remove(i)
>>> print foo
['b', 'd', 'e', 'f', 'g', 'h']
>>> for i in foo:
>>> foo.remove(i)
>>> print foo
['b', 'd', 'f', 'g', 'h']
>>> for i in foo:
>>> foo.remove(i)
>>> print foo
['b', 'd', 'f', 'h']
在这里,将创建一个新的列表对象,并将其分配给
foo

第二步:

>>> for i in foo:
现在,迭代开始了
i
循环变量被分配到索引0处的项的值,即
'a'

第三步:

>>> foo.remove(i)
>>> print foo
['b', 'c', 'd', 'e', 'f', 'g', 'h']
现在,
.remove(i)
执行
.remove(foo[0])
而不是
.remove('a')
。新列表现在在索引0处有
'b'
,在索引1处有
'c'
,依此类推

第4步:

>>> foo = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
>>> for i in foo:
>>> foo.remove(i)
>>> print foo
['b', 'd', 'e', 'f', 'g', 'h']
>>> for i in foo:
>>> foo.remove(i)
>>> print foo
['b', 'd', 'f', 'g', 'h']
>>> for i in foo:
>>> foo.remove(i)
>>> print foo
['b', 'd', 'f', 'h']
对于下一次迭代,
i
循环变量被分配到索引1处的项的值,该值当前为
'c'

第五步:

>>> foo = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
>>> for i in foo:
>>> foo.remove(i)
>>> print foo
['b', 'd', 'e', 'f', 'g', 'h']
>>> for i in foo:
>>> foo.remove(i)
>>> print foo
['b', 'd', 'f', 'g', 'h']
>>> for i in foo:
>>> foo.remove(i)
>>> print foo
['b', 'd', 'f', 'h']
现在,这次,
.remove(i)
执行从列表中删除
.remove(foo[1])
的操作。当前列表现在在索引0处有
'b'
,在索引1处有
'd'
,依此类推

第6步:

>>> foo = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
>>> for i in foo:
>>> foo.remove(i)
>>> print foo
['b', 'd', 'e', 'f', 'g', 'h']
>>> for i in foo:
>>> foo.remove(i)
>>> print foo
['b', 'd', 'f', 'g', 'h']
>>> for i in foo:
>>> foo.remove(i)
>>> print foo
['b', 'd', 'f', 'h']
对于下一次迭代,
i
循环变量被分配到索引2处的项的值,该值当前为
'e'

第7步:

>>> foo = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
>>> for i in foo:
>>> foo.remove(i)
>>> print foo
['b', 'd', 'e', 'f', 'g', 'h']
>>> for i in foo:
>>> foo.remove(i)
>>> print foo
['b', 'd', 'f', 'g', 'h']
>>> for i in foo:
>>> foo.remove(i)
>>> print foo
['b', 'd', 'f', 'h']
现在,这次,
.remove(i)
执行从列表中删除
.remove(foo[2])
的操作。类似地,项目的索引也会像上面的步骤5中那样更改

第8步:

>>> foo = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
>>> for i in foo:
>>> foo.remove(i)
>>> print foo
['b', 'd', 'e', 'f', 'g', 'h']
>>> for i in foo:
>>> foo.remove(i)
>>> print foo
['b', 'd', 'f', 'g', 'h']
>>> for i in foo:
>>> foo.remove(i)
>>> print foo
['b', 'd', 'f', 'h']
对于下一次迭代,
i
循环变量被分配到索引3处的项的值,该值当前为
'g'

第9步:

>>> foo = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
>>> for i in foo:
>>> foo.remove(i)
>>> print foo
['b', 'd', 'e', 'f', 'g', 'h']
>>> for i in foo:
>>> foo.remove(i)
>>> print foo
['b', 'd', 'f', 'g', 'h']
>>> for i in foo:
>>> foo.remove(i)
>>> print foo
['b', 'd', 'f', 'h']
现在,这次,
.remove(i)
执行从列表中删除
.remove(foo[3])
的操作

步骤10:

>>> for i in foo:
现在,
i
应该指向索引4处的项,但是由于原始列表已减少为4个元素,因此执行将在此处停止

>>> foo
['b', 'd', 'f', 'h']
以上是执行后的最终列表

一些结论:

  • 在对列表进行迭代时,切勿更改列表的长度。简单地说,在对原始列表进行迭代时,请勿修改原始列表

  • 在列表中迭代执行
    .remove()
    时,循环变量将使用索引而不是原始列表中的实际项引用列表项


    • 为了理解为什么会发生这种情况,让我们一步一步地看看内部发生了什么。

      第1步:

      >>> foo = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
      
      >>> for i in foo:
      
      >>> foo.remove(i)
      >>> print foo
      ['b', 'd', 'e', 'f', 'g', 'h']
      
      >>> for i in foo:
      
      >>> foo.remove(i)
      >>> print foo
      ['b', 'd', 'f', 'g', 'h']
      
      >>> for i in foo:
      
      >>> foo.remove(i)
      >>> print foo
      ['b', 'd', 'f', 'h']
      
      在这里,将创建一个新的列表对象,并将其分配给
      foo

      第二步:

      >>> for i in foo:
      
      现在,迭代开始了
      i
      循环变量被分配到索引0处的项的值,即
      'a'

      第三步:

      >>> foo.remove(i)
      >>> print foo
      ['b', 'c', 'd', 'e', 'f', 'g', 'h']
      
      现在,
      .remove(i)
      执行
      .remove(foo[0])
      而不是
      .remove('a')
      。新列表现在在索引0处有
      'b'
      ,在索引1处有
      'c'
      ,依此类推

      第4步:

      >>> foo = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
      
      >>> for i in foo:
      
      >>> foo.remove(i)
      >>> print foo
      ['b', 'd', 'e', 'f', 'g', 'h']
      
      >>> for i in foo:
      
      >>> foo.remove(i)
      >>> print foo
      ['b', 'd', 'f', 'g', 'h']
      
      >>> for i in foo:
      
      >>> foo.remove(i)
      >>> print foo
      ['b', 'd', 'f', 'h']
      
      对于下一次迭代,
      i
      循环变量被分配到索引1处的项的值,该值当前为
      'c'

      第五步:

      >>> foo = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
      
      >>> for i in foo:
      
      >>> foo.remove(i)
      >>> print foo
      ['b', 'd', 'e', 'f', 'g', 'h']
      
      >>> for i in foo:
      
      >>> foo.remove(i)
      >>> print foo
      ['b', 'd', 'f', 'g', 'h']
      
      >>> for i in foo:
      
      >>> foo.remove(i)
      >>> print foo
      ['b', 'd', 'f', 'h']
      
      现在,这次,
      .remove(i)
      执行从列表中删除
      .remove(foo[1])
      的操作。当前列表现在在索引0处有
      'b'
      ,在索引1处有
      'd'
      ,依此类推

      第6步:

      >>> foo = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
      
      >>> for i in foo:
      
      >>> foo.remove(i)
      >>> print foo
      ['b', 'd', 'e', 'f', 'g', 'h']
      
      >>> for i in foo:
      
      >>> foo.remove(i)
      >>> print foo
      ['b', 'd', 'f', 'g', 'h']
      
      >>> for i in foo:
      
      >>> foo.remove(i)
      >>> print foo
      ['b', 'd', 'f', 'h']
      
      对于下一次迭代,
      i
      循环变量被分配到索引2处的项的值,该值当前为
      'e'

      第7步:

      >>> foo = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
      
      >>> for i in foo:
      
      >>> foo.remove(i)
      >>> print foo
      ['b', 'd', 'e', 'f', 'g', 'h']
      
      >>> for i in foo:
      
      >>> foo.remove(i)
      >>> print foo
      ['b', 'd', 'f', 'g', 'h']
      
      >>> for i in foo:
      
      >>> foo.remove(i)
      >>> print foo
      ['b', 'd', 'f', 'h']
      
      现在,这次,
      .remove(i)
      执行从列表中删除
      .remove(foo[2])
      的操作。类似地,项目的索引也会像上面的步骤5中那样更改

      第8步:

      >>> foo = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
      
      >>> for i in foo:
      
      >>> foo.remove(i)
      >>> print foo
      ['b', 'd', 'e', 'f', 'g', 'h']
      
      >>> for i in foo:
      
      >>> foo.remove(i)
      >>> print foo
      ['b', 'd', 'f', 'g', 'h']
      
      >>> for i in foo:
      
      >>> foo.remove(i)
      >>> print foo
      ['b', 'd', 'f', 'h']
      
      对于下一次迭代,
      i
      循环变量被分配到索引3处的项的值