Skip to main content
Reword to separate "`x` and `y`, `z`" for clarity. Also make title format to one line.
Source Link
Mateen Ulhaq
  • 26.6k
  • 20
  • 115
  • 147

How can I merge two Python dictionaries in a single expression?

How can I merge two Python dictionaries in a single expression?

For dictionaries x and y, their shallowly-merged dictionary z becomes a shallowly-merged dictionary withtakes values from y, replacing those from x.

  • In Python 3.9.0 or greater (released 17 October 2020):, PEP-584PEP-584, discussed here, was implemented and provides the simplest method):

    z = x | y          # NOTE: 3.9+ ONLY
    
  • In Python 3.5 or greater:

    z = {**x, **y}
    
  • In Python 2, (or 3.4 or lower) write a function:

    def merge_two_dicts(x, y):
        z = x.copy()   # start with keys and values of x
        z.update(y)    # modifies z with keys and values of y
        return z
    

    and now:

    z = merge_two_dicts(x, y)
    

How can I merge two Python dictionaries in a single expression?

For dictionaries x and y, z becomes a shallowly-merged dictionary with values from y replacing those from x.

  • In Python 3.9.0 or greater (released 17 October 2020): PEP-584, discussed here, was implemented and provides the simplest method:

    z = x | y          # NOTE: 3.9+ ONLY
    
  • In Python 3.5 or greater:

    z = {**x, **y}
    
  • In Python 2, (or 3.4 or lower) write a function:

    def merge_two_dicts(x, y):
        z = x.copy()   # start with keys and values of x
        z.update(y)    # modifies z with keys and values of y
        return z
    

    and now:

    z = merge_two_dicts(x, y)
    

How can I merge two Python dictionaries in a single expression?

For dictionaries x and y, their shallowly-merged dictionary z takes values from y, replacing those from x.

  • In Python 3.9.0 or greater (released 17 October 2020, PEP-584, discussed here):

    z = x | y
    
  • In Python 3.5 or greater:

    z = {**x, **y}
    
  • In Python 2, (or 3.4 or lower) write a function:

    def merge_two_dicts(x, y):
        z = x.copy()   # start with keys and values of x
        z.update(y)    # modifies z with keys and values of y
        return z
    

    and now:

    z = merge_two_dicts(x, y)
    
Formatting, minor tweaks
Source Link

For dictionaries x and y, z becomes a shallowly merged-merged dictionary with values from y replacing those from x.

  • In Python 3.9.0 or greater (released 17 October 2020): PEP-584, discussed here, was implemented and provides the simplest method:

    z = x | y          # NOTE: 3.9+ ONLY
    
  • In Python 3.5 or greater:

    z = {**x, **y}
    
  • In Python 2, (or 3.4 or lower) write a function:

    def merge_two_dicts(x, y):
        z = x.copy()   # start with x's keys and values of x
        z.update(y)    # modifies z with y's keys and values & returnsof Noney
        return z
    

    and now:

    z = merge_two_dicts(x, y)
    

Say you have two dictionaries and you want to merge them into a new dictdictionary without altering the original dictionaries:

It is now showing as implemented in the release schedule for 3.5, PEP 478, and it has now made its way into the What's New in Python 3.5 document.

In both approaches, y will come second and its values will replace x's values, thus 'b'b will point to 3 in our final result.

You can also make a function to merge an undefinedarbitrary number of dictionaries, from zero to a very large number:

Here's an example where yy should have precedence, but instead the value from xx is retained due to the arbitrary order of sets:

This uses the dict constructor and is very fast and memory-efficient (even slightly more-so so than our two-step process) but unless you know precisely what is happening here (that is, the second dict is being passed as keyword arguments to the dict constructor), it's difficult to read, it's not the intended usage, and so it is not Pythonic.

Dictionaries are intended to take hashable keys (e.g. frozensetsfrozensets or tuples), but this method fails in Python 3 when keys are not strings.

Again, it doesn't work for 3 when keys are non-stringsnot strings. The implicit calling contract is that namespaces take ordinary dictionaries, while users must only pass keyword arguments that are strings. All other callables enforced it. dict broke this consistency in Python 2:

