@@ -93,13 +93,44 @@ The class can be used to simulate nested scopes and is useful in templating.
9393 The use-cases also parallel those for the builtin :func: `super ` function.
9494 A reference to ``d.parents `` is equivalent to: ``ChainMap(*d.maps[1:]) ``.
9595
96- Example of simulating Python's internal lookup chain::
96+
97+ .. seealso ::
98+
99+ * The `MultiContext class
100+ <http://svn.enthought.com/svn/enthought/CodeTools/trunk/enthought/contexts/multi_context.py> `_
101+ in the Enthought `CodeTools package
102+ <https://github.com/enthought/codetools> `_ has options to support
103+ writing to any mapping in the chain.
104+
105+ * Django's `Context class
106+ <http://code.djangoproject.com/browser/django/trunk/django/template/context.py> `_
107+ for templating is a read-only chain of mappings. It also features
108+ pushing and popping of contexts similar to the
109+ :meth: `~collections.ChainMap.new_child ` method and the
110+ :meth: `~collections.ChainMap.parents ` property.
111+
112+ * The `Nested Contexts recipe
113+ <http://code.activestate.com/recipes/577434/> `_ has options to control
114+ whether writes and other mutations apply only to the first mapping or to
115+ any mapping in the chain.
116+
117+ * A `greatly simplified read-only version of Chainmap
118+ <http://code.activestate.com/recipes/305268/> `_.
119+
120+
121+ :class: `ChainMap ` Examples and Recipes
122+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
123+
124+ This section shows various approaches to working with chained maps.
125+
126+
127+ Example of simulating Python's internal lookup chain::
97128
98129 import builtins
99130 pylookup = ChainMap(locals(), globals(), vars(builtins))
100131
101- Example of letting user specified values take precedence over environment
102- variables which in turn take precedence over default values::
132+ Example of letting user specified values take precedence over environment
133+ variables which in turn take precedence over default values::
103134
104135 import os, argparse
105136 defaults = {'color': 'red', 'user': guest}
@@ -109,8 +140,8 @@ The class can be used to simulate nested scopes and is useful in templating.
109140 user_specified = vars(parser.parse_args())
110141 combined = ChainMap(user_specified, os.environ, defaults)
111142
112- Example patterns for using the :class: `ChainMap ` class to simulate nested
113- contexts::
143+ Example patterns for using the :class: `ChainMap ` class to simulate nested
144+ contexts::
114145
115146 c = ChainMap() # Create root context
116147 d = c.new_child() # Create nested child context
@@ -128,28 +159,33 @@ The class can be used to simulate nested scopes and is useful in templating.
128159 d.items() # All nested items
129160 dict(d) # Flatten into a regular dictionary
130161
131- .. seealso ::
162+ The :class: `ChainMap ` class only makes updates (writes and deletions) to the
163+ first mapping in the chain while lookups will search the full chain. However,
164+ if deep writes and deletions are desired, it is easy to make a subclass that
165+ updates keys found deeper in the chain::
132166
133- * The `MultiContext class
134- <http://svn.enthought.com/svn/enthought/CodeTools/trunk/enthought/contexts/multi_context.py> `_
135- in the Enthought `CodeTools package
136- <https://github.com/enthought/codetools> `_ has options to support
137- writing to any mapping in the chain.
167+ class DeepChainMap(ChainMap):
168+ 'Variant of ChainMap that allows direct updates to inner scopes'
138169
139- * Django's `Context class
140- <http://code.djangoproject.com/browser/django/trunk/django/template/context.py> `_
141- for templating is a read-only chain of mappings. It also features
142- pushing and popping of contexts similar to the
143- :meth: `~collections.ChainMap.new_child ` method and the
144- :meth: `~collections.ChainMap.parents ` property.
145-
146- * The `Nested Contexts recipe
147- <http://code.activestate.com/recipes/577434/> `_ has options to control
148- whether writes and other mutations apply only to the first mapping or to
149- any mapping in the chain.
150-
151- * A `greatly simplified read-only version of Chainmap
152- <http://code.activestate.com/recipes/305268/> `_.
170+ def __setitem__(self, key, value):
171+ for mapping in self.maps:
172+ if key in mapping:
173+ mapping[key] = value
174+ return
175+ self.maps[0][key] = value
176+
177+ def __delitem__(self, key):
178+ for mapping in self.maps:
179+ if key in mapping:
180+ del mapping[key]
181+ return
182+ raise KeyError(key)
183+
184+ >>> d = DeepChainMap({'zebra': 'black'}, {'elephant' : 'blue'}, {'lion' : 'yellow'})
185+ >>> d['lion'] = 'orange' # update an existing key two levels down
186+ >>> d['snake'] = 'red' # new keys get added to the topmost dict
187+ >>> del d['elephant'] # remove an existing key one level down
188+ DeepChainMap({'zebra': 'black', 'snake': 'red'}, {}, {'lion': 'orange'})
153189
154190
155191:class: `Counter ` objects
@@ -326,23 +362,23 @@ or subtracting from an empty counter.
326362.. seealso ::
327363
328364 * `Counter class <http://code.activestate.com/recipes/576611/ >`_
329- adapted for Python 2.5 and an early `Bag recipe
330- <http://code.activestate.com/recipes/259174/> `_ for Python 2.4.
365+ adapted for Python 2.5 and an early `Bag recipe
366+ <http://code.activestate.com/recipes/259174/> `_ for Python 2.4.
331367
332368 * `Bag class <http://www.gnu.org/software/smalltalk/manual-base/html_node/Bag.html >`_
333- in Smalltalk.
369+ in Smalltalk.
334370
335371 * Wikipedia entry for `Multisets <http://en.wikipedia.org/wiki/Multiset >`_.
336372
337373 * `C++ multisets <http://www.demo2s.com/Tutorial/Cpp/0380__set-multiset/Catalog0380__set-multiset.htm >`_
338- tutorial with examples.
374+ tutorial with examples.
339375
340376 * For mathematical operations on multisets and their use cases, see
341- *Knuth, Donald. The Art of Computer Programming Volume II,
342- Section 4.6.3, Exercise 19 *.
377+ *Knuth, Donald. The Art of Computer Programming Volume II,
378+ Section 4.6.3, Exercise 19 *.
343379
344380 * To enumerate all distinct multisets of a given size over a given set of
345- elements, see :func: `itertools.combinations_with_replacement `.
381+ elements, see :func: `itertools.combinations_with_replacement `.
346382
347383 map(Counter, combinations_with_replacement('ABC', 2)) --> AA AB AC BB BC CC
348384
@@ -876,14 +912,14 @@ and more efficient to use a simple class declaration:
876912.. seealso ::
877913
878914 * `Named tuple recipe <http://code.activestate.com/recipes/500261/ >`_
879- adapted for Python 2.4.
915+ adapted for Python 2.4.
880916
881917 * `Recipe for named tuple abstract base class with a metaclass mix-in
882- <http://code.activestate.com/recipes/577629-namedtupleabc-abstract-base-class-mix-in-for-named/> `_
883- by Jan Kaliszewski. Besides providing an :term: `abstract base class ` for
884- named tuples, it also supports an alternate :term: `metaclass `-based
885- constructor that is convenient for use cases where named tuples are being
886- subclassed.
918+ <http://code.activestate.com/recipes/577629-namedtupleabc-abstract-base-class-mix-in-for-named/> `_
919+ by Jan Kaliszewski. Besides providing an :term: `abstract base class ` for
920+ named tuples, it also supports an alternate :term: `metaclass `-based
921+ constructor that is convenient for use cases where named tuples are being
922+ subclassed.
887923
888924
889925:class: `OrderedDict ` objects
0 commit comments