I find this example informative:
x = [n for n in range(1, 11)]
print('Before', x)
for i in x:
x.remove(i)
print('After', x)
Output:
Before [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
After [2, 4, 6, 8, 10]
Why is it removing every other number? It all makes sense if you rewrite the program like this:
x = [n for n in range(1, 11)]
print('Before', x)
i = 0
while i < len(x):
value = x[i]
x.remove(value)
print(i, value, x)
i += 1
print('After', x)
Output:
Before [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
0 1 [2, 3, 4, 5, 6, 7, 8, 9, 10]
1 3 [2, 4, 5, 6, 7, 8, 9, 10]
2 5 [2, 4, 6, 7, 8, 9, 10]
3 7 [2, 4, 6, 8, 9, 10]
4 9 [2, 4, 6, 8, 10]
After [2, 4, 6, 8, 10]
The first time through the loop the index is 0, and x[0] is removed from x. x is now one element shorter and all the values are shifted to the left.
The second time through the loop the index is 1. x[1] is 3, not 2. By removing a value from the list we changed the relationship between index and values, but the loop ignores this.
This same thing happened when I used
for i in x
. The for loop did not make a copy of the list and use that to iterate. The for loop must be using an index and an increment, just like the while loop example.
An easy solution is to use a copy of the list and use that to iterate:
x = [n for n in range(1, 11)]
print('Before', x)
i = 0
for i in x[:]:
x.remove(i)
print('After', x)
Output:
Before [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
After []