Deleting an item from the while iterating through it will usually result in RuntimeError: dictionary changed size during iteration
exception:
d = {1: 2}
# exception raised
for k in d:
del d[k]
To be more precise, the deletion itself will succeed. However, to enter the next round of iteration, the interpreter has to call next(it)
, where it
is an iterator through the dictionary it obtained earlier. At that point, next()
will notice that the dictionary size changed, and complain.
So far so good. But what if we both delete and add an item to a dictionary:
d = {1: 1}
# no exception raised
for k in d:
# order of next two lines doesn't matter
d[k*10] = k*10
del d[k]
I am almost sure that this is not safe (the docs imply neither insert nor delete is allowed during iteration). Why is the interpreter allowing this code to run without error?
My only guess is that it's too expensive to check which iterators are invalidated whenever an insert or delete method is called. So dict
doesn't attempt to be perfect about raising this exception. Instead, it just keeps track of the size of the dictionary inside each iterator, and checks that it hasn't changed whenever the iterator is actually asked to move to the next item. Is there no approach that would enable full validation at a low cost?