everything in python is an object
One: assignment
First look at the following example, id View the address of the object
x = 666
id(x) # 2650482715088
y = x
id(y) # 2650482715088
Because y=x just points y to the object pointed to by x, then you may be curious, if you modify x, will y change together? In fact, it will not, because when you modify x, you actually create a new object and point x to this object
x = 666
id(x) # 2650482966608
y = x
id(y) # 2650482966608
x=x+1
id(x) # 2650482967344
id(y) # 2650482966608
print(y) # 666
But this is only for immutable objects (int, string, etc.) mutable objects (list, etc.) will change. Because when an immutable object changes, a new object is actually created and assigned
x=[1,2,3]
y=x
id(x) # 2650483005960
id(y) # 2650483005960
x.append(5)
id(x) # 2650483005960
id(y) # 2650483005960
print(x) # [1, 2, 3, 5]
print(y) # [1, 2, 3, 5]
But if the variable object is changed explicitly, it will not affect the value of y
x = [1,2,3]
id(x) # 2650482808648
y = x
id(y) # 2650482808648
x = x + [4]
id(x) # 2650482864712
print(x)
print(y)
"""
[1, 2, 3, 4]
[1, 2, 3]
"""
Because actually a new object [1,2,3,4] is created and x points to this new object
2 cache pool
Look at the following example again, x and y point to the same object
x = 666
y = x
id(x) # 2040304935632
id(y) # 2040304935632
And the following is different
a = 888
id(a) # 2650482715440
b = 888
id(b) # 2650482715568
Because two objects are created and assigned to a and b respectively
- The first time: just create an integer object in memory
666
,x
andy
are the tags of this integer object - The second time: Create two integer objects in memory , using and as labels
888
respectivelya
b
Note: python has a pool of small integers (-5 ~ 256)
x=2
y=2
id(x) # 140736101317728
id(y) # 140736101317728
For such small and commonly used integer values as x
and , instead of creating two objects in memory, one object is created. At this time and are both labels of integer objects . Python's small integer pool is to improve cache efficiency and reduce the frequency of frequent creation and revocation of 'commonly used' objectsy
python
x
y
2
Similarly, strings also have a cache pool, and the cache mechanism complies with the following rules
Strings will be cached and reused, but they can only be composed of letters, numbers and underscores
s1="sssjkjksTjasdfgssshjkl哈"
len(s1)
s2="sssjkjksTjasdfgssshjkl哈"
id(s1) # 2040304847280
id(s2) # 2040304847664
s1 is s2 # False
s1="sssjkjks1Tjasdfgssshjklssssssss_"
len(s1)
s2="sssjkjks1Tjasdfgssshjklssssssss_"
id(s1) # 2040305172928
id(s2) # 2040305172928
s1 is s2
Next is shallow copy and deep copy
shallow copy and deep copy
First review the assignment just mentioned
abc=[1,'string',['python','java',25]]
zxc=abc
id(abc) # 2040305182344
id(zxc) # 2040305182344
So far there may be no doubts, modify the value inside, abc, zxc will change together
abc[0]=2
abc[2].append(5)
print(abc)
print(zxc)
"""
[2, 'string', ['python', 'java', 25, 5]]
[2, 'string', ['python', 'java', 25, 5]]
"""
but pay attention
abc=[1,'string',['python','java',25]]
zxc=abc
id(abc)
id(zxc)
print([id(x) for x in abc])
print([id(x) for x in zxc])
"""
[140736101317696, 2042134608752, 2040305268936]
[140736101317696, 2042134608752, 2040305268936]
"""
abc[0]=2
abc[2].append(5)
print(abc)
print(zxc)
"""
[2, 'string', ['python', 'java', 25, 5]]
[2, 'string', ['python', 'java', 25, 5]]
"""
print([id(x) for x in abc])
print([id(x) for x in zxc])
"""
[140736101317728, 2042134608752, 2040305268936]
[140736101317728, 2042134608752, 2040305268936]
"""
Note: The address of abc[0] has changed here, but the address of abc[2] remains unchanged (because int is an immutable object modification means creating a new object and assigning a value, while list is a mutable object)
Next is a shallow copy
abc=[1,'string',['python','java',25]]
zxc=copy.copy(abc)
id(abc) # 2040305143752
id(zxc) # 2040321956104
print([id(x) for x in abc])
print([id(x) for x in zxc])
"""
[140736101317696, 2042134608752, 2040305323016]
[140736101317696, 2042134608752, 2040305323016]
"""
Note that the addresses of abc and zxc are different, but the addresses of the elements in them still point to the same address
abc[0]=2
abc[2].append(5)
print(abc)
print(zxc)
"""
[2, 'string', ['python', 'java', 25, 5]]
[1, 'string', ['python', 'java', 25, 5]]
"""
print([id(x) for x in abc])
print([id(x) for x in zxc])
"""
[140736101320832, 2042134608752, 2040305323016]
[140736101317696, 2042134608752, 2040305323016]
"""
The address of abc[0] is different from the address of zxc[0], and the value is also different
deep copy
abc=[1,'string',['python','java',25]]
zxc=copy.deepcopy(abc)
id(abc) # 2326337710920
id(zxc) # 2326338046664
print([id(x) for x in abc])
print([id(x) for x in zxc])
"""
[140736246742080, 2326022994736, 2326340682056]
[140736246742080, 2326022994736, 2326340706824]
"""
abc[0]=99
abc[2].append(5)
print(abc)
print(zxc)
"""
[99, 'string', ['python', 'java', 25, 5]]
[1, 'string', ['python', 'java', 25]]
"""
print([id(x) for x in abc])
print([id(x) for x in zxc])
"""
[140736246745216, 2326022994736, 2326340682056]
[140736246742080, 2326022994736, 2326340706824]
"""
Note: There is no such thing as a copy for non-container types (such as numbers, strings, and other 'atomic' types of objects)
Summarize:
When "abc=zxc" is assigned, no new memory space is opened, and all variable modifications will affect each other
Shallow copy: Modifications to abc immutable objects will not affect zxc, but modifications to mutable objects will affect zxc
Deep copy: the modification of all variables will not affect each other
The case of shallow copy:
1 slice zxc=abc[:]
2 copy.copy
The case of deep copy:
1 copy.deepcopy
2 DataFrame.copy()
References:
1 Diagram of the difference between assignment, shallow copy, and deep copy in python
2 Python: Are function parameters passed by value or by reference?
3 Mutable objects and immutable objects