1
l = [1,2,3,4] * 10
for idx, n in enumerate(l):
    if n == 3: del l[idx]

This works, giving [1, 2, 4, 1, 2, 4, 1, 2, 4 ...]. Why? Shouldn't the first deletion throw all the indices off? Is Python silently modifying its behavior DWIM-style?

Schilcote
  • 2,344
  • 1
  • 17
  • 35
  • 2
    Because you don't have repeating elements – Mad Physicist Sep 24 '19 at 22:17
  • 5
    it works because there are no adjacent threes. Try: `[1, 2, 3, 3]` and it will break. – alkasm Sep 24 '19 at 22:17
  • Deletion throws the indices off, yes, but the real indices of all the threes are also decremented! So these mistakes cancel eachother out. – wim Sep 24 '19 at 22:20
  • @wim So it does... I don't understand why it doesn't delete any non-3s though. Does the `enumerate` work off the live list and not a copy? Why doesn't Python yell at me for modifying something while iterating over it then? – Schilcote Sep 24 '19 at 22:22
  • 2
    Yes, enumerate works off the live list. It's a "feature" for lists, because you can actually safely iterate and modify if you know what you're doing (deleting in *reverse* iteration, for example). Python will yell at you if you try the same thing for a dict... – wim Sep 24 '19 at 22:24
  • @wim You should upgrade that to an answer. – Schilcote Sep 24 '19 at 22:33
  • @alkasm What exactly will break? Deleting one element, then further iterate will only leap over the next element of the list. – a_guest Sep 24 '19 at 22:33
  • Deleting during reverse iteration takes overall worst-case quadratic time, though, so it's still a bad idea. – user2357112 Sep 24 '19 at 22:58

1 Answers1

2

It actually isn't iterating over all the elements, it's just that your code misses that fact.

You can demonstrate that with the following, which doesn't print anything:

l = [1,2,3,4] * 10
for idx, n in enumerate(l):
    if n == 3: del l[idx]
    elif n == 4: print('saw 4')

You might be interested in my answer to the related question How to modify list entries during for loop?

martineau
  • 119,623
  • 25
  • 170
  • 301