Sling Academy
Home/Python/Cloning a List in Python (Deep Copy & Shallow Copy)

Cloning a List in Python (Deep Copy & Shallow Copy)

Last updated: June 13, 2023

What is list cloning?

In Python, “cloning a list” means creating a new list object that has the same elements as an existing list. The cloned list is a separate entity from the original list, meaning any modifications made to one list do not affect the other. Cloning allows you to create a copy of a list to work with independently, preserving the original list in its original state.

Shallow Copy and Deep Copy

A shallow copy in Python creates a new list that references the original elements. It copies the top-level structure of the list but not the nested objects. If the original list contains nested objects, both the original list and the shallow copy will refer to the same nested objects. Changes to nested objects affect both the original list and the shallow copy.

A deep copy, however, creates a completely independent copy of the original list and its nested objects. Changes made to the deep copy do not affect the original list.

The choice between shallow copy and deep copy depends on whether your list contains nested objects or not:

  • If your original list contains only simple, immutable objects like numbers and strings, a shallow copy is generally faster and more memory-efficient than a deep copy.
  • If your original list contains nested and mutable objects, a deep copy is necessary to create a completely independent clone. However, this can be computationally expensive and memory-intensive, especially for large or complex data structures.

Best ways to clone a list in Python

Using the copy.deepcopy() function (deep copy)

This method is simple and concise and allows you to deep-copy lists of any size, shape, and data type. You don’t need to worry about writing your own logic or handling exceptions. You can also use this method to deep copy other types of objects, such as dictionaries, sets, tuples, etc.

copy is a standard Python library, so you don’t have to install any things. Just import it, and you’re ready to go.

Example:

# Importing the copy module
import copy

# Creating an original list
original_list = [1, 2, 3, ['a', 'b', 'c'], {'key': 'slingacademy.com'}]

# Deep copying the list using copy.deepcopy function
cloned_list = copy.deepcopy(original_list)

# Modify the cloned list
cloned_list[3][0] = 'X'
cloned_list[4]['key'] = 'Python'

# Printing both lists again
print("Original List:", original_list)
print("Cloned List:", cloned_list) 

Output:

Original List: [1, 2, 3, ['a', 'b', 'c'], {'key': 'slingacademy.com'}]
Cloned List: [1, 2, 3, ['X', 'b', 'c'], {'key': 'Python'}]

This approach works well in all scenarios, especially when you don’t know the structure of your list (such as when it is dynamically fetched from an API). However, in cases where you can be sure that your input list doesn’t contain nested and mutable objects, using a shallow copying technique might be faster.

Using the slice operator (shallow copy)

This is the easiest and fastest way to create a clone of a list in Python as long as the original list only contains immutable objects like strings or numbers. You just need to use square brackets [] and a colon : to create a slice of the original list that contains all its elements.

Example:

original_list = ['sling', 'academy', 'python']
clone_list = original_list[:]

# modify the clone list
clone_list.append('programming')

# print both lists
print('Original list:', original_list)
print('Clone list:', clone_list)

Output:

Original list: ['sling', 'academy', 'python']
Clone list: ['sling', 'academy', 'python', 'programming']

Keep in mind that you should only use this approach with simple lists.

Using the list.copy() method (shallow copy)

An alternative solution for producing a shallow copy of a list is to use the built-in list.copy() method.

Example:

original_list = ['sling', 'academy', 'python']

clone_list = original_list.copy()

# modify the clone list
clone_list.append('programming')
clone_list[0] = 'coding'

# print both lists
print('Original list:', original_list)
print('Clone list:', clone_list)

Output:

Original list: ['sling', 'academy', 'python']
Clone list: ['coding', 'academy', 'python', 'programming']

Using recursive slicing (deep copy)

You can also manually implement your own custom function to deep copy a nested list. The main idea here is to use square brackets [] and a colon : to create a slice of the original list that contains all its elements. However, instead of assigning this slice to a new list directly, you can use a recursive function that checks if each element is a list itself. If so, it calls itself on that element and returns a slice of it. Otherwise, it returns the element itself. This creates a new list object that is independent of the original list.

Example:

# Defining a recursive function to deep copy a list
def custom_deep_copy_list(original_list):
    # Creating an empty list
    cloned_list = []
    # Looping over each element of the original list
    for element in original_list:
        # If the element is a list itself, call the function on it and append its slice
        if isinstance(element, list):
            cloned_list.append(custom_deep_copy_list(element)[:])
        # If the element is not a list, append it directly
        else:
            cloned_list.append(element)
    # Returning the new list as a slice
    return cloned_list[:]

# Creating an original list
original_list = [1, 2, 3, ['a', 'b', 'c'], {'key': 'slingacademy.com'}]

# Deep copying the list using copy.deepcopy function
cloned_list = custom_deep_copy_list(original_list)

# Modify the cloned list
cloned_list[3][0] = 'X'
cloned_list[4]['key'] = 'Python'

# Printing both lists again
print("Original List:", original_list)
print("Cloned List:", cloned_list) 

Output:

Original List: [1, 2, 3, ['a', 'b', 'c'], {'key': 'Python'}]
Cloned List: [1, 2, 3, ['X', 'b', 'c'], {'key': 'Python'}]

This approach is more verbose than using the copy.deepcopy() function, but doesn’t add any performance benefits. I put it here for your reference, but don’t recommend using it in real-world tasks.

Conclusion

We’ve explored several ways to clone a list in Python. Choose the ones that suit your needs to go with. Happy coding & have a nice day!

Next Article: Python: How to Remove Duplicates from a List (with Examples)

Previous Article: Python: How to Flatten a Nested List (3 Approaches)

Series: Python List Tutorials (Basic and Advanced)

Python

You May Also Like

  • Python TypeError: write() argument must be str, not bytes
  • 4 ways to install Python modules on Windows without admin rights
  • Python TypeError: object of type ‘NoneType’ has no len()
  • Python: How to access command-line arguments (3 approaches)
  • Understanding ‘Never’ type in Python 3.11+ (5 examples)
  • Python: 3 Ways to Retrieve City/Country from IP Address
  • Using Type Aliases in Python: A Practical Guide (with Examples)
  • Python: Defining distinct types using NewType class
  • Using Optional Type in Python (explained with examples)
  • Python: How to Override Methods in Classes
  • Python: Define Generic Types for Lists of Nested Dictionaries
  • Python: Defining type for a list that can contain both numbers and strings
  • Using TypeGuard in Python (Python 3.10+)
  • Python: Using ‘NoReturn’ type with functions
  • Type Casting in Python: The Ultimate Guide (with Examples)
  • Python: Using type hints with class methods and properties
  • Python: Typing a function with default parameters
  • Python: Typing a function that can return multiple types
  • Python: Typing a function with *args and **kwargs