Don't loop over a list you are removing items from. The for
loop creates a list iterator that keeps track of the current item by incrementing a counter. But a shrinking list means that the counter will, from loop iteration to loop iteration, point at the wrong item:
>>> lst = range(5)
>>> for i in lst:
... lst.remove(i)
... print i
...
0
2
4
>>> lst
[1, 3]
What happens is that as you remove 0
from the list [0, 1, 2, 3, 4]
, the counter increments to item 1
, which in the now-altered list [1, 2, 3, 4]
points to the value 2
. Removing 2
from the list, the iterator count increments to 2
and in the altered list [1, 3, 4]
that means the next value in the loop is 4
, after which the iterator counter has counted beyond the end and the loop terminates.
If you are going to remove all items from the list, use a while loop:
while numbers:
n = numbers.pop()
# do something with `n`
If you are removing some items, another option would be to create a shallow copy:
for n in numbers[:]:
# ....
Now you can alter numbers
to your hearts content, as the for
loop is iterating over a copy instead.