Shallow Copy and Deep Copy in Python

In Python, copying objects is a common operation that can be done in various ways. However, it’s crucial to understand the difference between shallow copy and deep copy to avoid unexpected behavior in your programs. In this article, we will delve into the concepts of shallow and deep copies, their differences, and how to use them with practical coding examples.

Introduction to Copying in Python

Copying in Python can be done using various methods, but the two primary types are shallow copying and deep copying. These methods determine how the objects and their nested structures are duplicated.

Shallow Copy

A shallow copy creates a new object, but inserts references into it to the objects found in the original. In other words, only one level of the object is copied, and the references to the nested objects are shared between the original and the copy.

Deep Copy

A deep copy creates a new object and recursively copies all objects found in the original. This means that the copy and the original are completely independent, and changes to the copy will not affect the original and vice versa.

Using the copy Module

Python provides the copy module, which contains copy() and deepcopy() functions for shallow and deep copying, respectively.

Importing the Copy Module

import copy

Shallow Copy with copy.copy()

Let’s create a shallow copy of a list containing nested lists.

import copy

original_list = [1, 2, [3, 4], 5]
shallow_copied_list = copy.copy(original_list)

print("Original List:", original_list)
print("Shallow Copied List:", shallow_copied_list)

If we modify the nested list in the original list, the changes will be reflected in the shallow copied list.

original_list[2][0] = 'Changed'

print("Modified Original List:", original_list)
print("Shallow Copied List After Modification:", shallow_copied_list)

Deep Copy with copy.deepcopy()

Let’s create a deep copy of a list containing nested lists.

import copy

original_list = [1, 2, [3, 4], 5]
deep_copied_list = copy.deepcopy(original_list)

print("Original List:", original_list)
print("Deep Copied List:", deep_copied_list)

If we modify the nested list in the original list, the changes will not be reflected in the deep copied list.

original_list[2][0] = 'Changed'

print("Modified Original List:", original_list)
print("Deep Copied List After Modification:", deep_copied_list)

Output:

Original List: [1, 2, ['Changed', 4], 5]
Deep Copied List: [1, 2, [3, 4], 5]

Practical Examples

Example 1: Shallow Copy with a Dictionary

Shallow copying a dictionary containing nested dictionaries.

import copy

original_dict = {'a': 1, 'b': {'c': 2, 'd': 3}}
shallow_copied_dict = copy.copy(original_dict)

print("Original Dictionary:", original_dict)
print("Shallow Copied Dictionary:", shallow_copied_dict)

original_dict['b']['c'] = 'Changed'

print("Modified Original Dictionary:", original_dict)
print("Shallow Copied Dictionary After Modification:", shallow_copied_dict)

Output:

Original Dictionary: {'a': 1, 'b': {'c': 'Changed', 'd': 3}}
Shallow Copied Dictionary: {'a': 1, 'b': {'c': 'Changed', 'd': 3}}

Example 2: Deep Copy with a Dictionary

Deep copying a dictionary containing nested dictionaries.

import copy

original_dict = {'a': 1, 'b': {'c': 2, 'd': 3}}
deep_copied_dict = copy.deepcopy(original_dict)

print("Original Dictionary:", original_dict)
print("Deep Copied Dictionary:", deep_copied_dict)

original_dict['b']['c'] = 'Changed'

print("Modified Original Dictionary:", original_dict)
print("Deep Copied Dictionary After Modification:", deep_copied_dict)

Output:

Original Dictionary: {'a': 1, 'b': {'c': 'Changed', 'd': 3}}
Deep Copied Dictionary: {'a': 1, 'b': {'c': 2, 'd': 3}}

Understanding the Differences

Memory Usage

  • Shallow Copy: Uses less memory since it only copies references to the original objects.
  • Deep Copy: Uses more memory as it creates completely independent copies of all objects.

Performance

  • Shallow Copy: Faster due to less copying.
  • Deep Copy: Slower because it recursively copies all objects.

Use Cases

  • Shallow Copy: Suitable for scenarios where you need a copy of an object but don’t intend to modify nested objects.
  • Deep Copy: Necessary when you need a completely independent copy of an object, including all nested objects.

Understanding shallow and deep copies in Python is essential for managing data structures and ensuring your code behaves as expected. These concepts are particularly important when working with mutable objects like lists and dictionaries, where changes to one object can inadvertently affect another if they are not properly copied.

Key Points

Shallow Copy

  • Definition: A shallow copy creates a new object but inserts references into it to the objects found in the original. This means that the new object is a mix of new and old references.
  • Use Case: Shallow copies are useful when you need a copy of an object, but the nested objects don’t need to be independent of the original. For instance, shallow copies are sufficient when working with simple lists or dictionaries where the top-level structure might change, but the nested elements remain constant.
  • Memory Efficiency: Shallow copying is memory efficient because it doesn’t create duplicates of the nested objects. Instead, it just copies the references to those objects.
  • Performance: Shallow copies are faster to create because they involve less data duplication.

Deep Copy

  • Definition: A deep copy creates a new object and recursively copies all objects found in the original. This means that the new object is completely independent of the original.
  • Use Case: Deep copies are necessary when you need a completely independent copy of an object, including all nested objects. This is particularly useful in scenarios where changes to the nested objects in the original should not affect the copied object, such as when dealing with complex nested structures or when the data integrity of the copied object is critical.
  • Memory Usage: Deep copying is more memory-intensive because it creates duplicates of all nested objects.
  • Performance: Deep copies take longer to create due to the recursive nature of the copying process, which duplicates every nested object.

Practical Implications

  • Avoiding Unintended Side Effects: One of the most significant practical implications of understanding shallow and deep copies is avoiding unintended side effects in your programs. For example, if you mistakenly use a shallow copy when a deep copy is needed, changes to nested objects in the original will reflect in the copy, leading to potential bugs and data corruption.
  • Optimizing Performance and Memory Usage: Knowing when to use shallow versus deep copies allows you to optimize both performance and memory usage. Shallow copies can be used for lightweight, fast duplications, while deep copies should be reserved for cases where complete independence between the original and copy is necessary.
  • Complex Data Structures: When dealing with complex data structures, such as trees or graphs, where objects are deeply nested, understanding the distinction between these two types of copies is crucial. Deep copying ensures that the entire structure is replicated accurately, whereas shallow copying can lead to incomplete or incorrect duplications.

Conclusion

In conclusion, mastering the concepts of shallow and deep copies in Python is vital for any programmer working with mutable data structures. These concepts help ensure that your data remains consistent and that your programs behave as expected. By understanding and correctly applying shallow and deep copies, you can prevent unintended side effects, optimize your code’s performance and memory usage, and manage complex data structures effectively.

Whether you’re working on simple lists or complex nested dictionaries, the knowledge of when to use shallow and deep copies will make your code more robust, maintainable, and efficient.

Author

Sona Avatar

Written by

Leave a Reply

Trending

CodeMagnet

Your Magnetic Resource, For Coding Brilliance

Programming Languages

Web Development

Data Science and Visualization

Career Section

<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4205364944170772"
     crossorigin="anonymous"></script>