[Python-Dev] Issue 19332: Guard against changing dict during iteration

Serhiy Storchaka storchaka at gmail.com
Wed Nov 6 21:16:19 CET 2013

06.11.13 21:12, Eric Snow написав(ла):
> Just to clarify, do you mean we should only guard against
> modifications to the dict's keys during its iterator's __next__()?
> Changes to the values during __next__() would be okay, as would
> changes to the keys if they happen outside __next__()?

Dict iteration order can be changed after adding or deleting a key so 
continue iterating after this is not well defined. __next__() is invalid 
if dict keys was modified after iterators creation. This is common 
assertion for hashtables in many programming languages. The raising an 
exception in such situation just helps a programmer to find his mistake. 
Java raises an exception, in C++ this is an undefined behavior.

> Presumably the above restriction also applies to the iterators of the
> dict's views.

Yes. The proposed patch have tests for these cases.

> OrderedDict would also need to be changed, meaning this counter would
> have to be accessible to and incrementable by subclasses.  OrderedDict
> makes use of the MappingView classes in collections.abc, so those
> would also have be adjusted to check this counter.

Perhaps issue19414 is related. OrderedDict not needs such behavior 
because it's iteration order is well defined and we can implement 
another reasonable behavior (for example deleted keys are skipped and 
newly added keys are always iterated, because they added at the end of 
iteration order).

> Would MutableMapping also need to be adjusted to accommodate the
> counter?  Given that the MappingView classes would rely on the
> counter, I'd expect MutableMapping to need some method or variable
> that the views can rely on.  How would we make sure custom methods,
> particularly __setitem__() and __delitem__(), increment the counter?

MutableMapping doesn't implement neither __iter__() nor __setitem__(). 
Concrete implementation is responsible of this, either provide reliable 
__iter__() which have predictable behavior after __setitem__(), or 
detect such modification and raise an exception, or just ignore the problem.

The MappingView classes would get this for free because their iterators 
iterate over mapping itself.

> A strictly monotonic counter, right?  Every mutation method of dict
> would have to increment this counter.  So would that put a limit
> (albeit a high one) on the number of mutations that can be made to a
> dict?  Would there be conditions under which we'd reset the counter?
> If so, how would existing iterators cope?

It is very unlikely that unintentional causes exact 2**32 or 2**64 
mutations between dict iterations. If this will happen the programmer 
should use other methods to find his mistakes.

> Because the iterators (and views) already have a pointer to the dict, right?

Currently the PyDictObject object contains 3 words and adding yet one 
word unlikely change actually allocated size. Dict iterators already 
contain a field for dict's size, it will be replaced by a field for 
dict's counter.

More information about the Python-Dev mailing list