3

The Python docs give warnings about trying to modify a dict while iterating over it. Does this apply to views?

I understand that views are "live" in the sense that if you change the underlying dict, the view automatically reflects the change. I'm also aware that a dict's natural ordering can change if elements are added or removed. How does this work in conjunction with for/in? Can you safely modify the dict without messing up the loop?

d = dict()
# assume populated dict
for k in d.viewkeys():
    # possibly add or del element of d

Does the for/in loop iterate over all the new elements as well? Does it miss elements (because of order change)?

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
Ouroborus
  • 16,237
  • 4
  • 39
  • 62

1 Answers1

7

Yes, this applies to dictionary views over either keys or items, as they provide a live view of the dictionary contents. You cannot add or remove keys to the dictionary while iterating over a dictionary view, because, as you say, this alters the dictionary order.

Demo to show that this is indeed the case:

>>> d = {'foo': 'bar'}
>>> for key in d.viewkeys():
...     d['spam'] = 'eggs'
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: dictionary changed size during iteration
>>> d = {'foo': 'bar', 'spam': 'eggs'}
>>> for key in d.viewkeys():
...    del d['spam']
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: dictionary changed size during iteration

You can alter values, even when iterating over a values view, as the size of the dictionary won't then change, and the keys remain in the same order.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • I don't get an error when using `del`. Could you expand your answer to address that? – Ouroborus Jun 27 '15 at 19:15
  • 1
    @Ouroborus: also note that in Python 2, the `dict.keys()`, `dict.items()` and `dict.values()` functions create a new list object with those keys and / or values in a set order *first*, so altering the dictionary in the loop then won't affect those lists. That's not what the question is about. – Martijn Pieters Jun 27 '15 at 19:20
  • @MartjinPieters This tells me I definitely have an issue in my code but it's a completely different issue. I do have such a `del` but no errors which, based on your answer, means the `del` is not being run. Thank you much. – Ouroborus Jun 27 '15 at 19:21