Shallow copy vs Deepcopy of Dictionary- Python

Dictionary in Python provides methods to copy() for shallow copy of dictionary and copy.deepcopy() for deep copy of original dictionary. There are various properties and scenarios to create a copy of original dictionary.

Dictionary copy

Dictionary in Python, is a mutable, dynamic size collection datatype. Python Dictionary stores elements in key-value pairs, where elements are indexed by keys and each unique key maps to a specific value. Dictionary keys can only be of immutable datatype but values can be of any datatype. From Python version 3.7 and later, dictionaries maintain insertion order.

Assignment vs. Shallow copy vs. Deep copy

Lets explore the difference between assignment (reference), shallow copy and deep copy of dictionary.

dictionary_2 = dictionary_1

Assignment of Dictionary
Assignment of Dictionary

dictionary_2 = dictionary_1.copy()

Shallow Copy of Dictionary
Shallow Copy of Dictionary

dictionary_2 = copy.deepcopy(dictionary_1)

Deep Copy of Dictionary
Deep Copy of Dictionary
  • Assignment of dictionary – In Nested Dictionary article, we explored how one dictionary reference can be passed to another dictionary. dictionary_2 = dictionary_1, in this case elements of dictionary are stored once in memory but same elements are referenced by two different variables. If we will make any manipulation on dictionary elements using dictionary_1 reference, then it will be reflected with dictionary_2 reference as well.
  • Shallow Copy of dictionary – In case of shallow copy, all elements of original dictionary are copied and stored at another memory location but nested dictionary elements are still referenced from the same memory location. In shallow copy, nested dictionary elements are not copied. dictionary_1 referenced to original dictionary elements and dictionary_2 referenced to copied dictionary.
  • Deep Copy of dictionary – In case of deep copy, all elements of original dictionary are copied and stored at another memory location and nested dictionary elements are also copied to another memory location. In deep copy, nested dictionary elements are also copied. dictionary_1 referenced to original dictionary elements and dictionary_2 referenced to copied dictionary and their respective nested dictionaries.

Now, lets explore the programs for shallow copy and deep copy.

Shallow copy using copy() method

Syntax for shallow copy uses built-in copy() method

dictionary_2 = dictionary_1.copy()

  • Shallow Copy of dictionary will copy all elements of original dictionary to another memory location
  • But, nested dictionary elements are still referenced from the same memory location. Nested dictionary elements are not copied.
# copy of dictionary using copy() method
print("copy of dictionary using copy() method")
dictionary_1 = {'student_1': {'name': 'Johnson'}}

dictionary_2 = dictionary_1.copy()    # shallow copy with copy() method
print(dictionary_2)

dictionary_1["student_2"] = {"name": "Smith"}     # dictionary_1 direct update, will not affect dictionary_2

dictionary_1["student_1"]["name"] = "Harrison"  # nested dictionary update, will affect dictionary_2

print(dictionary_1)
print(dictionary_2)

In this program, we have defined an original dictionary referenced by a variable dictionary_1. We are using dictionary_2 = dictionary_1.copy() to create a copy of original dictionary and assign the copied dictionary reference to dictionary_2. We will explore two scenarios:

  • Update direct element from dictionary_1 – Using dictionary_1["student_2"] = {"name": "Smith"}, we are directly updating the original dictionary and adding a new key-value pair to it. Being a direct update using dictionary_1 reference, this update should not be reflected in the dictionary_2 reference.
  • Update nested element from dictionary_1 – Using dictionary_1["student_1"]["name"] = "Harrison", we are updating the nested dictionary and changing the name for key student_1. With shallow copy, nested dictionaries does not get copied and dictionary_1 and dictionary_2 will be referring to the same nested object. This change should be reflected in the dictionary_2 reference.

Program Output

copy of dictionary using copy() method
{'student_1': {'name': 'Johnson'}}       # original dictionary elements
{'student_1': {'name': 'Harrison'}, 'student_2': {'name': 'Smith'}}  # dictionary_1 with new element added
{'student_1': {'name': 'Harrison'}}      # dictionary_2 with nested object change

