In Python, there is a difference between the assignment of an object and the copy (deep/shallow copy), which can produce unexpected results if used without notice.
assigning values to Objects
Look directly at the code:
would = ["would", +, ["Python", "C #", "JavaScript"]]wilber = Willprint ID (would) print Willprint [ID (ele) for ele in Will]pri NT ID (Wilber) print Wilberprint [ID (ele) for ele in wilber]will[0] = "Wilber" Will[2].append ("CSS") Print ID (would) print would Print [ID (ele) for ele in Will]print ID (Wilber) print Wilberprint [ID (ele) for ele in Wilber]
The output of the code is:
Here's an analysis of this code:
- First, a variable named Will is created, which points to a list object, and the address of all objects can be seen from the first image (the results may vary from one run to another)
-
- Then, by assigning the Wilber variable to the will variable, the Wilber variable points to the object (memory address) of the would variable, which means "Wilber is will", "Wilber[i" is Will[i] "
As can be understood, in Python, the assignment of an object is an object reference (memory address) passed
- In the third picture, because Will and Wilber point to the same object, any changes to would are reflected on the Wilber
One thing to note here is that STR is an immutable type, so the old object is replaced when modified, resulting in a new address 39758496
Shallow Copy
Here's a look at the results of a shallow copy:
ImportCopywill= [" would", 28, ["Python","C #","JavaScript"]]wilber=copy.copy (would)PrintID (would)Print wouldPrint[ID (ele) forEleinchwould ]PrintID (Wilber)PrintWilberPrint[ID (ele) forEleinchWilber]will[0]="Wilber"will[2].append ("CSS")PrintID (would)Print wouldPrint[ID (ele) forEleinchwould ]PrintID (Wilber)PrintWilberPrint[ID (ele) forEleinchWilber]
The code results are:
Analyze This code:
- First, a will variable is still used, pointing to an object of type list
- Then, by copy () of the shallow copy function inside the copy module, a shallow copy of the object that would points to, then a shallow copy of the generated new object is assigned to the Wilber variable
A shallow copy creates a new object, in this example, "Wilber is isn't will"
However, for an element in an object, a shallow copy will only use the original element's reference (memory address), which means "wilber[i" is Will[i] "
- When you make changes to Will
Because the first element of the list is an immutable type, the first element of will corresponding list uses a new object 39758496
But the third element of the list is not a type, and the modification does not produce new objects, so will's modifications are reflected accordingly to the Wilber.
To summarize, the effect of a shallow copy is generated when we use the following actions:
- Using the slice [:] Action
- Using factory functions (such as List/dir/set)
- Using the copy () function in the Copy module
Deep Copy
Finally, take a look at the deep copy:
ImportCopywill= [" would", 28, ["Python","C #","JavaScript"]]wilber=copy.deepcopy (would)PrintID (would)Print wouldPrint[ID (ele) forEleinchwould ]PrintID (Wilber)PrintWilberPrint[ID (ele) forEleinchWilber]will[0]="Wilber"will[2].append ("CSS")PrintID (would)Print wouldPrint[ID (ele) forEleinchwould ]PrintID (Wilber)PrintWilberPrint[ID (ele) forEleinchWilber]
The result of the code is:
Analyze This code:
- First, you also use a would variable to point to an object of list type
- Then, a deep copy of the object that would points to is made through the deep copy function Deepcopy () inside the copy module, and then a deep copy of the generated new object is assigned to the Wilber variable
Similar to a shallow copy, a deep copy creates a new object, in this example, "Wilber isn't will"
However, for elements in an object, a deep copy is regenerated (with special conditions, as described below) instead of simply using the original element's reference (memory address)
In the example, the third element of would is pointing to 39737304, and the third element of Wilber is a completely new object 39773088, that is, "wilber[2" was not will[2] "
- When you make changes to Will
Because the first element of the list is an immutable type, the first element of will corresponding list uses a new object 39758496
But the third element of the list is a type, and the modification does not produce a new object, but because "wilber[2" is not will[2] ", the change will does not affect the Wilber
Special circumstances of the copy
In fact, there are some special cases for copying:
- For non-container types (such as numbers, strings, and other ' atomic ' types of objects) there is no copy.
In other words, for these types, "obj is copy.copy (obj)", "obj is copy.deepcopy (obj)"
- If the meta-ancestor variable contains only atomic type objects, it cannot be deep copied, see the following example
Summary
This article describes the assignment and copying of objects, and the differences between them:
- The assignment of objects in Python is the transfer of object references (memory addresses);
- With Copy.copy (), you can make a shallow copy of the object, which duplicates the object, but still uses the original reference for the element in the object.
- If you need to copy a container object and all of its elements (containing the element's child elements), you can use Copy.deepcopy () to make a deep copy
- For non-container types (such as numbers, strings, and other ' atomic ' types of objects) are not copied one says
- If the meta-ancestor variable contains only atomic type objects, it cannot be deeply copied.
Python depth copy