Published on

Understanding Shallow and Deep Copy in Python with the `copy` Module

Authors
  • avatar
    Name
    hwahyeon
    Twitter

The copy module in Python is used to copy objects, supporting both shallow copy and deep copy.

1. Reference Copy

a = [1, 2, 3]
b = a

In this code, b references the same list as a. b is not a copy of a; both a and b point to the same memory location. Therefore, if you change the values in a, b will reflect those changes as well.

2. Copy via Slicing

a = [1, 2, 3]
c = a[:]

This code copies the list a using slicing ([:]). The slicing operation creates a new list c, which has the same elements as a, but is a separate list. Thus, changes to a do not affect c.

3. Copy using the copy Module

import copy
a = [1, 2, 3]
d = copy.copy(a)

This code uses the copy.copy() function to create a new list d. Any changes made to a will not affect d because d is a separate list.

4. What is Shallow Copy?

Both slicing (in step 2) and copy.copy() (in step 3) are examples of shallow copying.

A shallow copy copies only the outermost list, while any nested lists (or objects) are still referenced from the original list.

For a one-dimensional list like in steps 2 and 3, the list seems fully copied because there are no nested objects. However, in the case of multi-dimensional lists, shallow copying means that only the outermost list is copied, while the inner lists continue to reference the original data.

Let's dive in!

5. Shallow Copy using the copy Module

a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
b = copy.copy(a)

In this example, b references the same inner lists as a. Therefore, if you modify a[0][0], the same change will be reflected in b[0][0] because both a and b share the same inner list.

This could be said to be like copying only the frame.

6. What is Deep Copy?

A deep copy recursively copies not just the outer list but all the nested lists and objects inside it. This means the new list and all its nested lists are completely independent of the original list!

a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
c = copy.deepcopy(a)

In this case, c is a fully independent copy of a. Any changes made to a will have no effect on c.

7. Shallow Copy via Slicing

a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
d = a[:]

Since slicing creates a shallow copy, d shares references to the inner lists with a. Thus, changes to a[0][0] will also affect d[0][0].

8. 3D List and Shallow Copy

Shallow copy behaves the same way for 3D lists.

a = [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]
b = copy.copy(a)

Here, copy.copy(a) only copies the outermost list, so if you modify a[0][0] or a[0][0][0], the same change will be reflected in b[0][0] or b[0][0][0]. The inner lists are still shared between a and b.

Why Use Shallow Copy?

  • Memory and Performance Efficiency: Deep copying large objects can increase memory usage and slow down execution. Shallow copying is more efficient when deep copying is unnecessary.
  • Shared References: Shallow copy is useful when you want multiple variables to reference the same data, so changes in one place are reflected across all references.
  • Avoiding Redundant Data: It is useful when the same data structure needs to be used in multiple places without duplicating the data unnecessarily.
  • Simpler for Flat Lists: For flat (1D) lists, shallow copying is straightforward and provides sufficient functionality without additional complexity.