How to copy a dict and modify it in one line of code

Solution

Build a function for that.

Your intention would be clearer when you use it in the code, and you can handle complicated decisions (e.g., deep versus shallow copy) in a single place.

def copy_dict(source_dict, diffs):
    """Returns a copy of source_dict, updated with the new key-value
       pairs in diffs."""
    result=dict(source_dict) # Shallow copy, see addendum below
    result.update(diffs)
    return result

And now the copy is atomic, assuming no threads involved:

setup2=copy_dict(setup1, {'param1': val10, 'param2': val20})

Addendum - deep copy

For primitives (integers and strings), there is no need for deep copy:

>>> d1={1:'s', 2:'g', 3:'c'}
>>> d2=dict(d1)
>>> d1[1]='a'
>>> d1
{1: 'a', 2: 'g', 3: 'c'}
>>> d2
{1: 's', 2: 'g', 3: 'c'}

If you need a deep copy, use the copy module:

result=copy.deepcopy(source_dict) # Deep copy

instead of:

result=dict(setup1)               # Shallow copy

Make sure all the objects in your dictionary supports deep copy (any object that can be pickled should do).


setup2 = dict(setup1.items() + {'param1': val10, 'param2': val20}.items())

This way if new keys do not exist in setup1 they get added, otherwise they replace the old key/value pairs.


The simplest way in my opinion is something like this:

new_dict = {**old_dict, 'changed_val': value, **other_new_vals_as_dict}

You could use keyword arguments in the dictionary constructor for your updates

new = dict(old, a=1, b=2, c=3)

# You can also unpack your modifications
new = dict(old, **mods)

This is equivalent to:

new = old.copy()
new.update({"a": 1, "b": 2, "c": 3})

Source

Notes

  • dict.copy() creates a shallow copy.
  • All keys need to be strings since they are passed as keyword arguments.