[Python-ideas] Dict joining using + and +=

Steven D'Aprano steve at pearwood.info
Mon Mar 4 11:44:09 EST 2019

On Mon, Mar 04, 2019 at 09:42:53AM -0500, David Mertz wrote:
> On Mon, Mar 4, 2019, 8:30 AM Serhiy Storchaka <storchaka at gmail.com> wrote:
> > But is merging two dicts a common enough problem that needs introducing
> > an operator to solve it? I need to merge dicts maybe not more than one
> > or two times by year, and I am fine with using the update() method.
> > Perhaps {**d1, **d2} can be more appropriate in some cases, but I did not
> > encounter such cases yet.
> >
> Like other folks in the thread, I also want to merge dicts three times per
> year. 

I'm impressed that you have counted it with that level of accuracy. Is 
it on the same three days each year, or do they move about? *wink*

> And every one of those times, itertools.ChainMap is the right way to
> do that non-destructively, and without copying.

Can you elaborate on why ChainMap is the right way to merge multiple 
dicts into a single, new dict?

ChainMap also seems to implement the opposite behaviour to that usually 
desired: first value seen wins, instead of last:

py> from collections import ChainMap
py> cm = ChainMap({'a': 1}, {'b': 2}, {'a': 999})
py> cm
ChainMap({'a': 1}, {'b': 2}, {'a': 999})
py> dict(cm)
{'a': 1, 'b': 2}

If you know ahead of time which order you want, you can simply reverse 

    # prefs = site_defaults + user_defaults + document_prefs
    prefs = dict(ChainMap(document_prefs, user_defaults, site_defaults))

but that seems a little awkward to me, and reads backwards. I'm used to 
thinking reading left-to-right, not right-to-left.

ChainMap seems, to me, to be ideal for implementing "first wins" 
mappings, such as emulating nested scopes, but not so ideal for 
update/merge operations.


More information about the Python-ideas mailing list