There are two types of copy operations in Python: shallow copy and deep copy. Shallow copy create a reference to an object while deep copy copies the memory and hence two things are completely different.

Shallow copy are the most frequently used copy operation. It enables data sharing for immutable objects. There are some rules for shallow copy to remember.

  • for immutable objects, such as int, float, shallow copy will create a new memory section.
  • for mutable objects, such as list, shallow copy will not affect the immutable elements in the list, but the nested elements will be affected.
a = [1,2,3, 'a']
b = a.copy()
b[0] = 1	# not affect a, a = [1,2,3,'a'], b = [0,2,3,'a']

However,

a = [1, [2,3], 'a']
b = a.copy()
c = copy.deepcopy(a)
b[1][0] = 0	# affect a, a = [1, [0,3], 'a'], b = [1, [0,3], 'a'], c is not affected

In the above example, if the list element is a class object, it is treated as a nested object.

Note that the assign operator = performs shallow copy if the right object is int, float, etc. When the right object is mutable, = is equivalent to reference.

a = 1
b = a	
b = 2	# not affect a, a = 1

However,

a = [1,2,3]
b = a
b[0] = 0	# affect a, a = [0,2,3]

For numpy array, if the array is not object array, the shallow copy operation np.copy() is sufficient.

a = np.array([1,2,3])
b = np.copy(a)
b[0] = 0	# not affect a, a = [1,2,3]

However,

a = np.array([1, [2,3], 'a'], dtype=object)
b = a.copy()
c = copy.deepcopy(a)
b[1][0] = 0	# affect a, a = [1, [0,3], 'a'], not affect c