How to copy a dict in Python
Check out the various ways to copy a dictionary in Python and the gotchas in each method.
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 !