Today we will learn about Python copy class. We will also learn about shallow copy, deep copy and and why do we need these different copy operations.
Python Copy
Python library provides us a Copy class with two operations – copy(x)
and deepcopy(x)
– for shallow copy and deep copy respectively. But why do we need them? Why can’t simple assignment of one object to another using equals operator is good enough?
The reason is that when we use equals python operator to create a new object, it actually creates a reference to the same object in the memory. Since both the variables refer to same object, any change in one will be reflected in other too. Most of the times we don’t want that, hence the need of a separate copy operation. Let’s prove our theory about assignment operator through a simple example.
1 2 3 4 5 6 7 |
old_list = [1, 2, 3, 4] new_list = old_list new_list.append(5) print("new_list items : ", new_list) print("old_list items : ", old_list) |
Output of above python program is:
1 2 3 4 |
new_list items : [1, 2, 3, 4, 5] old_list items : [1, 2, 3, 4, 5] |
Notice that we didn’t changed old_list but since both the lists were pointing to same object, any change in one of them got reflected in other too.
Also if we have an immutable object then assignment operator is good enough as the object value will not change.
Shallow Copy
When we use python shallow copy function copy()
, it actually creates a new object and then insert references of the objects found in the original object. So shallow copy is good enough in above case where we have a list of integers because the list elements are immutable. But it’s not good enough when we have a list of list. We will look into deep copy later, let’s first look at the python shallow copy example.
1 2 3 4 5 6 7 8 9 10 |
import copy old_list = [1, 2, 3, 4] # python copy - shallow copy new_list = copy.copy(old_list) new_list.append(5) print("new_list items : ", new_list) print("old_list items : ", old_list) <img class="alignnone wp-image-22886 size-full" src="http://all-learning.com/wp-content/uploads/2017/10/Python-Copy..png" alt="Python Copy" width="1200" height="628" /> |
As you can see in above output that the change in new_list
didn’t affected the old_list
because we use copy function to copy the list.
Now let’s see an example where shallow copy operation will fail because it doesn’t copy elements in the original object recursively.
1 2 3 4 5 6 7 8 |
import copy old_list = [[1, 2], [3, 4]] new_list = copy.copy(old_list) new_list[0].append(10) print("new_list items : ", new_list) print("old_list items : ", old_list) |
Output of above python copy example is:
1 2 3 4 |
new_list items : [[1, 2, 10], [3, 4]] old_list items : [[1, 2, 10], [3, 4]] |
The output clearly suggests that we need a separate operation for deep copy of objects.
Python Deep Copy
We should always use deepcopy(x)
function with objects like list of lists, so that objects are copied recursively. Let’s change the above shallow copy example and use deep copy function and check the output. I have also added some more append and remove operations to the program.
1 2 3 4 5 6 7 8 9 10 11 |
import copy list_of_list = [[1, 2], [3, 4], ["A", "B"]] # python deep copy new_list_of_list = copy.deepcopy(list_of_list) new_list_of_list[0].append(10) new_list_of_list[1].remove(3) list_of_list[2].append("C") print("list_of_list items : ", list_of_list) print("new_list_of_list items : ", new_list_of_list) |
Below image shows the output of python deep copy operation.
Note that this method is slower than shallow copy for obvious reasons, so use it only when it’s really required. Also deep copy will take more memory if the objects inside are also copied, so use it wisely and only if truly required.
That’s all about python copy and python deep copy operations.
Reference: Official Documentation