Using copy

https://docs.python.org/3/library/copy.html

INTRODUCTION

This module provides generic shallow and deep copy operations.
A 'shallow copy' constructs a new compound object and then inserts 'references' into it to the objects found in the original.
A 'deep copy' constructs a new compound object and then, recursively, inserts 'copies' into it of the objects found in the original.

Two problems with deep copy operations:
(a) recursive objects may cause a recursive loop,
(b) it may copy too much, such as data which is intended to be shared between copies.

The deepcopy() function avoids these problems by:
(a) keeping a 'memo' dictionary of objects already copied during the current copying pass,
(b) letting user-defined classes override the copying operation or the set of components copied.


import copy

# There are two methods available.
x = "any object"
y = copy.copy(x)       # a shallow copy of x
z = copy.deepcopy(x)   # a deep copy of x

M = [1, 2, 3]
L = [10, "a", M]
L2 = copy.copy(L)   # or L2 = L.copy(), or L2 = L[:]
assert id(L) != id(L2)
assert id(L[1]) == id(L2[1])
assert id(L[2]) == id(L2[2])
L3 = copy.deepcopy(L)
assert id(L) != id(L3)
assert id(L[1]) == id(L3[1])   # strings are immutable
assert id(L[2]) != id(L3[2])
M[1] = 22
print(L)   # [10, 'a', [1, 22, 3]]
print(L2)   # [10, 'a', [1, 22, 3]]
print(L3)   # [10, 'a', [1, 2, 3]]   # no changes

# http://stackoverflow.com/questions/1500718/
# what-is-the-right-way-to-override-the-copy-deepcopy-operations-on-an-object-in-p

class MyClass(object):
    def __init__(self): ...
    def __copy__(self): ...
    def __deepcopy__(self, memo): ...