How to Copy a List in Python (Shallow vs. Deep Copy)

Learn how to copy a list in Python. Explore list slicing, the copy() method, list constructors, and master the difference between shallow and deep copies.

Try Code in Editor

Explanation

In Python, lists are mutable objects, and variables hold references to these objects in memory rather than the actual values. This means that if you assign a list to a new variable (e.g., `list_b = list_a`), both variables reference the exact same list. Any modification made through `list_b` will immediately affect `list_a`. To avoid this side-effect, you must create an explicit copy of the list.

Python provides several ways to create a shallow copy of a list. A shallow copy constructs a new list containing references to the elements found in the original list. Common methods include using the built-in list `.copy()` method, using list slicing `list_a[:]`, or passing the list to the `list()` constructor. All of these create a new list container, allowing you to append or remove elements independently.

However, if a list contains nested mutable objects (like lists or dictionaries), a shallow copy will only duplicate the outer container; the nested objects remain shared. Modifying a nested list in the copy will alter the original list. To prevent this, you must perform a deep copy using the `copy` module's `deepcopy()` function, which recursively clones every object inside the hierarchy.

Step-by-Step Implementation

  1. 1

    Use my_list.copy() or my_list[:] to create a shallow copy of flat list structures.

  2. 2

    Avoid reference assignments like copy_list = my_list when you need independent collections.

  3. 3

    Import the copy module and use copy.deepcopy(my_list) for lists containing nested mutable structures.

  4. 4

    Ensure you understand your data structures to optimize performance and memory footprint.

Code Example

This code demonstrates the reference assignment trap, shallow copying using list.copy(), and deep copying nested lists using the copy module.

copy_lists.py
Try in Editor
import copy

# 1. The assignment reference trap (Not a copy!)
original = [1, 2, 3]
reference = original
reference.append(99)
print("Reference modification affects original:", original)

# Reset list
original = [1, 2, 3]

# 2. Creating a shallow copy (using list.copy())
shallow_copy = original.copy()
shallow_copy.append(100)
print("\nOriginal:", original)
print("Shallow copy:", shallow_copy)

# 3. The nested list limitation of shallow copies
nested = [[1, 2], [3, 4]]
shallow_nested = nested.copy()
shallow_nested[0].append(99) # Modifying nested list
print("\nOriginal nested:", nested)
print("Shallow nested copy:", shallow_nested)

# 4. Creating a deep copy
nested_original = [[1, 2], [3, 4]]
deep_copy = copy.deepcopy(nested_original)
deep_copy[0].append(99)
print("\nOriginal nested:", nested_original)
print("Deep copy (completely independent):", deep_copy)
Terminal Output
Reference modification affects original: [1, 2, 3, 99]

Original: [1, 2, 3]
Shallow copy: [1, 2, 3, 100]

Original nested: [[1, 2, 99], [3, 4]]
Shallow nested copy: [[1, 2, 99], [3, 4]]

Original nested: [[1, 2], [3, 4]]
Deep copy (completely independent): [[1, 2, 99], [3, 4]]

Frequently Asked Questions

What is the difference between a shallow copy and a deep copy?

A shallow copy copies the outermost container, but references nested mutable objects. A deep copy recursively duplicates all nested containers and objects, resulting in completely isolated data structures.

Is list slicing (list[:]) faster than list.copy()?

They are virtually identical in performance since both execute optimized C operations under the hood. Using list.copy() is generally preferred for readability.

Related How-To Guides

Recommended Python Resources

Expand your knowledge with related interactive tutorials, cheat sheets, and code comparisons.