Aliasing, Shallow copy and Deep copy in Python

2021-01-10

In python, a list can be assigned to a variable in many ways, we will learn about the following three:

  • Aliasing
  • Shallow Copy
  • Deep Copy

Let us see the differences one by one. We will take a list original_list and will create new_list using above methods. Then we will do some operations on original_list and will check how it impacts new_list.

Aliasing

original_list = [[1,2],[4,6]]
new_list = original_list                         #ALIASING

original_list[0].append(6)            
#updated 1st element in original_list

original_list.append([5,6,8])
#added new element in original_list

print('original_list  ->  '+ str(original_list))
print('new_list       ->  ' +str(new_list))

#OUTPUT 
original_list  ->  [[1, 2, 6], [4, 6], [5, 6, 8]]
new_list       ->  [[1, 2, 6], [4, 6], [5, 6, 8]]
#all changes reflected in both lists

It does not create a copy of original_list to new_list. It just creates an alias i.e. both the variables can be used to access the same list.

In our example, on updating first element of original_list and on adding a new element to the original_list, we see the changes are also reflected in new_list.

Shallow Copy

original_list = [[1,2],[4,6]]
new_list = list(original_list)                 #SHALLOW COPY

original_list[0].append(6)
#updated 1st element in original_list

original_list.append([5,6,8])
#added new element in original_list

print('original_list  ->  '+ str(original_list))
print('new_list       ->  ' +str(new_list))

#OUTPUT
original_list  ->  [[1, 2, 6], [4, 6], [5, 6, 8]]
new_list       ->  [[1, 2, 6], [4, 6]]
#1st element impacted in both lists but new element only added to original

It creates a copy of original_list and assign it to new_list. However both lists are still referencing to the same original elements (elements which were there in original_list before copying). So any updation of these elements is reflected in both the lists. While if we remove or add a new element to either list, that will not be reflected in the other one.

We see in our example, on updating first element of original_list, first element of new_list also gets updated because both the lists are referencing to the same element saved in memory. But on adding new element to original_list, new_list is not impacted.

Deep Copy

With shallow copy we can add or remove element from one list without impacting the other but can not update the original elements without impacting the other. For that, we need deep copy. We have a module ‘copy’ for that purpose.

import copy
original_list = [[1,2],[4,6]]
new_list = copy.deepcopy(original_list)            #DEEP COPY

original_list[0].append(6)

original_list.append([5,6,8])

print('original_list  ->  '+ str(original_list))
print('new_list       ->  ' +str(new_list))

original_list  ->  [[1, 2, 6], [4, 6], [5, 6, 8]]
new_list       ->  [[1, 2], [4, 6]]
#nothing changed in new_list

It creates a new copy of the elements in memory which were present in original_list before copying of list. So both the lists now reference to different elements. Hence updating, adding or removing of any element in either list does not impact the other one.

In our example, we can see that new_list remains unchaged after updating and adding element in original_list.

Note - we can also do this -> new_list = copy.copy(original_list) for shallow copy. This is equivalent to new_list = list(original_list)