Deep Copy and Shallow Copy in Python
Tags: python, deepcopy, shallowcopy, programming
Published: 2022-12-09 11:08:36


### Shallow Copy and Deep Copy
In this article, we will learn about shallow copy and deep copy in Python.


In Python, we use the assignment (`=`) operator to create a copy of an object. However, it doesn't make a new object. Instead, it just shares the reference of the original object to a new variable.
In the following example, the `old_list` hold value `[1, 2, 3]`  and assign to new variable named `new_list` by using assignment(`=`) operator. If we modify the `new_list`, the `old_list` will also be affected. You can also see that the `old_list` and `new_list` id are the same, i.e., `4350750272`.

```python
>>> old_list = [1, 2, 3]
>>> new_list = old_list
>>> new_list[2] = 0
>>> print(old_list)
[1, 2, 0]
>>> print(new_list)
[1, 2, 0]
>>> print(f"id of new_list {id(new_list)}, id of old_list {id(old_list)}")
id of new_list 4350750272, id of old_list 4350750272
```

## Why do we need a deep copy or a shallow copy?
Sometimes we need to keep original values unchanged and only modified in the new ones or vice versa. In Python, we have two ways to do this.
1. Shallow copy
2. Deep copy

## Python copy Module
Python has a `copy` module for the deep and shallow copy.

**copy.copy(x)**
Return a shallow copy of x.

**copy.deepcopy(x)**
Return a deep copy of x.

**exception copy.Error**
Raised for module-specific errors.

## Shallow Copy
A shallow copy creates new objects that store the original objects' reference. 
A shallow copy doesn't create a copy of nested objects where, as it only copies the reference of the nested objects. [1]

**Create a copy using shallow copy**
```python
>>> import copy
>>> old_list = [[1, 2], [3, 4]]
>>> new_list = copy.copy(old_list)
>>> print(old_list)
[[1, 2], [3, 4]]
>>> print(new_list)
[[1, 2], [3, 4]]
```

In the above example, we create a nested list and shallow copy the value to another variable named `new_list` using the `copy` method, it will create independent objects with the same content.
Now we add some data in `old_list`.

```python
>>> old_list.append([5,6])
>>> print(old_list)
[[1, 2], [3, 4], [5, 6]]
>>> print(new_list)
[[1, 2], [3, 4]]
```
Here, we append new list `[5, 6]` to `old_list`. The `new_list` contains references of original nested objects stored in  `old_list`. The new sublist `[5, 6]` was not copied in `new_list`. But, if you change any nested objects in the `old_list`, the changes also reflect in the `new_list` because both lists share the reference of the same nested objects.
```python
>>> old_list[1][1] = 'X'
>>> print(old_list)
[[1, 2], [3, 'X'], [5, 6]]
>>> print(new_list)
[[1, 2], [3, 'X']]
```

## Deep Copy
 A deep copy creates a new object and recursively adds the copies of nested objects present in the original elements. [1]
 
**Create a copy using deep copy**  

```python  
>>> import copy  
>>> old_list = [[1, 2], [3, 4]]  
>>> new_list = copy.deepcopy(old_list)  
>>> print(old_list)  
[[1, 2], [3, 4]]  
>>> print(new_list)  
[[1, 2], [3, 4]]  
```
If any changes to nested objects of the `old_list`, the changes are not reflected in `new_list`.
```python
>>> import copy
>>> old_list = [[1, 2], [3, 4]]
>>> new_list = copy.deepcopy(old_list)  
>>> old_list[1][1] = 'X'
>>> print(old_list)
[[1, 2], [3, 'X']]
>>> print(new_list)
[[1, 2], [3, 4]]
```

## What is the Difference Between Deep and Shallow Copies? [2]
The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):

-   A  _shallow copy_  constructs a new compound object and then (to the extent possible) inserts  _references_  into it to the objects found in the original.
    
-   A  _deep copy_  constructs a new compound object and then, recursively, inserts  _copies_  into it of the objects found in the original.


**References:**

[1] https://www.programiz.com/python-programming/shallow-deep-copy

[2] https://docs.python.org/3/library/copy.html

Originally published in https://shafik.io/2022/12/deep-copy-and-shallow-copy-in-python