Advanced Python 9 | Mutable vs. Immutable, Assign, Shallow Copy, and Deep Copy

Series: Advanced Python

Advanced Python 9 | Mutable vs. Immutable, Assign, Shallow Copy, and Deep Copy

Origin From https://dribbble.com/shots/12228737-GitHub-Sign-in
  1. Mutable and Immutable Objects

(1) The Definition of the Mutable Objects

An immutable object means that if we change the value of this object, then the address of this object will not be changed.

(2) The Definition of the Immutable Objects

An immutable object means that if we change the value of this object, then the address of this object will be changed.

(3) Mutable and Immutable Datatypes in Python

Mutable: list, dictionary, set
Immutable: integer, float, boolean, tuple, string

(4) Testing Mutable and Immutable

Based on the definition of the mutable and immutable, we can create a function for us to show if an object is mutable or not by changing its value and then check it’s address.

def is_mutable(var):
"""
This function has one argument as its input, this
input varible is the variable for checking whether or
not it is a mutable datatype or an immutable datatype.
The returned value of this function will be a boolean,
and True means the datatype of the input variable is
mutable while False means the datatype of the input
variable is immutable.
Supported datatype:
- integer
- string
- boolean
- float
- tuple
- set
- list
- dictionary
"""
# get the address of the variable
ID = id(var)
# change the value of the variable
# if the variable is a set
try:
var.add('testing')
typ = 0
except AttributeError:
# if the variable is a list
try:
var.append('testing')
typ = 0
except AttributeError:
# if the variable is a dictionary
try:
var['testing'] = 'testing'
typ = 0
# if the variable is not a set, a list,
# or a dictionary, then print use type()
# to find out the data type
except TypeError:
typ = type(var)
# if the variables is an int
if typ == int:
var += 1
# if the variables is a string
elif typ == str:
var += 'testing'
# if the variables is a boolean
elif typ == bool:
var = not var
# if the variables is a float
elif typ == float:
var += 1.0
# if the variables is a tuple
elif typ == tuple and var != ('testing', 'testing'):
var = ('testing', 'testing')
elif typ == tuple and var == ('testing', 'testing'):
var = (0, 'testing')
# we just support the basic data types in python,
# any other datatypes will raise an error
elif typ != 0:
assert 0==1, str(typ)+': Datatype not support.'
# compare the new address with the original one
# if the address changes, then it's immutable
# if the address remains the same, then it's mutable
return ID == id(var)
view raw is_mutable.py hosted with ❤ by GitHub

2. Assign, Shallow Copy, and Deep Copy

(1) Acknowledge

People find it hard to understand the difference between the assignment statement and the copy (including copy, shallow copy, and deep copy) statement. Thanks to the lolviz package from Terence Parr, we can now state this confusing problem in a visualized and clear way.

Install lolviz,

$ brew install graphviz
$ pip install lolviz

Import packages,

from lolviz import *
from copy import *

(2) Assign, Shallow Copy, Deepcopy

Assign in the python means to point two variables to the same mutable object. For immutable objects, they will give the value to a new immutable object.

Shallow Copy in the python is exactly the copy() function (or method) which means to point two variables to two different mutable objects, but if there’s any mutable objects inside that these two different objects, they will not be copied and they are still pointed by these two different objects.

Deepcopy means to copy everything, including objects in the objects.

  • For a immutable object, assign, shallow copy, and deepcopy mean exactly the same thing,
X = 1
Y = X
callviz(varnames=['X','Y'])
X = 1
Y = copy(X)
callviz(varnames=['X','Y'])
X = 1
Y = deepcopy(X)
callviz(varnames=['X','Y'])
  • For a immutable object, assign means to point the variable to exactly the same object, whereas shallow copy means only copy the overall mutable object, but not the other mutable objects inside this object. Deepcopy means to copy both the overall mutable object and the mutable objects inside the data type. Here are some examples,
X = [1,2]
Y = X
callviz(varnames=['X','Y'])
X = [1,2]
Y = copy(X)
callviz(varnames=['X','Y'])
X = [1,2]
Y = X.copy()
callviz(varnames=['X','Y'])
X = [1,2]
Y = deepcopy(X)
callviz(varnames=['X','Y'])
X = [[1,2],[3,4]]
Y = X
callviz(varnames=['X','Y'])
X[0] = ['p', 'q']
callviz(varnames=['X','Y'])
X = [[1,2],[3,4]]
Y = X.copy()
callviz(varnames=['X','Y'])
X[0] = ['p', 'q']
callviz(varnames=['X','Y'])
X = [[1,2],[3,4]]
Y = deepcopy(X)
callviz(varnames=['X','Y'])
X[0] = ['p', 'q']
callviz(varnames=['X','Y'])

(3) Practice

View the following two code blocks and find the difference in their data structure.

X = [[1,[1,2]],'a','b']
Y = copy(X)
Y[2] = ['p']
X = copy(Y)
callviz(varnames=['X','Y'])

and

X = [[1,[1,2]],'a','b']
Y = X
Y[2] = ['p']
X = Y
callviz(varnames=['X','Y'])
Data Structures (Left for CodeBlock #1, Right for CodeBlock #2)