Why iterative loop to remove items in list stops

梦想的初衷 提交于 2020-12-04 09:18:39

问题


New to Python, trying to understand how this iterative loop that is intended to remove all items form the list is handling the indexes in the list and why it stops where it does...

Why does this loop:

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

Stop here?

['b', 'd', 'f', 'h']

Instead of here?

['H']

Also, what's happening "under the hood" with the indexes here?

With every iteration, is Python keeping track of which index is next while at the same time, once an item is removed the item to its right moves one index to the left (and that's why it's skipping every other item)?


回答1:


To understand why this is happening, let us look step-by-step what is happening internally.

Step 1:

>>> foo = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']

Here, a new list object is created and is assigned to foo.

step1

Step 2:

>>> for i in foo:

Now, the iteration starts. i loop variable is assigned the value of item at index 0 which is 'a'.

step2

Step 3:

>>> foo.remove(i)
>>> print foo
['b', 'c', 'd', 'e', 'f', 'g', 'h']

Now, .remove(i) performs .remove(foo[0]) and not .remove('a') apparently. The new list now has 'b' at index 0, 'c' at index 1 and so on.

Step3

Step 4:

>>> for i in foo:

For the next iteration, i loop variable is assigned the value of item at index 1 which is currently 'c'.

step4

Step 5:

>>> foo.remove(i)
>>> print foo
['b', 'd', 'e', 'f', 'g', 'h']

Now this time, .remove(i) performs .remove(foo[1]) which removes 'c' from the list. The current list now has 'b' at index 0, 'd' at index 1 and so on.

step5

Step 6:

>>> for i in foo:

For the next iteration, i loop variable is assigned the value of item at index 2 which is currently 'e'.

step6

Step 7:

>>> foo.remove(i)
>>> print foo
['b', 'd', 'f', 'g', 'h']

Now this time, .remove(i) performs .remove(foo[2]) which removes 'e' from the list. Similarly, the indices of the items gets changed as in step 5 above.

step7

Step 8:

>>> for i in foo:

For the next iteration, i loop variable is assigned the value of item at index 3 which is currently 'g'.

step8

Step 9:

>>> foo.remove(i)
>>> print foo
['b', 'd', 'f', 'h']

Now this time, .remove(i) performs .remove(foo[3]) which removes 'g' from the list.

step9

Step 10:

>>> for i in foo:

Now, i should point to item at index 4 but since the original list has been reduced to 4 elements, the execution will stop here.

>>> foo
['b', 'd', 'f', 'h']

Above is the final list after execution.

SOME CONCLUSIONS:

  • NEVER CHANGE THE LENGTH OF LISTS WHILE ITERATING ON THEM. In simple words, don't modify the original list while performing iteration on it.

  • When performing .remove() in a list iteratively, the loop variable will refer to the list item using indexes and not by the actual items in the original list.




回答2:


It starts at index zero, removing the "A" there. It then moves to index one, removing the "D" there. (not "C", because that's at index zero at this point.) Then there are only two items left in the list, so it can't move on to index two, and the loop ends.

Perhaps instead of a for loop, you could use a while loop that continues until the list is empty.

foo = ['A', 'C', 'D', 'E']
while foo:
    foo.pop(0)
    print foo

... Or you could iterate over a copy of the list, which won't change from underneath you as you modify foo. Of course, this uses a little extra memory.

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


来源:https://stackoverflow.com/questions/30651715/why-iterative-loop-to-remove-items-in-list-stops

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!