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!