How to copy a dict in Python

Check out the various ways to copy a dictionary in Python and the gotchas in each method.

How to copy a dict in Python

If we have a dict (or any other complex data structure) in python, let us see the different ways we can copy our structure:

Method 1: Copy by reference

When you assign dict2 = dict1, you are not making a copy of dict1, it results in dict2 being just another name for dict1

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict1
>>> dict2
{'key2': 'value2', 'key1': 'value1'}
>>> dict2["key2"] = "changed"
>>> dict1
{'key2': 'changed', 'key1': 'value1'}

Method 2: Shallow copy

If we have a simple dict, we can do a shallow copy to create a copy and handle the two structures separately.

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict(dict1)
>>> dict2["key2"] = "changed"
>>> dict1
{'key1': 'value1', 'key2': 'value2'}
>>> dict2
{'key1': 'value1', 'key2': 'changed'}
>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict1.copy()
>>> dict2["key2"] = "changed"
>>> dict1
{'key1': 'value1', 'key2': 'value2'}
>>> dict2
{'key1': 'value1', 'key2': 'changed'}
>>> {'key1': 'value1', 'key2': 'changed'}
{'key1': 'value1', 'key2': 'changed'}

However, if our structure has nested structure, the changes made to the nested structure in one dict will get reflected in both

>>> dict1 = {"key1": [1,4,5,7], "key2": [7,2,6,9]}
>>> dict2 = dict(dict1)
>>> dict2["key2"][3] = 9999
>>> dict1
{'key1': [1, 4, 5, 7], 'key2': [7, 2, 6, 9999]}
>>> dict2
{'key1': [1, 4, 5, 7], 'key2': [7, 2, 6, 9999]}

To avoid this, we can use deepcopy().

Method 3: Deep copy

>>> import copy
>>> dict1 = {"key1": [1,4,5,7], "key2": [7,2,6,9]}
>>> dict2 = copy.deepcopy(dict1)
>>> dict2["key2"][3] = 9999
>>> dict1
{'key1': [1, 4, 5, 7], 'key2': [7, 2, 6, 9]}
>>> dict2
{'key1': [1, 4, 5, 7], 'key2': [7, 2, 6, 9999]}

Here's what the Python copy module documentation says about shallow v/s deep copy:

The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):

  • A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
  • A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.

Tip:

Use id to check whether the two variables are pointing to the same or different object The snippet below shows how the ids look like when we do shallow copy of a complex dict.

Please note that while dict1 and dict2 have different id, the id for value corresponding to "key2" is same for both the dictionaries, hence in case of shallow copy we saw that change made in one dict got reflected to the other.

>>> dict1 = {"key1": [1,4,5,7], "key2": [7,2,6,9]}
>>> dict2 = dict(dict1)
>>> id(dict1)
1541071407216
>>> id(dict2)
1541071987912
>>> id(dict1["key2"])
1541071921992
>>> id(dict2["key2"])
1541071921992

Happy coding ! Cheers !