Copy or clone a list in Python
Introduction
Copying data structures such as lists is a frequently performed task in computer programming. For instance, one of the most efficient sorting algorithms is merge sort. Merge sort uses divide and conquer approach to split the unsorted list into two sections in a recursive fashion. To do so, merge sort uses list copying technique. You may check the following post for more information.
Getting back to the main topic, we are going to summarize different ways to copy lists in Python. Let us get started…
List assignment
Before we dive into our topic, let us clarify an import point. In Python, assigning a list to another one does not perform any copying. Assignment only copies the reference. The end result is having two pointers to the same data. If we modify one, the other is modified automatically. The id built in function can be used to prove that both lists have the same id. Actual copying produces distict ids. Here is an example…
1 2 3 4 5 6 7 8 9 10 11 |
# Define list A A = [1, 2, 3] # Assign A to B B = A # Print lists print(A) print(B) # This should print: True print(id(A)==id(B)) |
If you run the code snippet above, you should get the following output…
1 2 3 |
[1, 2, 3] [1, 2, 3] True |
As you can see, both A and B have the same id meaning they both point to the same memory location.
List slicing
Slicing in Python is handy when it comes to extracting data from lists. Using slicing technique to clone a list is a little bit odd but it does the job perfectly. Slicing creates a new list and copies elements from the source list. Here is an example…
1 2 3 4 5 6 7 8 9 10 11 |
# Define list A A = [1, 2, 3] # Copy A to B using slicing B = A[:] # Print lists print(A) print(B) # This should print: False print(id(A)==id(B)) |
If you run the code snippet above, you should get two different lists with distinct ids…
1 2 3 |
[1, 2, 3] [1, 2, 3] False |
Note that slicing performs shallow copying. In other words, if the source list contains objects then only the references to those objects are copied. Here is an example…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# Define list A A = [1, [2, 3, 4], 5] # Copy list A to B B = A[:] # Print A and B # They should contain the same elements print(A) print(B) # A and B are different lists so this # should print: False print(id(A) == id(B)) # Modify element 3 in the sublist to 7 B[1][1] = 7 # Add one more element to B B.append(6) # This should print: [1, [2, 7, 4], 5] # because the sublist is shared between # the two copies meaning it is shallow # copying print(A) # This should print: [1, [2, 7, 4], 5, 6] print(B) # This should print: True because the sublist # is shared between the two print(id(B[1])==id(A[1])) |
Here is the output for the above code snippet…
1 2 3 4 5 6 |
[1, [2, 3, 4], 5] [1, [2, 3, 4], 5] False [1, [2, 7, 4], 5] [1, [2, 7, 4], 5, 6] True |
List construction
A list object in Python can be constructed from any other object of sequence type. This means we can clone an existing list using the list constructor. Here is an example…
1 2 3 4 5 6 7 8 9 10 11 12 |
# Define list A A = [1, 2, 3] # Copy A to be using construction B = list(A) # Print A and B print(A) print(B) # This should print: False becasue # A and B are two different lists print(id(A)==id(B)) |
Construction also works with generators. Here is an example…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# List comprehension A = [x * 2 for x in range(5)] # Copy A to B B = list(A) # Create C from a generator C = list(x * 2 for x in range(5)) # Print all lists print(A) print(B) print(C) # These should print: False print(id(A)==id(B)) print(id(A)==id(C)) |
If you run the code snippet above, you should get the following output…
1 2 3 4 5 |
[0, 2, 4, 6, 8] [0, 2, 4, 6, 8] [0, 2, 4, 6, 8] False False |
For more information about generators, you may check the following post.
Copy module
Python offers a dedicated module for copying. In the next two sections we will see how to perform shallow and deep copying using the copy module…
Shallow copy
Using the same example mentioned earlier but using the copy.copy() method…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# Import the copy module import copy # Define list A A = [1, [2, 3, 4], 5] # Copy list A to B B = copy.copy(A) # Print A and B # They should contain the same elements: # [1, [2, 3, 4], 5] print(A) print(B) # A and B are different lists so this # should print: False print(id(A) == id(B)) # Modify element 3 in the sublist to 7 B[1][1] = 7 # Add one more element to B B.append(6) # This should print: [1, [2, 7, 4], 5] # because the sublist is shared between # the two copies meaning it is shallow # copying print(A) # This should print: [1, [2, 7, 4], 5, 6] print(B) # This should print: True becaue the sublist # is shared between the two print(id(B[1])==id(A[1])) |
We should get the same output we got earlier using slicing…
1 2 3 4 5 6 |
[1, [2, 3, 4], 5] [1, [2, 3, 4], 5] False [1, [2, 7, 4], 5] [1, [2, 7, 4], 5, 6] True |
Deep copy
If the list contains objects, deepcopy should be used. Here is an example…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
import copy # Define list A A = [1, [2, 3, 4], 5] # Copy list A to B B = copy.deepcopy(A) # Print A and B # They should contain the same elements: # [1, [2, 3, 4], 5] print(A) print(B) # A and B are different lists so this # should print: False print(id(A) == id(B)) # Modify element 3 in the sublist to 7 B[1][1] = 7 # Add one more element to B B.append(6) # This should print: [1, [2, 3, 4], 5] # because the sublist is not shared between # the two copies meaning it is deep copying print(A) # This should print: [1, [2, 7, 4], 5, 6] print(B) # This should print: False becaue the sublist # is not shared between the two print(id(B[1])==id(A[1])) |
If you run the code snippet above, you should get the following output…
1 2 3 4 5 6 |
[1, [2, 3, 4], 5] [1, [2, 3, 4], 5] False [1, [2, 3, 4], 5] [1, [2, 7, 4], 5, 6] False |
Copy method
In Python 3.x, the list data structure has a shallow copy method. This is not supported in Python 2.x. Here is an example…
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# Define list A A = [1, 2, 3] # Copy list A to B B = A.copy() # Print A and B # They should contain the same elements print(A) print(B) # A and B are different lists so this # should print: False print(id(A) == id(B)) |
If you run the code snippet above, you should get the following output…
1 2 3 |
[1, 2, 3] [1, 2, 3] False |
extend function
Extending a list can also be used to copy another list. For more information about extend, you may check the following post. Let us take an example…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# Define list A A = [1, 2, 3] # Copy list A to B B = [] B.extend(A) # Print A and B # They should contain the same elements print(A) print(B) # A and B are different lists so this # should print: False print(id(A) == id(B)) |
If you run the code snippet above, you should get the following output…
1 2 3 |
[1, 2, 3] [1, 2, 3] False |
List comprehension
List comprehension can also be used to copy lists. For more information about list comprehension, you may check the following post. Let us take an example…
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# Define list A A = [1, 2, 3] # Copy list A to B B = [i for i in A] # Print A and B # They should contain the same elements print(A) print(B) # A and B are different lists so this # should print: False print(id(A) == id(B)) |
If you run the code snippet above, you should get the following output…
1 2 3 |
[1, 2, 3] [1, 2, 3] False |
Manual copying using append
Appending to an existing list can be used to copy data from another list. Here is an example…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# Define list A A = [1, 2, 3] # Copy list A to B B = [] for i in A: B.append(i) # Print A and B # They should contain the same elements print(A) print(B) # A and B are different lists so this # should print: False print(id(A) == id(B)) |
If you run the code snippet above, you should get the following output…
1 2 3 |
[1, 2, 3] [1, 2, 3] False |
Time to summarize…
Summary
- There are various ways to clone a list in Python. Which method to use depends on preference, performance or convenience
- Shallow copying copies elements and references to nested structures
- Deep copying copies all elements including nested data structures
- List assignment copies only the reference
- Lists in Python can be copied using slicing, construction, copy module, copy list method
- Other methods to copy lists include extending a list, list comprehension or appending elements
References
Thanks for visiting. For feedback, please use the comments section below.