Python dictionary copy (shallow copy and deep copy) - Difference of b=a.copy() and b=a

Python dictionary has copy() method that returns the same dictionary.

a = {'book': 97, 'pen': 145, }

b = a.copy()

print(b)  # {'book': 97, 'pen': 145}

Are those the same or different objects? Python id, which returns the object "memory address", helps us to check it.

a = {'book': 97, 'pen': 145, }

b = a.copy()

print(id(a))  # 4439141504
print(id(b))  # 4439141568

The ids are different so both objects have the different addresses. In other words, both are "essentially" different.

Reference

If not using copy() method and create a new reference to the old object, both values and ids are the same.

a = {'book': 97, 'pen': 145, }
b = a

print(id(a))  # 4561136768
print(id(b))  # 4561136768

In this case, if you add the key and value to a, b will be automatically updated because b is simply a reference to a.

a = {'book': 97, 'pen': 145, }
b = a
a['note'] = 314

print(a)  # {'book': 97, 'pen': 145, 'note': 314}
print(b)  # {'book': 97, 'pen': 145, 'note': 314}

It may look strange for Python beginners. If you create b by copy method, the change of a doesn't reflect b.

a = {'book': 97, 'pen': 145, }
b = a.copy()
a['note'] = 314

print(a)  # {'book': 97, 'pen': 145, 'note': 314}
print(b)  # {'book': 97, 'pen': 145}

Shallow copying vs deep copying in Python

copy() means shallow copying. The above examples show copy() copys a new object that isn't a reference to the original one but it's not a perfect copying in some contexts. Here is another example that the original dictionary has a list.

d1 = {'A': [1, 2], 'B': 'Book', }

d2 = d1

d1['A'].append(3)
d1['B'] = 'Pen'

print(d1)  # {'A': [1, 2, 3], 'B': 'Pen'}
print(d2)  # {'A': [1, 2, 3], 'B': 'Pen'}

Both dictionaries are the same. Then check both values in case of copying.

d1 = {'A': [1, 2], 'B': 'Book', }

d2 = d1.copy()

d1['A'].append(3)
d1['B'] = 'Pen'

print(d1)  # {'A': [1, 2, 3], 'B': 'Pen'}
print(d2)  # {'A': [1, 2, 3], 'B': 'Book'}

d2 should be completely different from d1 but both dictionaries append 3 to A list. The value of B remains Book but the iterable value of A changes due to updating d1.

Because copy() is not a perfect copying, this method is often called "shallow copying". So what should we use to copy an object perfectly? The best way is to use deepcopy() in copy module.

import copy

d1 = {'A': [1, 2], 'B': 'Book', }

d2 = copy.deepcopy(d1)

d1['A'].append(3)
d1['B'] = 'Pen'

print(d1)  # {'A': [1, 2, 3], 'B': 'Pen'}
print(d2)  # {'A': [1, 2], 'B': 'Book'}

Though we append d1 list, d2 list doesn't change. There are not any changes in d2 because both dictionaries are perfectly different.

Python Dictionary

Python Tutorial