2
L = 10*[1]
for l in L:
    L.remove(l)
print(L)

Why does print(L) return 5 terms of the original list L? I was looking through the debugger and the len of (L) both locally and globally is 5, and L.remove(1) is a valid operation on a list [1,1,1,1,1] right? What's making the loop exit when the len(L) is 5?

benvc
  • 14,448
  • 4
  • 33
  • 54
sjfklsdafjks
  • 149
  • 2

1 Answers1

4

It is because you are mutating the list L while iterating over it. Once you have removed 5 items, you have eliminated any further indices for the loop to iterate over. The loop is iterating over the index positions of your list from index position 0 to the last index in the list. Since you are removing items during each iteration, you are changing the index position of the items in the list, but this does not change the next index value the loop will iterate over.

This is easier to see if you have a list with unique item values like [1,2,3,4,5,6,7,8,9,10]. In the first iteration you remove item value 1 mutating your list to [2,3,4,5,6,7,8,9,10], then the second iteration goes to index position 1, which is now item value 3 and you remove that item.

When your loop finishes, you will have removed all the odd value items (leaving [2, 4, 6, 8, 10]) and the loop will stop because index position 5 no longer exists in the list.

Here is an example of how this works in practice:

items = [1,2,3,4,5,6,7,8,9,10]

for i, item in enumerate(items):
    print(f'Iterating over index {i} where item value {item}')
    print(f'Next item: {items[i+1]}')
    items.remove(item)
    if i < len(items) - 1:
        print(f'Oops, next item changed to {items[i+1]} because I removed an item.')
    else:
        print('Oops, no more items because I removed an item.')

print(f'Mutated list after loop completed: {items}')

# OUTPUT
# Iterating over index 0 where item value 1
# Next item: 2
# Oops, next item changed to 3 because I removed an item.
# Iterating over index 1 where item value 3
# Next item: 4
# Oops, next item changed to 5 because I removed an item.
# Iterating over index 2 where item value 5
# Next item: 6
# Oops, next item changed to 7 because I removed an item.
# Iterating over index 3 where item value 7
# Next item: 8
# Oops, next item changed to 9 because I removed an item.
# Iterating over index 4 where item value 9
# Next item: 10
# Oops, no more items because I removed an item.
# Mutated list after loop completed: [2, 4, 6, 8, 10]
benvc
  • 14,448
  • 4
  • 33
  • 54
  • Why does the next loop iteration goto index position one? Isn’t the .remove(x) function defined as x being an object and not an index? Edit: and thanks for the answer! – sjfklsdafjks Oct 25 '18 at 18:08
  • I like this answer, but it belongs to one of the marked duplicates, which have identical questions. It's in your interests too: over time good answers are more likely to attract upvotes on a canonical (which gets more views). – jpp Oct 25 '18 at 18:23
  • @jpp agreed that this question has been asked and answered before. Just seemed like OP was more interested in the "why" than the "how" and while the dups address the "why" briefly, they are much more focused on the "how". This is only to explain why I answered the question at all instead of immediately marking as duplicate, but I completely agree with you marking it as a dup. – benvc Oct 25 '18 at 18:44
  • @benvc, Sure, I do appreciate your answer. I just feel *more people* will be able to read and appreciate it on the very popular duplicates (via google etc), while most likely this question is likely to get a few more views, then disappear for all intents. – jpp Oct 25 '18 at 18:46