The above article introduces Python Dynamic type Shared reference Etc , With this foundation , Let's take a closer look at Python assignment , The principle of copying , There are different treatments involving mutable and immutable types . more Pyton Advanced Series , Please refer to Python Advanced learning Play data series
Summary :
Immutable type :
Python The immutable type in has an integer , character string , Tuples etc. , One-time creation , Cannot be modified , As long as there are changes , Is to re create a new object .
for example :Python The bottom is c Written language ,c There is no such thing as a string , A string is an array of characters , So the memory address is the way of character array
a = 'abc'
b = a
a = 'bcd'
sentence #1 a = ‘abc’
Create an array of strings ‘abc’ object , Assign the address of the string array to the variable a, The elements of the array store characters separately a,b,c.
sentence #2 b = a
Put the variable a The address of the string array pointed to is assigned to b
sentence #3 a = ‘bcd’
Create a new string array ‘bcd’ object , Assign the address of the new string array to the variable a, such a It's a change of direction , But variables b It still points to the string array ‘abc’ object .
Illustrates immutable type memory storage :
Variable type
Python The variable types in are list list ,set aggregate ,dict Dictionary, etc , One-time creation , Can be modified .
for example :list list
a = [1,'hi',3]
a.append(100)
a[1] = 22
sentence #1 a = [1,‘hi’,3]
Create a list object and 3 Other objects , Each element in the list stores the address of the element object .
Assign the address of the list object to the variable a
The first element of the list points to the value 1 Object address of
The second element of the list points to ‘hi’ String array object address , The elements in the string array are stored as characters h, i
The third element of the list points to a value of 3 Object address of
sentence #2 a.append(100)
Because lists are mutable objects , So you don't have to recreate creating new list objects , Add an element to the original list , Point to a new object 100 The address of .
sentence #3 a[1] = 22
Because lists are mutable objects , So you don't have to recreate creating new list objects , The change element in the original list points to , Point the second element of the list to another object 22 The address of .
Illustrates variable type memory storage : By the visible on , Immutable types have only one level of reference to , Mutable types have at least two levels of references to
.
Copy of immutable type copy:
import copy
a = 'hello'
a_assign = a
a_copy = copy.copy(a)
a_copy_deep = copy.deepcopy(a)
print("id(a):{}".format(id(a)))
print("id(a_assign):{}".format(id(a_assign)))
print("id(a_copy):{}".format(id(a_copy)))
print("id(a_copy_deep):{}".format(id(a_copy_deep)))
Output :
id(a):2557654519408
id(a_assign):2557654519408
id(a_copy):2557654519408
id(a_copy_deep):2557654519408
For immutable types such as numbers and strings , assignment 、 Shallow copy and deep copy are meaningless , Because it always points to the same memory address
.
Variable type copy:
import copy
a = [1,2,[3,4],5]
a_assign = a
a_copy = copy.copy(a) # same as a_assign = a[:]
a_copy_deep = copy.deepcopy(a)
a.append(66)
a[1] = 22
a[2][1] = 44
print("id(a):{}\t\ta:{}".format(id(a),a))
print("id(a_assign):{}\ta_assign:{}".format(id(a_assign),a_assign))
print("id(a_copy):{}\ta_copy:{}".format(id(a_copy),a_copy))
print("id(a_copy_deep):{}\ta_copy_deep:{}".format(id(a_copy_deep),a_copy_deep))
Output :
id(a):2527859256200 a:[1, 22, [3, 44], 5, 66]
id(a_assign):2527859256200 a_assign:[1, 22, [3, 44], 5, 66]
id(a_copy):2527859283528 a_copy:[1, 2, [3, 44], 5]
id(a_copy_deep):2527859255752 a_copy_deep:[1, 2, [3, 4], 5]
sentence #1 a = [1,2,[3,4],5]
Create a list as parent object , Assign the address of the list object to the variable a
Then create the values as 1,2,3,4,5 The object of ,
And create a list list Sub object , The first element points to the value 3 The object of , The second element points to a value of 4 The object of .
The first element of the main chain table points to the object 1 The address of
The second element of the main chain table points to the object 2 The address of
The third element of the main chain table points to the object list [3,4] The address of
The fourth element of the main chain table points to the object 5 The address of
sentence #2 a_assign = a
take Variable a Point to the Main list object Assign the address of to the variable a_assign
sentence #3 a_copy = copy.copy(a)
Shallow copy , Just copy variables a The top-level object of the object pointed to , Or say : Parent object , Don't torture shell objects . Only the first layer of data is created in memory .
That is, create a new main list object , Its address is assigned to the variable a_copy , The elements in the new list are copy a The element of the list object that points to .
This new list The first element points to the object 1 The address of
This new list The second element points to the object 2 The address of
This new list The third element points to the object list [3,4] The address of
This new list The fourth element points to the object 5 The address of Notice the second level sub objects ** list [3,4]** It's not copy Of
sentence #4 a_copy_deep = copy.deepcopy(a)
Deep copy , Copy all objects , Top level objects and their nested objects . Or say : Parent objects and their children . Recreate a copy of all the data in memory ( Exclude the last layer , namely :python Internal optimization of strings and numbers , Caching , Do not create short numbers frequently , Short string object )
The illustration :
sentence #5 a.append(66)
a The list object pointed to by the variable is appended with a new element pointing to the value 66 The object of , So the variable a = [1,2,[3,4],5, 66
]
because Variable a and Variable a_assign Points to the same list object , therefore a_assign = [1,2,[3,4],5, 66
]
a_copy_deep and a_copy_deep Points to the newly created main list object , So not affected , There is no change .
a_copy_deep = [1,2,[3,4],5]
a_copy_deep = [1,2,[3,4],5]
sentence #6 a[1] = 22
Put the variable a The second element in the pointed list points to another new object 22, So the variable a = [1,22
,[3,4],5], 66
]
because Variable a and Variable a_assign Points to the same list object , therefore a_assign = [1,22
,[3,4],5], 66
]
a_copy_deep and a_copy_deep Points to the newly created main list object , So not affected , There is no change .
a_copy_deep = [1,2,[3,4],5]
a_copy_deep = [1,2,[3,4],5]
sentence #7 a[2][1] = 44
Put the variable a The third element of the list pointed to is a child object , The second element of the child object points to another new object 44, So the variable a = [1,22
,[3,44
],5], 66
]
because Variable a and Variable a_assign Points to the same list object , therefore a_assign = [1,22
,[3,44
],5], 66
]
Because of the variable a_copy Just copied the variables a List of main objects pointed to , But not copy( Recreate ) Sub object , therefore a_copy The third element in the list object pointed to still corresponds to a The variable points to the child object of the third element in the main object , So child objects should also find changes , a_copy = [1,2,[3,44
],5]
a_copy_deep It is possible to recreate child objects , So don't suffer a The change of the sub object pointed to affects , So there's no change a_copy_deep = [1,2,[3,4],5]
The illustration :
Direct assignment : It's just a reference to an object ( Alias ).
Shallow copy (copy): Copy the parent object , Does not copy the inner child of an object .
Deep copy (deepcopy): copy Modular deepcopy Method , It completely copies the parent object and its children .
Deep and shallow copies are copies of the source object , Take up different memory space , That is, create a new memory space .
If the source object has only one level , Source makes any changes , Does not affect deep copy objects , For example, for immutable types ,int,str.
If the source object has more than one level of directory , Source makes any changes , All affect shallow copy , But it doesn't affect deep copy , Slices of sequence objects are actually shallow copies , That is, only the top-level objects are copied , For example, for convertible types , list,set,dict.