Python list copy – How to perform shallow copy and deep copy
Python list copy involves copying or cloning lists. Lists can store literally any type of data. Whether it’s a primitive data type like int or float or an object or another list, all can fit into a list. Situations arise when the content of one list needs to be copied into another. As easy you might have found python programming to be, if you don’t understand how things work, you’ll be in trouble. Assigning the list to another variable does not copy the list but it copies only the reference. In this case, when you make any change to the new list, it gets reflected in the older one. This might not be what you want.
The very first thing you must understand is that python lists can be of two types:
- Simple Lists – These are lists which contain data of primitive types. There are a few standard methods which can be used while performing a copy of a simple list. Remember that shallow and deep copy does not apply to simple lists. So be careful while performing them.
- Compound Lists – These are also called as compound objects. They contain other compound objects like dictionaries, other lists, class instances, etc. We can apply shallow and deep copy to these types of lists.
There are many ways in which python list copy can be performed by you. Some might be looking for the shortest way and a few others for the quickest. Python list copy on compound lists consists of two major techniques: Shallow Copy and Deep Copy. Before we get into these two types of copying methods, let us first see the quickest ways to copy simple lists.
Let us consider the following simple and compound lists:
list_one = [222,333,555,666,888] # this is a simple list list_two = ["one", "two", "three", "four"] # this is another simple list list_three = [list_one, list_two] # this is a compund list as it consists of two lists.
Python list copy on Simple Lists
Following are methods to copy simple lists. These methods are listed from the fastest method to the slowest method to perform the copy.
import copy list_copy_1 = list_one[:] # this is called list slicing. This is the fastest method. list_copy_2 = list(list_one) # using the inbuilt list() method. list_copy_3 = copy.copy(list_two) #using the copy module list_copy_4 = [item for item in list_two] # this is the list comprehension method.
Some useful links:
For those of you who want to know more about these methods, here are some useful links to official python docs:
- Python list slicing: Though this is the fastest method, many people might refrain from using it just coz this does not look like a good solution. However, if you want to optimize your code, then go ahead with this.
- List Comprehensions: These provide a one line solution to creating/ copying lists.
- Python Copy module
Python list copy on Compound lists
So, now you know that there are two types of copying mechanisms available when you are dealing with compound lists. It is important that you clearly understand which technique has to be applied in which scenario. Let’s go through them individually.
Shallow Copy
Shallow copy creates a new compound list, but instead of creating copies of the objects within the old list, it just copies the references of those objects into the new list. To understand it better, let’s see an example.
import copy print list_three #output is: [[222, 333, 555, 666, 888], ['one', 'two', 'three', 'four']] new_list2 = copy.copy(list_three) # copy() is used to perform shallow copy and note that list_three is a compound list. print new_list2 # output is: [[222, 333, 555, 666, 888], ['one', 'two', 'three', 'four']] print new_list2[0] == list_three[0] #output: True list_one.append(999) print list_three # you can observe that the newly appended number has been reflected correctly. #output:[[222, 333, 555, 666, 888, 999], ['one', 'two', 'three', 'four']] print new_list2 # here too, the change in the object has been clearly reflected. #output: [[222, 333, 555, 666, 888, 999], ['one', 'two', 'three', 'four']] print id(new_list2) == id(list_three) # code to see if both the lists are the same? #output False
From the example above, we can see that though a new compound list has been created ( indicated by the difference in ids), the lists inside them are just references (indicated as change made to list one can be seen on both list_three and new_list2). Thus making a change in one of the objects will result in a change in the other.
Deep Copy
Deep copy doesn’t just create a new compound list, it also creates a new object for all the nested objects within the original list. This means that if you make a change to one of the objects in the list do not affect the other at all in any way. Just like in the previous case, let us take an example and learn more about it.
import copy print list_three #output is: [[222, 333, 555, 666, 888], ['one', 'two', 'three', 'four']] new_list3 = copy.deep_copy(list_three) print new_list3 # output is: [[222, 333, 555, 666, 888], ['one', 'two', 'three', 'four']] print new_list3[0] == list_three[0] #output: False #note that in the above case, the check returned false as the two objects are now different, thanks to the deep copy. list_one.append(123) print list_three # you can observe that the newly appended number has been reflected correctly. #output:[[222, 333, 555, 666, 888, 999, 123], ['one', 'two', 'three', 'four']] print new_list3 # Observe in the output here that the first list hasn't been affected, unlike in the case of shallow copy. #output: [[222, 333, 555, 666, 888, 999], ['one', 'two', 'three', 'four']]
From this, we can clearly see that deep copy creates a copy of the inner objects in a list. Hence you can now confirm that the deep copy creates a new object even to the innermost object in a given list.
Conclusion
I hope the differences in the two types of python list copy methods are clear. In conclusion, If you want to have a copy of the list which is not affected by changes made to the original one, use the deep copy. Shallow copy will do the job for you in all other cases.
Don’t forget to subscribe to my blog to get such amazing python content straight to your inbox. Have any thoughts? share them in the comment section below!
Dude, image explains a lot. Thanks for that.
Glad you found this useful 🙂
Thanks for the explanation. I see there is a mistake in the code which u have mentioned.
import copy
print list_three
#output is: [[222, 333, 555, 666, 888], [‘one’, ‘two’, ‘three’, ‘four’]]
new_list3 = copy.deep_copy(list_three)
print new_list3
# output is: [[222, 333, 555, 666, 888], [‘one’, ‘two’, ‘three’, ‘four’]]
print new_list3[0] == list_three[0] ==> Here output is true right there is no change did in list_three and new_list3
#output: False
#note that in the above case, the check returned false as the two objects are now different, thanks to the deep copy.
thanks for the comment, I will have a look and edit it!