Python Forum

Full Version: dictionary merge
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
i have 2 or more dictionaries to merge. they always have different keys. is there a way to do this in one expression? the .update() method returns None so it is unusable for this.
From 3.5 ** dictionary unpacking operators.
>>> x = {'a': 1, 'b': 2}
>>> y = {'c': 999, 'd': 200}
>>> z = {**x, **y}
>>> z
{'a': 1, 'b': 2, 'c': 999, 'd': 200}
i am going to:
my_function(**merged_dict)
and that will be the only use for the merged dictionary ... both parts being used for keyword arguments in the function call ... like:
my_function(**{**dicta,**dictb})
is that the way to do it even for keyword arguments?
There is no need to create a merged dict, just to unpack it in function call. Isn't that what you actually want:
spam = {'a':1, 'b':2}
eggs = {'c':3, 'd':4}

def foo(*args, **kwargs):
    for key, value in kwargs.items():
        print(f'{key} -> {value}')

foo(**spam, **eggs)
Output:
a -> 1 b -> 2 c -> 3 d -> 4
or to extend it with positional arguments:

spam = {'a':1, 'b':2}
eggs = {'c':3, 'd':4}

def foo(*args, **kwargs):
    for arg in args:
        print(arg)
    for key, value in kwargs.items():
        print(f'{key} -> {value}')

foo('boo', 'woo', **spam, **eggs)
Output:
boo woo a -> 1 b -> 2 c -> 3 d -> 4
or
spam = {'a':1, 'b':2}
eggs = {'c':3, 'd':4}
bar = ['boo', 'woo']

def foo(*args, **kwargs):
    for arg in args:
        print(arg)
    for key, value in kwargs.items():
        print(f'{key} -> {value}')

foo(*bar, **spam, **eggs)
Output:
boo woo a -> 1 b -> 2 c -> 3 d -> 4
Depending on use case there is also collections.ChainMap

If there are duplicate keys first one is kept (this is in contrast of merging when last one is kept):

>>> from collections import ChainMap
>>> spam = {'a':1, 'b':2} 
>>> eggs = {'c':3, 'd':4}                                                                                                       
>>> chained = ChainMap(spam, eggs)
>>> chained                                                                                                                   
ChainMap({'a': 1, 'b': 2}, {'c': 3, 'd': 4})
>>> eggs['e'] = 5                                                                                                                          
>>> chained                                                                                                                                
ChainMap({'a': 1, 'b': 2}, {'c': 3, 'd': 4, 'e': 5})
>>> spam['c'] = 'c'                                                                                                                        
>>> chained                                                                                                                                
ChainMap({'a': 1, 'b': 2, 'c': 'c'}, {'c': 3, 'd': 4, 'e': 5})
>>> dict(chained)                                                                                                                          
>>> {'c': 'c', 'd': 4, 'e': 5, 'a': 1, 'b': 2}
i did not know it is possible to "merge" 2 or more keyword args when using **. that is why i wondered if that dictionary object reference was passed as the reference in the function that is also using **. so, it must be true that for a function call with keyword args, all of them are collected into a new dictionary for a function that uses ** and a reference to that new dictionary is stored in that function instance's local name space as the name after the ** in the def.