Published: 6 April 2021, 18:00
What if we want to modify a collection inside a function but don’t want these modifications to affect the caller code? Then we should explicitly copy the value.
For this purpose, all mutable built-in collections provide method .copy
:
def f(v2):
v2 = v2.copy()
v2.append(2)
print(f'{v2=}')
# v2=[1, 2]
v1 = [1]
f(v1)
print(f'{v1=}')
# v1=[1]
Custom objects (and built-in collections too) can be copied using copy.copy:
import copy
class C:
pass
def f(v2: C):
v2 = copy.copy(v2)
v2.p = 2
print(f'{v2.p=}')
# v2.p=2
v1 = C()
v1.p = 1
f(v1)
print(f'{v1.p=}')
# v1.p=1
However, copy.copy
copies only the object itself but not underlying objects:
v1 = [[1]]
v2 = copy.copy(v1)
v2.append(2)
v2[0].append(3)
print(f'{v1=}, {v2=}')
# v1=[[1, 3]], v2=[[1, 3], 2]
So, if you need to copy all subobjects recursively, use, copy.deepcopy
:
v1 = [[1]]
v2 = copy.deepcopy(v1)
v2[0].append(2)
print(f'{v1=}, {v2=}')
# v1=[[1]], v2=[[1, 2]]