Skip to content

Commit 7121a6e

Browse files
bpo-36060: Document how collections.ChainMap() determines iteration order (GH-11969) (GH-11978)
(cherry picked from commit 86f093f) Co-authored-by: Raymond Hettinger <[email protected]>
1 parent 3bd3a71 commit 7121a6e

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

Doc/library/collections.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,21 @@ The class can be used to simulate nested scopes and is useful in templating.
100100
:func:`super` function. A reference to ``d.parents`` is equivalent to:
101101
``ChainMap(*d.maps[1:])``.
102102

103+
Note, the iteration order of a :class:`ChainMap()` is determined by
104+
scanning the mappings last to first::
105+
106+
>>> baseline = {'music': 'bach', 'art': 'rembrandt'}
107+
>>> adjustments = {'art': 'van gogh', 'opera': 'carmen'}
108+
>>> list(ChainMap(adjustments, baseline))
109+
['music', 'art', 'opera']
110+
111+
This gives the same ordering as a series of :meth:`dict.update` calls
112+
starting with the last mapping::
113+
114+
>>> combined = baseline.copy()
115+
>>> combined.update(adjustments)
116+
>>> list(combined)
117+
['music', 'art', 'opera']
103118

104119
.. seealso::
105120

Lib/test/test_collections.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,20 @@ def test_basics(self):
114114
self.assertEqual(f['b'], 5) # find first in chain
115115
self.assertEqual(f.parents['b'], 2) # look beyond maps[0]
116116

117+
def test_ordering(self):
118+
# Combined order matches a series of dict updates from last to first.
119+
# This test relies on the ordering of the underlying dicts.
120+
121+
baseline = {'music': 'bach', 'art': 'rembrandt'}
122+
adjustments = {'art': 'van gogh', 'opera': 'carmen'}
123+
124+
cm = ChainMap(adjustments, baseline)
125+
126+
combined = baseline.copy()
127+
combined.update(adjustments)
128+
129+
self.assertEqual(list(combined.items()), list(cm.items()))
130+
117131
def test_constructor(self):
118132
self.assertEqual(ChainMap().maps, [{}]) # no-args --> one new dict
119133
self.assertEqual(ChainMap({1:2}).maps, [{1:2}]) # 1 arg --> list

0 commit comments

Comments
 (0)