[Python-ideas] Have dict().update() return its own reference.

Steven D'Aprano steve at pearwood.info
Sat Apr 21 02:24:41 CEST 2012

Masklinn wrote:
> On 2012-04-20, at 23:41 , Paul Moore wrote:
>> On 20 April 2012 20:49, Masklinn <masklinn at masklinn.net> wrote:
>>> If they're huge mappings, you probably don't want to go around copying
>>> them either way[0] and would instead use more custom mappings, either
>>> some sort of joining proxy or something out of Okasaki (a clojure-style
>>> tree-based map with structural sharing for instance)
>> Python 3.3 has collections.ChainMap for this sort of case.
> Yeah, it's an example of the "joining proxy" thing. Though I'm not sure
> I like it being editable, or the lookup order when providing a sequence
> of maps (I haven't tested it but it appears the maps sequence is traversed
> front-to-back, I'd have found the other way around more "obvious", as if
> each sub-mapping was applied to a base through an update call).

ChainMap is meant to emulate scoped lookups, e.g. builtins + globals + 
nonlocals + locals. Hence, newer scopes mask older scopes. "Locals" should be 
fast, hence it is at the front.

As for being editable, I'm not sure what you mean here, but surely you don't 
object to it being mutable?

> An other potential weirdness of this solution — I don't know how ChainMap
> behaves there, the documentation is unclear — is iteration over the map
> and mapping.items() versus [(key, mapping[key]) for key in mapping]
> potentially having very different behaviors/values since the former is
> going to return all key:value pairs but the latter is only going to return
> the key:(first value for key) pairs which may lead to significant repetitions
> any time a key is present in multiple contexts.

No, iteration over the ChainMap returns unique keys, not duplicates.

 >>> from collections import ChainMap
 >>> mapping = ChainMap(dict(a=1, b=2, c=3, d=4))
 >>> mapping = mapping.new_child()
 >>> mapping.update(dict(d=5, e=6, f=7))
 >>> mapping = mapping.new_child()
 >>> mapping.update(dict(f=8, g=9, h=10))
 >>> len(mapping)
 >>> mapping
ChainMap({'h': 10, 'g': 9, 'f': 8}, {'e': 6, 'd': 5, 'f': 7}, {'a': 1, 'c': 3, 
'b': 2, 'd': 4})
 >>> list(mapping.keys())
['h', 'a', 'c', 'b', 'e', 'd', 'g', 'f']
 >>> list(mapping.values())
[10, 1, 3, 2, 6, 5, 9, 8]


More information about the Python-ideas mailing list