What makes an iterator an iterator?
Peter Otten
__peter__ at web.de
Wed Apr 18 06:53:46 EDT 2007
Steven D'Aprano wrote:
> class SortedDict(dict):
> def __iter__(self):
> for key in sorted(self.keys()):
> yield key
>
> Note that using sorted(self) does not work.
That's because sorted() invokes __iter__() if present. To prevent the
recursion you can explicitly invoke dict.__iter__():
>>> class SortedDict(dict):
... def __iter__(self):
... return iter(sorted(super(SortedDict, self).__iter__()))
...
>>> sd = SortedDict(a=1, b=2, c=3)
>>> list(sd)
['a', 'b', 'c']
Note that a list of keys is still built before the first key is yielded,
and, unlike dict, you can modify your SortedDict while iterating over it:
>>> for k in sd:
... if k == "b": sd["x"] = 42
...
>>> sd
{'a': 1, 'x': 42, 'c': 3, 'b': 2}
whereas:
>>> d = dict(a=1, b=2, c=3)
>>> for k in d:
... if k == "b": d["x"] = 42
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RuntimeError: dictionary changed size during iteration
By the way, I think it would be worthwile to change super() to allow
e. g. super(SomeClass, self)[...] as an alternate spelling for
super(SomeClass, self).__getitem__(...) etc. With such an enhancement
SortedDict would become
class SortedDict(dict):
def __iter__(self):
# doesn't work in current Python
iter(sorted(super(SortedDict, self)))
Peter
More information about the Python-list
mailing list