问题
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
.
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'
.
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.
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'
.
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.
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'
.
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.
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'
.
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.
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