How to Deep Copy a List in Python

Samyak Jain Feb 02, 2024
  1. Shallow Copy vs Deep Copy
  2. Use the copy.deepcopy() Function to Deep Copy a List in Python
  3. Use List Comprehension to Deep Copy a List in Python
How to Deep Copy a List in Python

We can create shallow and deep copies in Python. A deep copy of a list is to create a new list and then recursively insert in it the copies of the original list’s elements. It refers to cloning a list, and any changes made in the original list do not affect the cloned list.

Deep copying is a process that creates a new object that is a duplicate of an existing object, along with duplicates of any objects referenced by the original object, recursively. This is particularly important when dealing with complex data structures like lists, dictionaries, or any custom objects which may have nested objects within them.

When a deep copy operation is performed, the new data structure is entirely independent of the original. Any changes made to the new data structure do not affect the original data structure, and vice versa.

Shallow Copy vs Deep Copy

The counterpart to deep copying is shallow copying. Unlike deep copying, a shallow copy creates a new object, but does not create copies of the objects that the original object references. Instead, the new object maintains references to the original objects. This means that if you modify the nested objects in the new, shallowly copied object, you’ll also modify the nested objects in the original object.

To illustrate this with an example, consider a list A with nested lists:

A = [[1, 2], [3, 4]]

Now, let’s create a shallow copy of list A:

import copy

B = copy.copy(A)

If we modify an element in list B, it will also affect list A because the nested lists are not copied, only referenced:

B[0][0] = 0
print(A)

Output:

[[0, 2], [3, 4]]

On the other hand, if we create a deep copy of list A, changes to the deep copy will not affect the original list:

C = copy.deepcopy(A)
C[0][0] = 5
print(A)

Output:

[[1, 2], [3, 4]]

Understanding the difference between shallow and deep copying is crucial for managing data effectively in Python, especially when working with mutable objects or complex, nested data structures. Making the right choice between a shallow copy and a deep copy can prevent bugs, ensure data integrity, and improve the readability and maintainability of your code.

Use the copy.deepcopy() Function to Deep Copy a List in Python

The deepcopy() function within Python’s copy module, is a powerful tool for creating deep copies of lists, among other data structures. When a deep copy of a list is created using this function, a new list is formed with new instances of every element found in the original list.

This is especially crucial when the list contains objects or other lists (nested lists), as it ensures that the new list is entirely independent of the original one. This independence is manifested in that changes to the deep copy have no impact on the original list, and vice versa.

Let’s delve into the provided example to elucidate this concept further.

import copy

A = [[10, 60], [50, "Hi"], ["Hello", 5, 80]]
B = copy.deepcopy(A)
A[2][0] = "World"
A[0][1] = 10
print("List A is : % s" % (A))
print("List B is : % s" % (B))

Output:

List A is : [[10, 10], [50, 'Hi'], ['World', 5, 80]]
List B is : [[10, 60], [50, 'Hi'], ['Hello', 5, 80]]
  • In list A, we observe the modifications we made: the first element of the third list has changed to World, and the second element of the first list has changed to 10.
  • Conversely, list B remains unaltered. Despite the changes in list A, list B retains its original structure and values. This is because list B is a deep copy of list A, and they are entirely independent of each other.

The deepcopy() function traverses the original list A recursively and creates new instances of every item it encounters, forming a completely separate list B. This recursive copying process is what makes deepcopy() a reliable choice for copying complex, nested data structures.

The independence betwe

Use List Comprehension to Deep Copy a List in Python

List comprehension is a concise and expressive technique in Python used for creating new lists by applying an expression to each item in an iterable, like lists, tuples, strings, and more. It’s cherished for its simplicity and efficiency in code writing.

In the context of copying a list, list comprehension can be employed to generate a new list with the same elements. However, it’s imperative to note that this method performs a shallow copy for nested lists, not a deep copy like the deepcopy() function from the copy module.

Let’s explore this through the following example:

A = [2, 4, 6, 8, 10]
B = [i for i in A]
A[0] = "Hi"
print("List A is : % s" % (A))
print("List B is : % s" % (B))

Running the above code will yield the following output:

Analysing the Output:

  • After modifying the first element of list A, list B remains unaffected. This is because list comprehension has created a new list B with new instances of the elements from list A.
  • However, it’s crucial to note that this method creates a shallow copy of the original list, not a deep copy. This means that if the list contains nested objects, changes to the nested objects in the copied list will affect the original list.

Although list comprehension provides a more concise and Pythonic way to copy a list, it’s crucial to use the deepcopy() function for nested lists to ensure a true deep copy is created, preserving the independence of the original and copied lists.

In essence, list comprehension is a quick and readable method for copying one-dimensional lists. However, for more complex, nested lists or when a true deep copy is required, leveraging the deepcopy() function from the copy module is the recommended approach.

Pitfalls When Using List Comprehnsion to Copy a Nested List

When dealing with nested lists, using list comprehension will result in a shallow copy rather than a deep copy. This means that while the outer list is copied, the nested lists within it are not - they are simply referenced. Let’s delve into this concept with an example:

# Defining a nested list 'A'
A = [[1, 2], [3, 4]]

# Attempting to create a new list 'B' using list comprehension
B = [i for i in A]

# Modifying an element in the nested list within 'B'
B[0][0] = 0

# Printing the lists to observe the changes
print("List A is : % s" % (A))
print("List B is : % s" % (B))

Output:

List A is : [[0, 2], [3, 4]]
List B is : [[0, 2], [3, 4]]

Explanation:

  1. Creation of Nested List:
    • Initially, a nested list A is created with two sub-lists.
  2. Shallow Copy Using List Comprehension:
    • A new list B is then created using list comprehension, which iterates through list A and copies its elements into list B.
  3. Modification:
    • An element within the nested list of B is then modified. Specifically, the first element of the first sub-list is changed from 1 to 0.
  4. Observation:
    • Upon printing both lists, it’s observed that the modification has affected both lists A and B. This is indicative of a shallow copy since the nested lists within A and B are not independent of each other but rather refer to the same underlying objects.
  5. Implication:
    • This behavior demonstrates the limitation of using list comprehension for deep copying, especially with nested lists. The outer list is copied, but the nested lists are merely referenced, leading to unintended side effects when either list is modified.

Related Article - Python List