Dictionaries in Python are mutable data structures used to store key-value pairs. When working with dictionaries, you might want to create a copy of a dictionary so that changes to the new dictionary don't affect the original one.
Python offers multiple ways to copy dictionaries, from shallow copies to deep copies.
This tutorial will walk through the various methods of copying dictionaries in Python with examples for both shallow and deep copying.
1. Copying Dictionaries with the copy() Method (Shallow Copy)
The most straightforward way to copy a dictionary in Python is by using the copy() method. This method creates a shallow copy, meaning that the copy contains references to the same objects as the original dictionary for nested objects like lists or other dictionaries.
Example: Shallow Copy with copy()
# Example: Copying a dictionary using the copy() method original_dict = { "name": "Alice", "age": 30, "address": { "city": "New York", "state": "NY" } } # Create a shallow copy of the dictionary copied_dict = original_dict.copy() # Modify the shallow copy copied_dict["name"] = "Bob" copied_dict["address"]["city"] = "San Francisco" # Print both dictionaries print("Original Dictionary:", original_dict) print("Copied Dictionary:", copied_dict)
Output:
Original Dictionary: {'name': 'Alice', 'age': 30, 'address': {'city': 'San Francisco', 'state': 'NY'}} Copied Dictionary: {'name': 'Bob', 'age': 30, 'address': {'city': 'San Francisco', 'state': 'NY'}}
In this example:
The copy() method creates a shallow copy of the dictionary.
Changing a value that is not nested (e.g., name) in the copied_dict does not affect the original_dict.
However, since the address is a nested dictionary, both dictionaries share the same reference. Therefore, changing the city in copied_dict also affects original_dict.
2. Copying Dictionaries with the dict() Constructor (Shallow Copy)
You can also use the dict() constructor to create a shallow copy of a dictionary. This method works similarly to copy() and produces the same result.
Example: Shallow Copy with dict()
# Example: Copying a dictionary using the dict() constructor original_dict = { "name": "Alice", "age": 30, "address": { "city": "New York", "state": "NY" } } # Create a shallow copy using the dict() constructor copied_dict = dict(original_dict) # Modify the shallow copy copied_dict["name"] = "Bob" copied_dict["address"]["city"] = "San Francisco" # Print both dictionaries print("Original Dictionary:", original_dict) print("Copied Dictionary:", copied_dict)
Output:
Original Dictionary: {'name': 'Alice', 'age': 30, 'address': {'city': 'San Francisco', 'state': 'NY'}} Copied Dictionary: {'name': 'Bob', 'age': 30, 'address': {'city': 'San Francisco', 'state': 'NY'}}
In this example:
The dict() constructor also creates a shallow copy.
Just like in the previous example, the address field is shared between the original and copied dictionaries, leading to unintended changes.
3. Copying Dictionaries with a Comprehension (Shallow Copy)
Another way to create a shallow copy is by using a dictionary comprehension. This method allows you to iterate through the original dictionary and build a new one.
Example: Shallow Copy with Dictionary Comprehension
# Example: Copying a dictionary using a dictionary comprehension original_dict = { "name": "Alice", "age": 30, "address": { "city": "New York", "state": "NY" } } # Create a shallow copy using dictionary comprehension copied_dict = {key: value for key, value in original_dict.items()} # Modify the shallow copy copied_dict["name"] = "Bob" copied_dict["address"]["city"] = "San Francisco" # Print both dictionaries print("Original Dictionary:", original_dict) print("Copied Dictionary:", copied_dict)
Output:
Original Dictionary: {'name': 'Alice', 'age': 30, 'address': {'city': 'San Francisco', 'state': 'NY'}} Copied Dictionary: {'name': 'Bob', 'age': 30, 'address': {'city': 'San Francisco', 'state': 'NY'}}
In this example:
A dictionary comprehension creates a shallow copy of the dictionary.
As before, modifications to the nested address dictionary affect both the original and copied dictionaries.
4. Deep Copying Dictionaries with copy.deepcopy()
To avoid the issue of shared references with nested dictionaries (or other nested objects), you need to create a deep copy. A deep copy recursively copies all objects inside the dictionary, including nested dictionaries or lists. The copy module provides the deepcopy() function for this purpose.
Example: Deep Copy with copy.deepcopy()
import copy # Example: Deep copying a dictionary using deepcopy() original_dict = { "name": "Alice", "age": 30, "address": { "city": "New York", "state": "NY" } } # Create a deep copy of the dictionary copied_dict = copy.deepcopy(original_dict) # Modify the deep copy copied_dict["name"] = "Bob" copied_dict["address"]["city"] = "San Francisco" # Print both dictionaries print("Original Dictionary:", original_dict) print("Copied Dictionary:", copied_dict)
Output:
Original Dictionary: {'name': 'Alice', 'age': 30, 'address': {'city': 'New York', 'state': 'NY'}} Copied Dictionary: {'name': 'Bob', 'age': 30, 'address': {'city': 'San Francisco', 'state': 'NY'}}
In this example:
The deepcopy() function creates an entirely independent copy of the dictionary, including all nested objects.
Modifications to the nested address dictionary in copied_dict do not affect original_dict, which is the key advantage of deep copying.
5. Differences Between Shallow and Deep Copy
Let’s summarize the differences between a shallow copy and a deep copy with a quick comparison:
Shallow Copy:
Creates a new dictionary with references to the same objects as the original dictionary for any mutable objects (like lists or other dictionaries).
If you modify nested objects in the copied dictionary, it will also affect the original dictionary.
Deep Copy:
Creates a new dictionary and recursively copies all objects inside it, including any nested dictionaries, lists, or other mutable objects.
Modifications to nested objects in the copied dictionary do not affect the original dictionary.
6. Copying Dictionaries with Nested Lists or Objects
Deep copying is particularly important when your dictionary contains nested objects such as lists. Let’s look at how deep copying ensures that these nested objects are handled properly.
Example: Copying a Dictionary with Nested Lists
import copy # Example: Copying a dictionary with nested lists original_dict = { "name": "Alice", "hobbies": ["reading", "swimming"], "address": { "city": "New York", "state": "NY" } } # Shallow copy using copy() shallow_copy = original_dict.copy() # Deep copy using deepcopy() deep_copy = copy.deepcopy(original_dict) # Modify the shallow copy and deep copy shallow_copy["hobbies"].append("traveling") deep_copy["hobbies"].append("cooking") # Print all dictionaries print("Original Dictionary:", original_dict) print("Shallow Copy:", shallow_copy) print("Deep Copy:", deep_copy)
Output:
Original Dictionary: {'name': 'Alice', 'hobbies': ['reading', 'swimming', 'traveling'], 'address': {'city': 'New York', 'state': 'NY'}} Shallow Copy: {'name': 'Alice', 'hobbies': ['reading', 'swimming', 'traveling'], 'address': {'city': 'New York', 'state': 'NY'}} Deep Copy: {'name': 'Alice', 'hobbies': ['reading', 'swimming', 'cooking'], 'address': {'city': 'New York', 'state': 'NY'}}
In this example:
Modifying the hobbies list in the shallow copy also affects the hobbies list in the original dictionary, because both dictionaries reference the same list object.
Modifying the hobbies list in the deep copy does not affect the original dictionary, as it was fully copied by deepcopy().
Summary
You can create a shallow copy of a dictionary using the copy() method, the dict() constructor, or a dictionary comprehension. However, with shallow copies, changes to nested objects (such as lists or dictionaries) affect both the original and copied dictionaries.
A deep copy can be created using copy.deepcopy() from the copy module, which recursively copies all objects inside the dictionary, ensuring that changes to the copied dictionary do not affect the original.
Use shallow copies when your dictionary contains only simple data types (e.g., strings, integers), and use deep copies when your dictionary contains mutable objects like lists or other dictionaries to avoid unintended side effects.
By mastering these techniques, you can safely and effectively copy dictionaries in Python to suit various use cases.