Iterating list in "for" loop, with deletions, skips members

I create the list and print one member at a time and delete each.
Why is it skipping all the odd numbers?
code
L = [1,2,3,4,5,6,7,8]
for x in L:
print(x)
L.remove(x)
print(L)
output
1
[2, 3, 4, 5, 6, 7, 8]
3
[2, 4, 5, 6, 7, 8]
5
[2, 4, 6, 7, 8]
7
[2, 4, 6, 8]

It is skipping the even (not odd) numbers because you are deleting
items, which moves the remaining items back one position.

Let’s take a simpler example:

L = [1, 2, 3]

When you iterate over L, there is an internal counter that points to the
current position in the list. That position starts at 0:

for x in L: ...

which gives x = 1. So you have:

Step 1:

  • position 0
  • L = [1, 2, 3]
  • x = 1

Step 2: remove x from L

  • position is still 0
  • L = [2, 3]

Step 3: advance to the next position

  • position → 1
  • L = [2, 3]
  • so x = 3

and you skipped 2.

The lesson here is:

Never modify a list while you are iterating over it.

For experts only: you can safely modify the list if you walk through the
list backwards, removing items only from the end you have already
visited. But if you’re an expert, you will also know that doing that is
much more complicated and slower, so experts know enough to know that
they rarely want to do it that way.

Instead, you should iterate over a temporary copy:

for x in L[:]:  # Use a list slice to make a copy.
    print(x)
    L.remove(x)  # Modify the original, not the copy.
    print(L)
1 Like

Thanks,
I don’t see an option to “mark as answer”
Pete

Because this is a discussion forum, not Stack Overflow :slightly_smiling_face:

Actually, Discourse has an “Accepted” plugin, but it is not activated here.

Interesting; can this be activated on a per top-level-category basis? If so, might be worth having a separate category for questions (which probably half or more of Users, by far the most active top-level-category on this Discourse at least in terms of posts.

I have no idea, but something like that would make sense. Cc. @admins