Python Deep and shallow copy of
Before we talk about depth copy , Let's review
== The difference between .
In judging whether the objects are equal or not, we can use
- is： Compare two objects for the same reference , namely Their id Whether or not the same
- == ： Compare two objects for the same value .
id() , yes Python A built-in function , Returns the unique identification of the object , To get the memory address of the object .
First , Will be an integer 1 Allocate a memory space . Variable a and b All point to this memory space （ Memory addresses are equal ）, So their id equal .
a is b by
however , Is that true for all integers ？ The answer is ： No ！ Only in -25 ~ 256 Integers in the range do not reallocate memory space .
As shown below ：
because 257 Out of range , therefore id inequality , therefore
a is b The returned value is False.
>>> a = 257 >>> b = 257 >>> print(id(a)) 20004752 >>> print(id(b)) 20001312 >>> print(a is b) False >>> print(a == b) True
This is done with performance in mind ,Python Yes -5 To 256 The integer of maintains an array , It's equivalent to a cache , When the value is in this range , The corresponding reference address is returned directly from the array . If it's not in this range , Will open up a new memory space .
is and == Which is more efficient ？
by comparison ,
is Comparison is more efficient , Because it only needs to judge the id Whether it is the same or not .
== Overload is required __eq__ This function , Traverse the contents of all elements in a variable , Is the comparison the same . So it's inefficient
Shallow copy Deep copy
Assign values to variables , There are two ways Direct assignment , Copy
Direct assignment is just
= That's all right. . Copy is divided into shallow copy and deep copy
Let's start with the conclusion ：
- Shallow copy ： The copy is a reference to the object , If the original object changes , The corresponding copy object will also change
- Deep copy ： Copy every element in the object , The copy object is no longer related to the original object , Two are separate objects
Just look at the concept above , It may not be easy for beginners to understand . Take a look at the following example
a = [1, 2, 3] b = a print(id(a)) # 52531048 print(id(b)) # 52531048
Defining variables a, At the same time a Assign a value to b. After printing, they found their
id It's the same . The description points to the same memory address .
And then modify a Value , Check out their id
a = [1, 2, 3] b = a print(id(a)) # 46169960 a = 0 print(a, b) # [1, 0, 3] [1, 0, 3] print(id(a)) # 46169960 print(id(b)) # 46169960
At this time, I found the modified a and b And the beginning a The memory address is the same . in other words a and b Still pointing to that piece of memory , It's just in memory [1, 2, 3] Turned into [1, 0, 3]
Because the memory address changes every time it is executed again , At this time id(a) Value 46169960 And 52531048 It's the same
So we can judge ,b and a The quotation of is the same , When a When things change ,b It will change .
Assignment is ： you a No matter how , Who are you pointing to , I b Follow who you point to .
When it comes to copying, you can't avoid mutable and immutable objects .
- The variable object ： When it is necessary to change the values inside the object , Of this object id No change .
- Immutable object ： When it is necessary to change the values inside the object , Of this object id Will change .
a = [1, 2, 3] print(id(a)) # 56082504 a.append(4) # Modify the list a after id It hasn't changed , The variable object print(id(a)) # 56082504 a = 'hello' print(id(a)) # 59817760 a = a + ' world' print(id(a)) # 57880072 # Modify string a after ,id There is a change . Immutable object print(a) # hello world
Copy the immutable object , To some extent, it's the same as assignment operation . But for multi-level nested structures , Shallow copy copies only the parent object , Do not copy internal child objects .
copy Modular copy.copy Make a light copy .
import copy a = [1, 2, 3] b = copy.copy(a) print(id(a)) # 55755880 print(id(b)) # 55737992 a = 0 print(a, b) # [1, 0, 3] [1, 2, 3]
Generally speaking , I will now a Copy a copy and reallocate a memory space . Behind you a How to change , Then follow me b It doesn't matter .
For shallow copies of lists, you can also use list(), list[:] To achieve
however ！ I mentioned earlier that for multi nested structures , We need to pay attention to
See the following example
import copy a = [1, 2, [3, 4]] b = copy.copy(a) print(id(a)) # 23967528 print(id(b)) # 21738984 # change a Sub list in a[-1].append(5) print(a) # [1, 2, [3, 4, 5]] print(b) # [1, 2, [3, 4, 5]] ？？ Why not [1, 2, [3, 4]] Well ？
b By a A shallow copy of . I modified a Nested list in , Find out b It has also been revised ？
If you still don't understand , Refer to the figure below .LIST It's a nested sub object , Points to another memory space . So shallow copy just copies the elements
2 And child object references ！
Another situation , What if a tuple is nested ？
import copy a = [1, 2, (3, 4)] b = copy.copy(a) # change a Tuples in a[-1] += (5,) print(a) # [1, 2, (3, 4, 5)] print(b) # [1, 2, (3, 4)]
We found that the light copy came from b Nothing has changed . Because tuples are immutable objects . Changing the tuple will generate a new object .b The tuple reference in still points to the old tuple .
What about deep copy , Is to reallocate a memory space （ New object ）, Copy all the elements in the original object recursively to the new object .
stay Python in adopt
copy.deepcopy() To achieve deep copy .
import copy a = [1, 2, [3, 4]] b = copy.deepcopy(a) print(id(a)) # 66587176 print(id(b)) # 66587688 # change a Variable objects in a[-1].append(5) print(a) # [1, 2, [3, 4, 5]] print(b) # [1, 2, [3, 4]] After deep copy, the word list will not be affected by the original
1、 Both deep and shallow copies copy the source object , Take up different memory space
2、 If the source object has no subdirectories , The shallow copy can only copy the parent directory , Changing subdirectories affects shallow copy objects
3、 Slicing a list is essentially a shallow copy