What happens if you modify a collection while looping over it?

A dict raises RuntimeError: dictionary changed size during iteration. A list does something worse: it silently skips elements, because removing one shifts everything left while the index keeps advancing. Iterate over a copy, or build a new collection.

Overview

Two different failures

A dictionary keeps a version counter and compares it on each step, so a size change during iteration is caught immediately and loudly. That is a feature: the alternative is undefined behaviour, because a resize can move every entry to a different slot.

A list has no such check. Deleting element i shifts everything after it one place left, while the loop's internal index advances — so the element that moved into position i is never visited. You get a wrong answer and no error at all, which is the harder bug to find.

Dicts, sets & hashingConceptualEasy

Step through it

What to watch

  • The dict records its size and checks it on every step.
  • The error names the real cause — a size change.
  • Rebuilding rather than mutating avoids the question entirely.

Say this out loud

"Dicts raise RuntimeError. Lists don't - they silently skip elements, because deleting shifts the rest left while the index moves right. I iterate over list(d) or a slice copy, or better, build a new collection with a comprehension."

What happens if you modify a collection while looping over it?

Why can't you delete from a dict or a list while iterating it, and what should you do instead?

The fixes, in order of preference

Build a new collection. [x for x in items if keep(x)] or {k: v for k, v in d.items() if keep(k)}. Nothing is mutated, the intent is explicit, and it is usually faster than repeated deletion.

Iterate over a snapshot. for k in list(d): or for x in items[:]:. Necessary when you genuinely must mutate in place — because other references to the object are watching.

Filter in place backwards. Walking from the end means deletions only shift elements you have already passed. Correct, and worth knowing for when memory matters.

What counts as a change

For a dict, only a size change trips the check. Assigning to an existing key is fine, which surprises people who expect any mutation to raise. Adding a key raises just as deletion does.

Sets behave like dicts. collections.deque also raises. And modifying the object a variable points to — appending to a list stored as a dict value — is not a change to the dict, so it is perfectly legal.

Run it in Python

The dict raising, the list silently skipping on the same logical operation, and the three fixes all producing the answer the broken loop was supposed to give.

mutating.pyPython 3
Output

How the code works

  1. del d[key] inside for key in dRaises immediately. The dict compares its recorded size on every step, because a resize can move every entry and iteration would otherwise be undefined.
  2. broken.remove(x) inside for x in brokenNo error, and 6 survives. Removing 4 shifts 6 into the slot the loop has already passed, so it is never examined — the silent failure is the dangerous one.
  3. [x for x in items if x % 2]The fix to reach for first. Nothing is mutated, the intent is visible, and it is usually faster than repeated remove, which is O(n) each.
  4. nested[key].append(0)Legal. Mutating a value does not change the dictionary's size or its keys, so the version check never fires.

Change one thing

  • Add a key inside the loop instead of deleting one. Same RuntimeError — it is the size that matters, not the direction.
  • Try the same removal on a set. It raises like the dict, which is a good reminder that only the list fails quietly.

Where this runs

Real CPython, compiled to WebAssembly and running on your own machine — nothing is uploaded. The first run takes a few seconds while the interpreter downloads; after that it is immediate. Need more room, or want to paste your own attempt? Use the Python compiler.

Check yourself

0 of 3

Answer without scrolling back up.

  1. Deleting from a list while iterating over it:

  2. Which dict operation during iteration is legal?

  3. The preferred fix is:

Cheat sheet

What happens if you modify a collection while looping over it?

A dict raises RuntimeError: dictionary changed size during iteration. A list does something worse: it silently skips elements, because removing one shifts everything left while the index keeps advancing. Iterate over a copy, or build a new collection.

INTERVIEW · vizlearn.in/interview/modifying-a-collection-while-iterating.html

About the author

Ashish Jangra builds and maintains VizLearn. Every module here is written and the visualisation behind it hand-built, so the numbers in a readout come from the same code that draws the picture. Corrections are genuinely welcome and get priority over everything else — if a page states something wrong, or an animation misrepresents what the algorithm does, get in touch.