This inconsistency was bad given other implementations of Python (PypyPyPy, Jython, IronPython). Thus it was fixed in Python 3, as this usage could be a breaking change.

or in pythonPython 2.6 (and perhaps as early as 2.4 when generator expressions were introduced):

For dictionaries x and y, z becomes a shallowly merged dictionary with values from y replacing those from x.

  • In Python 3.9.0 or greater (released 17 October 2020): PEP-584, discussed here, was implemented and provides the simplest method:

    z = x | y          # NOTE: 3.9+ ONLY
    
  • In Python 3.5 or greater:

    z = {**x, **y}
    
  • In Python 2, (or 3.4 or lower) write a function:

    def merge_two_dicts(x, y):
        z = x.copy()   # start with x's keys and values
        z.update(y)    # modifies z with y's keys and values & returns None
        return z
    

    and now:

    z = merge_two_dicts(x, y)
    

Say you have two dictionaries and you want to merge them into a new dict without altering the original dictionaries:

It is now showing as implemented in the release schedule for 3.5, PEP 478, and it has now made its way into What's New in Python 3.5 document.

In both approaches, y will come second and its values will replace x's values, thus 'b' will point to 3 in our final result.

You can also make a function to merge an undefined number of dictionaries, from zero to a very large number:

Here's an example where y should have precedence, but instead the value from x is retained due to the arbitrary order of sets:

This uses the dict constructor and is very fast and memory-efficient (even slightly more-so than our two-step process) but unless you know precisely what is happening here (that is, the second dict is being passed as keyword arguments to the dict constructor), it's difficult to read, it's not the intended usage, and so it is not Pythonic.

Dictionaries are intended to take hashable keys (e.g. frozensets or tuples), but this method fails in Python 3 when keys are not strings.

Again, it doesn't work for 3 when keys are non-strings. The implicit calling contract is that namespaces take ordinary dictionaries, while users must only pass keyword arguments that are strings. All other callables enforced it. dict broke this consistency in Python 2:

This inconsistency was bad given other implementations of Python (Pypy, Jython, IronPython). Thus it was fixed in Python 3, as this usage could be a breaking change.

or in python 2.6 (and perhaps as early as 2.4 when generator expressions were introduced):

For dictionaries x and y, z becomes a shallowly-merged dictionary with values from y replacing those from x.

  • In Python 3.9.0 or greater (released 17 October 2020): PEP-584, discussed here, was implemented and provides the simplest method:

    z = x | y          # NOTE: 3.9+ ONLY
    
  • In Python 3.5 or greater:

    z = {**x, **y}
    
  • In Python 2, (or 3.4 or lower) write a function:

    def merge_two_dicts(x, y):
        z = x.copy()   # start with keys and values of x
        z.update(y)    # modifies z with keys and values of y
        return z
    

    and now:

    z = merge_two_dicts(x, y)
    

Say you have two dictionaries and you want to merge them into a new dictionary without altering the original dictionaries:

It is now showing as implemented in the release schedule for 3.5, PEP 478, and it has now made its way into the What's New in Python 3.5 document.

In both approaches, y will come second and its values will replace x's values, thus b will point to 3 in our final result.

You can also make a function to merge an arbitrary number of dictionaries, from zero to a very large number:

Here's an example where y should have precedence, but instead the value from x is retained due to the arbitrary order of sets:

This uses the dict constructor and is very fast and memory-efficient (even slightly more so than our two-step process) but unless you know precisely what is happening here (that is, the second dict is being passed as keyword arguments to the dict constructor), it's difficult to read, it's not the intended usage, and so it is not Pythonic.

Dictionaries are intended to take hashable keys (e.g. frozensets or tuples), but this method fails in Python 3 when keys are not strings.

Again, it doesn't work for 3 when keys are not strings. The implicit calling contract is that namespaces take ordinary dictionaries, while users must only pass keyword arguments that are strings. All other callables enforced it. dict broke this consistency in Python 2:

This inconsistency was bad given other implementations of Python (PyPy, Jython, IronPython). Thus it was fixed in Python 3, as this usage could be a breaking change.