From the output, New element is added only in the dictionary referenced by dictionary_1 and nested object change is reflected by both dictionary_1 and dictionary_2.

Shallow copy using dict constructor

We can also achieve shallow copy of a dictionary using dict constructor.

dictionary_2 = dict(dictionary_1)

Shallow copy with dict constructor is similar to shallow copy with copy() method. All elements of original dictionary will be copied to another memory location except the nested dictionary elements.

print("copy of dictionary using dict() constructor")
dictionary_1 = {'student_1': {'name': 'Johnson'}}
dictionary_2 = dict(dictionary_1)     # shallow copy with dict constructor
print(dictionary_2)
dictionary_1["student_2"] = {"name": "Smith"}   # dictionary_1 direct update, will not affect dictionary_2
dictionary_1["student_1"]["name"] = "Harrison"  # nested dictionary update, will affect dictionary_2
print(dictionary_1)
print(dictionary_2)

In this program, we have defined an original dictionary referenced by a variable dictionary_1. We are using dictionary_2 = dict(dictionary_1) to create a copy of original dictionary and assign the copied dictionary reference to dictionary_2.

Program Output

copy of dictionary using dict() constructor
{'student_1': {'name': 'Johnson'}}       # original dictionary elements
{'student_1': {'name': 'Harrison'}, 'student_2': {'name': 'Smith'}}  # dictionary_1 with new element added
{'student_1': {'name': 'Harrison'}}      # dictionary_2 with nested object change

From the output, New element is added only in dictionary_1 and nested object change is reflected by both dictionary_1 and dictionary_2.

Deep copy using copy.deepcopy() method

deepcopy() method is provided by the copy module. We need to import copy module, before using deepcopy() method. Syntax for deep copy:

dictionary_2 = copy.deepcopy(dictionary_1)

  • This method takes original dictionary as an argument and returns reference to copied dictionary.
  • Deep copy of dictionary will copy all elements (including nested objects) of original dictionary to another memory location and can be referenced by another variable.
  • Nested dictionary elements are also copied to another memory location.
# deep copy of dictionary using copy.deepcopy() method
print("deep copy of dictionary using copy.deepcopy() method")

import copy
dictionary_1 = {'student_1': {'name': 'Johnson'}}
dictionary_2 = copy.deepcopy(dictionary_1)    # deep copy with copy.deepcopy() method
print(dictionary_2)
dictionary_1["student_2"] = {"name": "Smith"}   # dictionary_1 direct update, will not affect dictionary_2
dictionary_1["student_1"]["name"] = "Harrison"  # nested dictionary update, will not affect dictionary_2
print(dictionary_1)
print(dictionary_2)

First, we have to import the copy module. Original dictionary is referenced by a variable dictionary_1. We are using dictionary_2 = copy.deepcopy(dictionary_1) to create a deep copy of original dictionary and assign the copied dictionary reference to dictionary_2. We will explore two scenarios:

  • Update direct element from dictionary_1 should not be reflected in the dictionary_2 reference.
  • Update nested element from dictionary_1 – Using dictionary_1["student_1"]["name"] = "Harrison", we are updating the nested dictionary and changing the name for key student_1. With deep copy, nested dictionaries also get copied and dictionary_1 and dictionary_2 will be referring to the different nested object. This change will not be reflected in the dictionary_2 reference.

Program Output

deep copy of dictionary using copy.deepcopy() method
{'student_1': {'name': 'Johnson'}}   # original dictionary elements
{'student_1': {'name': 'Harrison'}, 'student_2': {'name': 'Smith'}}   # dictionary_1 with new element added
{'student_1': {'name': 'Johnson'}}   # dictionary_2 with no change in nested object

From the output, New element is added only in dictionary_1 and nested object change is only reflected with dictionary_1. There is no change in dictionary_2 elements.

Summary

In this article we learned about assignment (reference), shallow copy and deep copy of dictionary. We learned about:

Code – Github Repository

All code snippets and programs for this article and for Python tutorial, can be accessed from Github repository – Comments and Docstring in Python.

Python Topics


Interview Questions & Answers

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *