A shallow copy creates a new object but doesn't create a copy of nested objects, instead it just copies the reference of nested objects.
A deep copy creates a new object and recursively adds the copies of nested objects present in the original elements. It means that any changes made to a copy of object do not reflect in the original object.
copy.copy() function is used for shallow copy and copy.deepcopy() function is used for deep copy.
>>> import copy
>>> org_list = [{'id': 1}, {'id':2}, {'id':3}]
>>> shallow_list = copy.copy(org_list)
let's modify shallow list nested object:
>>> shallow_list[1]['name'] = 'two'
>>> shallow_list
[{'id': 1}, {'id': 2, 'name': 'two'}, {'id': 3}]
>>> org_list
[{'id': 1}, {'id': 2, 'name': 'two'}, {'id': 3}]
You can see the change is reflected on original list also. Let's add new item:
>>> shallow_list.append({'id' : 4})
>>> shallow_list
[{'id': 1}, {'id': 2, 'name': 'two'}, {'id': 3}, {'id': 4}]
>>> org_list
[{'id': 1}, {'id': 2, 'name': 'two'}, {'id': 3}]
You can see it is NOT reflected in original list. So any change in referenced nested elements only will be reflected on both lists.
Let's reset original list and look into deep copy case
>>> org_list = [{'id': 1}, {'id':2}, {'id':3}]
>>> deep_list = copy.deepcopy(org_list)
>>> deep_list[1]['name'] = 'two'
>>> deep_list.append({'id' : 4})
>>> deep_list
[{'id': 1}, {'id': 2, 'name': 'two'}, {'id': 3}, {'id': 4}]
>>> org_list
[{'id': 1}, {'id': 2}, {'id': 3}]
You can see original list is independent from deep copied list.
Enjoy Python!!