]> granicus.if.org Git - python/commitdiff
bpo-36060: Document how collections.ChainMap() determines iteration order (GH-11969)
authorRaymond Hettinger <rhettinger@users.noreply.github.com>
Thu, 21 Feb 2019 17:12:15 +0000 (09:12 -0800)
committerGitHub <noreply@github.com>
Thu, 21 Feb 2019 17:12:15 +0000 (09:12 -0800)
Doc/library/collections.rst
Lib/test/test_collections.py

index d847d6b79227cbc79ec298ba74e3b99ac216ea14..ca2f1167cc86d4cfe2eb96424ff2ce0fecdc9cda 100644 (file)
@@ -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::
 
index 74372d28ed050d5d64cb841704767949a98802fa..2d5a2661b6898e4f6386afa278f2fc5e10a74454 100644 (file)
@@ -113,6 +113,20 @@ class TestChainMap(unittest.TestCase):
         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