Laszlo Nagy wrote: > Given this iterator: > > class SomeIterableObject(object): > .... > .... > > def __iter__(self): > ukeys = self.updates.keys() > for key in ukeys: > if self.updates.has_key(key): > yield self.updates[key] > for rec in self.inserts: > yield rec > .... > .... > > How can I get this exception: > > RuntimeError: dictionary changed size during iteration > > > It is true that self.updates is being changed during the iteration. But > I have created the "ukeys" variable solely to prevent this kind of > error. Here is a proof of correctness: > >>>> d = {1:1,2:2} >>>> k = d.keys() >>>> del d[1] >>>> k > [1, 2] >>>> k is d.keys() > False > > So what is wrong with this iterator? Why am I getting this error message?
The keys() method which used to return a list in 2.x was changed in 3.x to return a view object and to become more or less the equivalent of the old dict.iterkeys(): >>> d = dict(a=1) >>> keys = d.keys() >>> keys dict_keys(['a']) >>> for k in keys: ... d["b"] = 42 ... Traceback (most recent call last): File "<stdin>", line 1, in <module> RuntimeError: dictionary changed size during iteration >>> keys dict_keys(['a', 'b']) You now have to create the list explicitly to avoid the error: >>> d = dict(a=1) >>> keys = list(d.keys()) >>> for k in keys: ... d["b"] = 42 ... >>> d {'a': 1, 'b': 42} >>> keys ['a'] -- http://mail.python.org/mailman/listinfo/python-list