or in Python 2.6 (and perhaps as early as 2.4 when generator expressions were introduced):

probably shouldn't be fixing grammar on quotes, but in this case, the grammar fix was wrong, it is "the fact... is" not "the fact... are".
Source Link
Aaron Hall
  • 388.5k
  • 91
  • 409
  • 336

Despite what Guido says, dict(x, **y) is in line with the dict specification, which btw. works for both Python 2 and 3. The fact that this only works for string keys areis a direct consequence of how keyword parameters work and not a short-coming of dict. Nor is using the ** operator in this place an abuse of the mechanism, in fact, ** was designed precisely to pass dictionaries as keywords.

Despite what Guido says, dict(x, **y) is in line with the dict specification, which btw. works for both Python 2 and 3. The fact that this only works for string keys are a direct consequence of how keyword parameters work and not a short-coming of dict. Nor is using the ** operator in this place an abuse of the mechanism, in fact, ** was designed precisely to pass dictionaries as keywords.

Despite what Guido says, dict(x, **y) is in line with the dict specification, which btw. works for both Python 2 and 3. The fact that this only works for string keys is a direct consequence of how keyword parameters work and not a short-coming of dict. Nor is using the ** operator in this place an abuse of the mechanism, in fact, ** was designed precisely to pass dictionaries as keywords.

Move newest version to be the first - as it should be the preferred way
Source Link
Loading
format with fences, improve copy-pasteability, update a bit of Python 2 specific code, remove Python 2 specific performance analysis, update perf analysis for 3.8
Source Link
Aaron Hall
  • 388.5k
  • 91
  • 409
  • 336
Loading
Added dict comprehension link, and changed some dict to dictionary
Source Link
Red
  • 27.4k
  • 7
  • 41
  • 61
Loading
PEP-584 implemented circa 3.9.0a4
Source Link
Nick T
  • 26.5k
  • 13
  • 85
  • 125
Loading
update for update in PEP
Source Link
Aaron Hall
  • 388.5k
  • 91
  • 409
  • 336
Loading
foreshadowing z = x + y
Source Link
Aaron Hall
  • 388.5k
  • 91
  • 409
  • 336
Loading
deleted 6 characters in body
Source Link
Aaron Hall
  • 388.5k
  • 91
  • 409
  • 336
Loading
address comments asking about nested dictionaries
Source Link
Aaron Hall
  • 388.5k
  • 91
  • 409
  • 336
Loading
added an example of splatting with a literal dict
Source Link
Jesse Dhillon
  • 8k
  • 1
  • 35
  • 34
Loading
added 493 characters in body
Source Link
Aaron Hall
  • 388.5k
  • 91
  • 409
  • 336
Loading
added 323 characters in body
Source Link
Aaron Hall
  • 388.5k
  • 91
  • 409
  • 336
Loading
added 964 characters in body
Source Link
Aaron Hall
  • 388.5k
  • 91
  • 409
  • 336
Loading
added 147 characters in body
Source Link
Aaron Hall
  • 388.5k
  • 91
  • 409
  • 336
Loading
added 1681 characters in body
Source Link
Aaron Hall
  • 388.5k
  • 91
  • 409
  • 336
Loading
Use triple double quotes for function docstrings (as per PEP257 https://www.python.org/dev/peps/pep-0257/#what-is-a-docstring)
Source Link
Loading
added 5 characters in body
Source Link
Aaron Hall
  • 388.5k
  • 91
  • 409
  • 336
Loading
added 168 characters in body
Source Link
Aaron Hall
  • 388.5k
  • 91
  • 409
  • 336
Loading
Reordered to put the most modern approach first; added emphasis on *single expression* since I imagine that may have gone over some readers' heads; tweaked language slightly for clarity in a few places. Feel free to revert if you disagree!
Source Link
Mark Amery
  • 150.3k
  • 87
  • 415
  • 465
Loading
added 62 characters in body
Source Link
Aaron Hall
  • 388.5k
  • 91
  • 409
  • 336
Loading
added 12 characters in body
Source Link
Aaron Hall
  • 388.5k
  • 91
  • 409
  • 336
Loading