This is the 25th day of my participation in the August Genwen Challenge.More challenges in August

Python assignment

Assignment just copies the reference to the new object, but does not create a new memory space. It does not create a separate object. It just labels the original block of data with a new label, so when one label is changed, the block of data will change, and the other label will change.

Example:

a = [9.2.3.4.5]
b = a
a.sort()
print(a,b)  # a:,3,4,5,9 [2] b:,3,4,5,9 [2]
Copy the code

This is because the assignment reference refers to an object, not to a new independent object. So how do we get a separate object that is the same as the list of a? This requires a shallow copy operation.

Python shallow copy

Shallow copy refers to the reallocation of a block of memory to create a new object, but the elements inside are references to the child objects of the original object. There are three forms:

  • Slicing operation
  • The factory function
  • Copy module copy function
a = [9.3.2.4.5]
# Slice operation
b = a[::-1]
# factory function
c = list(a)
# copy function
import copy
d = copy.copy(a)
a.sort()
print(a,b)  B, C, D :[9, 3, 2, 4, 5]
Copy the code

A shallow copy is called a shallow copy because it copies only one layer, the outermost object itself, and the inner elements are just references. There is a nested list[] in the list, and if we modify it, the situation will be different.

Shallow copy needs to be discussed in two cases:

  1. When the object copied by shallow copy is immutable (string, tuple, numeric type), the result is the same as the result of assignment.

  2. When shallow copy copies mutable objects (such as lists, dictionaries, etc.), then it depends on the case:

    In the first case, there are no complex subobjects in the copied object, and the original value change does not affect the value of the shallow copy, and the value change of the shallow copy does not affect the original value. The id value of the original value is different from the original value of the shallow copy.

    In the second case, the copied object has complex subobjects (such as a list in which a subelement is a list). If the complex subobjects are not changed, the value change of the shallow copy does not affect the original value. But changing the value of a complex child object in the original value affects the value of the shallow copy.

Python deep copy

Deep copy refers to reallocating a block of memory, creating a new object, and recursively copying elements from the original object into the new object by creating new child objects.

In the shallow copy above, it doesn’t matter if the elements in the meta-object are immutable; But if the element is mutable, shallow copies usually have some problems, such as:

list1 = [[1.2], (30.40)]
list2 = list(list1)
​
list1.append(100)
print("list1:",list1)  # list1: [[1, 2], (30, 40), 100]
print("list2:",list2)  # list2: [[1, 2], (30, 40)]
​
list1[0].append(3)
print("list1:",list1)  # list1: [[1, 2,3], (30, 40), 100]
print("list2:",list2)  # list2: [[1, 2,3], (30, 40)]
Copy the code

We can see that the value of the shallow-copy object changes when it is modified, so that a full copy of the object needs to be performed by a deep copy operation.

However, deep copy is not perfect and often brings its own set of problems. If the copied object has a reference to itself, the program can easily fall into an infinite loop, for example:

import copy
list1 = [1]
list1.append(list1)
print(list1) # (1, [...]]
​
list2 = copy.deepcopy(list1)
print(list2) # (1, [...]]
Copy the code

List X has references to itself, so x is an infinitely nested list. However, the deepcopy function deepcopy maintains a dictionary that records the copied objects and their ids. If the dictionary already stores the objects to be copied, the dictionary returns them directly.