Python Copy Dictionary: Shallow Copy Vs Deep Copy
In Python, if you use the assignment operator (=) to copy a dictionary, you are not actually creating a new copy. Both variables will point to the same dictionary in memory, so changing one will also change the other.
To create an independent copy, Python provides several ways to copy a dictionary, depending on whether you need a shallow copy or a deep copy.
Shallow Copy Dictionary
A shallow copy creates a new dictionary, but if the original dictionary contains mutable objects (like lists or other dictionaries) as values, those nested objects are not actually copied. Instead, the new dictionary stores references to the same nested objects, so changes to them in the copy will also appear in the original.
There are several ways to create a shallow copy of a dictionary:
Using the copy() Method
The copy() method is the easiest and most common way to create a shallow copy of a dictionary.
Example: Copying a Dictionary With Immutable Values
person = {"name": "James", "age": 30}
# Make a shallow copy
person_copy = person.copy()
print(person_copy) # Output: {'name': 'James', 'age': 30}
Now, let’s see what happens when we modify the immutable values in the copied dictionary.
person = {"name": "James", "age": 30}
# Make a shallow copy
person_copy = person.copy()
# Modify the copied dictionary
person["name"] = "Rock"
person["age"] = 55
print(person_copy) # Output: {'name': 'James', 'age': 30}
print(person) # Output: {'name': 'Rock', 'age': 55}
In this example, changing the values in the copied dictionary doesn’t affect the original dictionary because the values "name" and "age" are immutable objects (string and integer).
When you modify an immutable value in the copy, Python creates a new object in memory, so the original data remains unchanged.
Example: Copying and Modifying Mutable Values in a Dictionary
Now, let’s see what happens when you modify a mutable value (such as a list or dictionary) in a shallow-copied dictionary.
person = {"name": "James", "scores": [50, 60, 70]}
# Make a shallow copy of the dictionary
person_copy = person.copy()
# Change the string value in the copied dictionary
person_copy["name"] = "Rock"
# Append a new score to the list inside the copied dictionary
person_copy["scores"].append(100)
print(person_copy) # Output: {'name': 'Rock', 'scores': [50, 60, 70, 100]}
print(person) # Output: {'name': 'James', 'scores': [50, 60, 70, 100]}
In this example changing the "name" in the copy doesn’t affect the original dictionary because strings are immutable.
However, appending a value to the "scores" list affects both dictionaries because a shallow copy only copies the references to the mutable objects, not the objects themselves. Both "person" and "person_copy" share the same "score" list in memory. So any modification to that shared list appears in both dictionaries.
Using The dict() Constructor
You can also pass an existing dictionary as an argument to the dict() constructor to create a shallow copy of that dictionary.
For example:
person = {"name": "James", "age": 30}
# Make a shallow copy using the dict() constructor
person_copy = dict(person)
print(person_copy) # Output: {'name': 'James', 'age': 30}
Deep Copy Dictionary
A deep copy creates a completely independent copy of the dictionary, including all nested mutable objects. Any changes made to the deep copy, including those to nested objects, will not affect the original dictionary.
You can create a deep copy of a dictionary using the deepcopy() function from the copy module.
Example: Deep Copy With Nested Data
import copy
person = {"name": "James", "scores": [50, 60, 70]}
# Make a deep copy of the dictionary
person_copy = copy.deepcopy(person)
# Change the string value in the copied dictionary
person_copy["name"] = "Rock"
# Append a new score to the list inside the copied dictionary
person_copy["scores"].append(100)
print(person_copy) # Output: {'name': 'Rock', 'scores': [50, 60, 70, 100]}
print(person) # Output: {'name': 'James', 'scores': [50, 60, 70]}
In this example, changing the value of "name" and "scores" doesn’t affect the original dictionary because copy.deepcopy() creates an entirely independent copy of the original dictionary and all its nested objects.
Shallow Copy Vs Deep Copy in Python
Here is a quick comparison table that summarizes the main differences between shallow copy and deep copy in Python:
| Feature | Shallow Copy | Deep Copy |
| Copies top level dictionary | ✅ | ✅ |
| Copies nested mutable objects | ❌ | ✅ |
| Affects original when nested data is changed | ✅ | ❌ |
| Common methods | copy(), dict() | copy.deepcopy() |