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!

 

akshay pai

I am a data science engineer and I love working on machine learning problems. I have experience in computer vision, OCR and NLP. I love writing and sharing my knowledge with others. This is why I created Source Dexter. Here I write about Python, Machine Learning, and Raspberry Pi the most. I also write about technology in general, books and topics related to science. I am also a freelance writer with over 3 years of writing high-quality, SEO optimized content for the web. I have written for startups, websites, and universities all across the globe. Get in Touch! We can discuss more.

4 thoughts on “Python list copy – How to perform shallow copy and deep copy

  • November 16, 2018 at 12:56 pm
    Permalink

    Dude, image explains a lot. Thanks for that.

    Reply
  • July 23, 2019 at 1:01 pm
    Permalink

    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.

    Reply

Leave a Reply