Detailed explanation of Python direct assignment, deep copy, and shallow copy

Copyright statement: This article is the original article of the blogger and follows the CC 4.0 BY-SA copyright agreement. Please attach the original source link and this statement for reprinting.
Link to this article: https://blog.csdn.net/zsq8187/article/details/109907066


I am learning Python. I spent a day writing a copy of the notes based on my own review and understanding test. After thinking about it, let’s put this note out separately)

Shallow copy and deep copy

The assignment of objects in Python is done directly by reference. To copy, you need to use the copy module in the standard library.

  • Direct assignment: pass the memory address directly
  • Shallow copy copy.copy(): create a new object , copy the memory addresses of all elements inside
  • Deep copy copy.deepcopy(): create a new object , copy the memory address immutably, recursively create a new object and copy the content if it contains variable (see the type of tuple below)
    • In the copy here, you can temporarily regard tuples with variable elements as mutable.
  • Immutable types : Number (number), String (string), Tuple (tuple) [all container types except tuples]
  • Variable types : List (list), Dictionary (dictionary), Set (collection) [Fighter container type]
  • Non-container types : Number (number), String (string) [both immutable types]
  • Container type : List (list), Dictionary (dictionary), Tuple (tuple) [variable types except tuples]
  • To facilitate understanding, you can take a look at the following schematic diagram reproduced from others.

"Copy" of immutable types

Immutable types are non-container types except for tuples . They are not copied. Copying with the copy module is direct assignment and transfer of memory addresses.

  • To understand some design reasons for copying, we must first solve the reason for direct assignment to achieve "copy"
  • becauseThe need for copying is to hope that the two variables will not interfere with each other, and a new one. The immutable type of "modified" to have achieved the independence of both (its "modification" is to re-create a variable, the new variable to point to the new object, old variable still points to the old objects). Therefore, there is no need to open up a new space for copying the same content, just point directly to the same address.

Direct assignment

  • Verification in the figure:
a = "a"
b = a # 直接赋值,进行“拷贝”
print(b is a)
b = "b" # “修改”又是直接赋值了,因为它们无法修改
print(a)
print(b)
print(b is a)

True
a
b
False

  • Tuples of immutable types are also assigned directly . But tuples with variable elements are special , see the next section.

—> So in the following copy of the variable type/container type, the sub-elements of the immutable type can be directly assigned and passed the memory address.

It should be noted that the direct assignment here is to directly point the old and new variable labels to the same object . "Modify" refers to "modify" one variable label without moving to another variable label. So that the two are independent and do not affect.


Direct assignment of mutable types

The above is the direct assignment of immutable types, here is a look at the direct assignment of mutable types. This is the variable label pointing to the same object. Always operate the same object , and will not meet the copy requirements:
Direct assignment of mutable types

(I don't want to edit the picture, just understand the meaning. The container types are variable except for tuples. The "copy" of tuples will be discussed separately)


Variable type deep copy and shallow copy

Its deep and shallow copies are [ create a new object ], but the direct child elements point to different points. Here is the new and old variable labels pointing to two different objects ! (The tuple is special, pay attention later)

  • Therefore, the future modification of these two variables will not interfere with each other! This can also be simply analogized from the "Direct Assignment of Immutable Type" diagram above: the variable AB is replaced with the object AB (they correspond to each other); these two objects are containers and point to many "strings".
import copy
aList = ["你", "好", 1, [1, 2, 3]]
bList = copy.copy(aList) # 浅拷贝:拷贝了所有元素的内存地址到一个新list对象里
cList = copy.deepcopy(aList) # 深拷贝:在浅拷贝的基础上,还递归为容器元素创建新对象拷贝内容

In direct assignment, we use the old and new variable labels as the benchmark to see the modification of the variable content. Here, we continue to look at the variable label, which points to the old and new container objects. When the elements of the container object are of immutable type, following the above-mentioned logic, the newly created object gives the elements of the container object new addresses so as not to affect each other.

  1. Shallow copy, because the immutable type "你", "好", 1modify new objects are given new address, so that interference between the two, but modified sub-list [1, 2, 3]will not create a new object, so this has been both reference the same, mutually influential .
    Insert picture description here
  • Shallow copy in the dictionary: Create two dictionary objects, create a new object * for the key , but copy the memory address of the value , and their values ​​are shared (you need to understand the memory diagram of the dictionary). If the values ​​have variable types, they still affect each other.
    • A new object is created for the key: for example, the dictionary A, B: B is a shallow copy of A, if a key of B is deleted at this time, the corresponding key in A has no effect. The initial independence of the two dictionaries is realized, and the need for this kind of shallow copy is realized.
    • See point 4 for the detailed diagram. It is recommended to read points 1 and 2 first.
  1. In deep copy, recursion is performed to create a new object copy content for the container element. So that the two variables will never interfere with each other.
    Insert picture description here
  • Deep copy in the dictionary: new objects are created for keys and values ​​(immutable types are still just copying memory addresses), and the two do not interfere with each other.
  1. Special case: tuple
  • Tuples are immutable types and should be uncopyable. They pass memory addresses .
  • The special thing is that tuples with variable type elements can be deep copied , create a new object, and recursively create new objects for the variable elements (it still does not have a shallow copy, copy.copy()but also transfers the memory address )
  1. After understanding the deep and shallow copies of the above list, it is not difficult to understand the deep and shallow copies of the dictionary by analogy.

Shallow copy of dictionaryDeep copy of dictionary

  1. About the above test: Omitted. Don't forget the knowledge points. .

Reprinted information

  1. Direct assignment: pass memory address
    Direct assignment

  2. Shallow copy: create a new object, copy all memory addresses
    Shallow copy

  3. Deep copy: Create new objects, copy memory addresses of immutable types, and recursively create new objects with variable types .
    Deep copy!

  4. The difference between deep copy and shallow copy of immutable tuples and mutable lists

The difference between deep copy and shallow copy of immutable tuples and mutable lists
Here, the first part, the whole tuple is immutable direct assignment, so it is True;
the second part, a variable copy type, a shallow vs. deep copy their content is the same as ==is True; and they are Copy new objects, so the memory address ==is False.

Where the copy is used

Python generally uses shallow copy by default. The following examples are waiting to be added.
such as:

  • Slices [:]using a shallow copy
  • Keyword parameter: **extraShallow copy is used, the delete key inside the function has no effect on the original value outside, but the variable type value is shared

Reference/Picture Reprint: Graphical Python Deep Copy and Shallow Copy-Tian Xiao Project-博客园

Guess you like

Origin blog.csdn.net/zsq8187/article/details/109907066