Python—淺拷貝和深拷貝的詳解
首先我們要了解一下淺拷貝和深拷貝的概念:
1.淺拷貝
定義:淺拷貝是對另外一個變量的內存地址的拷貝,這兩個變量指向同一個內存地址的變量值。
注:僅僅拷貝的是目標變量的所在地址,目標變量的所在地址不發生任何變化。
實際上,變量中並沒有存儲任何的值,它只是指向了一個內存地址,而這個地址裏存儲着具體的內容,例如把變量a賦值給變量b的時候,實際上是把a指向內存中某對象的鏈接賦給了b,也就是說,現在a和b都指向了同一個對象。因此,在改變了內存中array的值後,而a與b都引用了該array對象,所以都一起發生了變化
淺拷貝的特點:
- 公用一個值;
- 這兩個變量的內存地址一樣;
- 對其中一個變量的值改變,另外一個變量的值也會改變;
2.深拷貝
定義:一個變量對另外一個變量的值拷貝。
注:拷貝的是目標變量的值,是真實的拷貝,新的變量產生了新的內存地址。
深拷貝的特點:
- 變量的內存地址不同;
- 變量各有自己的值,且互不影響;
- 對其任意一個變量的值的改變不會影響其餘變量的值;
3. Python中表(List)數據中
-
直接賦值給另一個變量是 淺拷貝
-
切片操作 是 深拷貝
#Python中的淺拷貝 a = [1,2,3,4,5,6] b = a #a直接賦值b print('a的初始內存地址:',id(a)) print('b的初始內存地址:',id(b)) b.append(7)#對b尾部加數字7 print('a:',a) print('b:',b) print('a的當前內存地址:',id(a)) print('b的當前內存地址:',id(b)) print('-----------------------------') c = a[0:3] # c使用切片進行拷貝 c.append(8)#在c的尾部添加數字8 a.append(9) print('a:',a) print('b:',b) print('c:',c) print('a的內存地址:',id(a)) print('b的內存地址:',id(b)) print('c的內存地址:',id(c))#打印c的內存地址 """ a的初始內存地址: 2186126011016 b的初始內存地址: 2186126011016 a: [1, 2, 3, 4, 5, 6, 7] b: [1, 2, 3, 4, 5, 6, 7] a的當前內存地址: 2186126011016 b的當前內存地址: 2186126011016 ----------------------------- a: [1, 2, 3, 4, 5, 6, 7, 9] b: [1, 2, 3, 4, 5, 6, 7, 9] c: [1, 2, 3, 8] a的內存地址: 2186126011016 b的內存地址: 2186126011016 c的內存地址: 2186126011976 """
-
顯然淺拷貝後變量的存放地址相同,僅僅是拷貝到內存地址,且其中一個變量發生增刪等操作會直接改變目標變量的值;
-
深拷貝後變量的存放地址不同,說明另外開闢了新的內存空間存放拷貝後的變量,且其中一個變量的增刪操作不會不會對其餘的變量產生影響。
4. Numpy 中的深拷貝和淺拷貝
np.copy()
方法是 深拷貝;- 切片操作是特殊的 淺拷貝;(注意與python的list切片使用是深拷貝,這是一種特殊的淺拷貝,因爲出現了新的內存地址,但是數據修改仍會同步)
- 直接賦值給另一個變量是 淺拷貝。
# 導入numpy
import numpy as np
a = np.arange(6)
print('一、淺拷貝')
#1、直接賦值法
b = a
#2、切片法
c = a[:]
print('a:',a)
print('b:',b)
print('c:',c)
print('改變b的第1個位置上的元素之後———')
# 改變a中第一個元素的值
a[0] = 4
c[2] = 7
print('a:',a,id(a))
print('b:',b,id(b))
print('c:',c,id(c))
print('二、深拷貝')
d = a.copy()
print('a:',a)
print('d:',d)
# 將a的第2個元素值也更改
a[1] = 5
print('賦值後:')
print('a:',a,id(a))
print('d:',d,id(d))
"""
一、淺拷貝
a: [0 1 2 3 4 5]
b: [0 1 2 3 4 5]
c: [0 1 2 3 4 5]
改變b的第1個位置上的元素之後———
a: [4 1 7 3 4 5] 2186126040480
b: [4 1 7 3 4 5] 2186126040480
c: [4 1 7 3 4 5] 2186126040960 #numpy中的切片的使用比較特殊,會發現存儲地址已經發出變化,但是a和c之間仍然會相互影響,所以這是一種特殊的淺拷貝。
二、深拷貝
a: [4 1 7 3 4 5]
d: [4 1 7 3 4 5]
賦值後:
a: [4 5 7 3 4 5] 2186126040480
d: [4 1 7 3 4 5] 2186125987392
"""