diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index 58607874be93d6..46849b0985d4d4 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -32,6 +32,7 @@ from itertools import chain as _chain from itertools import repeat as _repeat from itertools import starmap as _starmap +from itertools import islice as _islice from keyword import iskeyword as _iskeyword from operator import eq as _eq from operator import itemgetter as _itemgetter @@ -1010,9 +1011,8 @@ def __len__(self): return len(set().union(*self.maps)) # reuses stored hash values if possible def __iter__(self): - d = {} - for mapping in reversed(self.maps): - d.update(dict.fromkeys(mapping)) # reuses stored hash values if possible + lazy_views = (key_view.keys() for key_view in reversed(self.maps)) + d = dict.fromkeys(_chain.from_iterable(lazy_views)) return iter(d) def __contains__(self, key): @@ -1032,7 +1032,7 @@ def fromkeys(cls, iterable, *args): def copy(self): 'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]' - return self.__class__(self.maps[0].copy(), *self.maps[1:]) + return self.__class__(self.maps[0].copy(), *_islice(self.maps, 1, None)) __copy__ = copy @@ -1050,7 +1050,7 @@ def new_child(self, m=None, **kwargs): # like Django's Context.push() @property def parents(self): # like Django's Context.pop() 'New ChainMap from maps[1:].' - return self.__class__(*self.maps[1:]) + return self.__class__(*_islice(self.maps, 1, None)) def __setitem__(self, key, value): self.maps[0][key] = value