[Python-checkins] bpo-36060: Document how collections.ChainMap() determines iteration order (GH-11969) (GH-11978)

Raymond Hettinger webhook-mailer at python.org
Thu Feb 21 12:47:49 EST 2019


https://github.com/python/cpython/commit/7121a6eeb7941f36fb9e7eae28ec24ecfa533e81
commit: 7121a6eeb7941f36fb9e7eae28ec24ecfa533e81
branch: 3.7
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: Raymond Hettinger <rhettinger at users.noreply.github.com>
date: 2019-02-21T09:47:46-08:00
summary:

bpo-36060: Document how collections.ChainMap() determines iteration order (GH-11969) (GH-11978)

(cherry picked from commit 86f093f71a594dcaf21b67ba13dda72863e9bde9)

Co-authored-by: Raymond Hettinger <rhettinger at users.noreply.github.com>

files:
M Doc/library/collections.rst
M Lib/test/test_collections.py

diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst
index 4a6d99026b57..0413f469228a 100644
--- a/Doc/library/collections.rst
+++ b/Doc/library/collections.rst
@@ -100,6 +100,21 @@ The class can be used to simulate nested scopes and is useful in templating.
         :func:`super` function.  A reference to ``d.parents`` is equivalent to:
         ``ChainMap(*d.maps[1:])``.
 
+    Note, the iteration order of a :class:`ChainMap()` is determined by
+    scanning the mappings last to first::
+
+        >>> baseline = {'music': 'bach', 'art': 'rembrandt'}
+        >>> adjustments = {'art': 'van gogh', 'opera': 'carmen'}
+        >>> list(ChainMap(adjustments, baseline))
+        ['music', 'art', 'opera']
+
+    This gives the same ordering as a series of :meth:`dict.update` calls
+    starting with the last mapping::
+
+        >>> combined = baseline.copy()
+        >>> combined.update(adjustments)
+        >>> list(combined)
+        ['music', 'art', 'opera']
 
 .. seealso::
 
diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py
index 2099d236d0c4..2e7c1996d118 100644
--- a/Lib/test/test_collections.py
+++ b/Lib/test/test_collections.py
@@ -114,6 +114,20 @@ def test_basics(self):
         self.assertEqual(f['b'], 5)                                    # find first in chain
         self.assertEqual(f.parents['b'], 2)                            # look beyond maps[0]
 
+    def test_ordering(self):
+        # Combined order matches a series of dict updates from last to first.
+        # This test relies on the ordering of the underlying dicts.
+
+        baseline = {'music': 'bach', 'art': 'rembrandt'}
+        adjustments = {'art': 'van gogh', 'opera': 'carmen'}
+
+        cm = ChainMap(adjustments, baseline)
+
+        combined = baseline.copy()
+        combined.update(adjustments)
+
+        self.assertEqual(list(combined.items()), list(cm.items()))
+
     def test_constructor(self):
         self.assertEqual(ChainMap().maps, [{}])                        # no-args --> one new dict
         self.assertEqual(ChainMap({1:2}).maps, [{1:2}])                # 1 arg --> list



More information about the Python-checkins mailing list