轉(zhuǎn)載請注明出處:http://www.reibang.com/p/db57f7f70a5c
本文出自Shawpoo的簡書
我的博客:CSDN博客
【Python學(xué)習(xí)筆記專欄】:http://blog.csdn.net/column/details/17658.html
在學(xué)習(xí)Python的過程中悍赢,經(jīng)常會對變量進(jìn)行“賦值”,有時候又要對變量的值做臨時處理,而又不能改變原來變量的值啊奄,這就可能用到了“淺拷貝”和“深拷貝”纬朝。所以下面通過具體的例子來區(qū)分它們?nèi)叩牟煌?/p>
另外收叶,大多數(shù)面向?qū)ο蟮恼Z言都會涉及到變量的“賦值”、“淺拷貝”和“深拷貝”共苛,如Python判没,Java或者C++等。
一隅茎、賦值
在Python中澄峰,賦值很簡單,例如辟犀,將一個變量的值賦值給另一個變量俏竞,其實(shí)就是將這兩個變量指向同一個內(nèi)存地址。所以如果這個變量的值改變了堂竟,那么另一個變量的值也會跟著改變魂毁,因?yàn)樗鼈兊膬?nèi)存地址始終相同。例:
a = [1, 2, 3, ['a', 'b', 'c']]
b = a
print(id(a), id(b)) #打印它們各自的內(nèi)存地址
print(a)
print(b)
a.append(4)
print("-----------")
print(id(a), id(b))
print(a)
print(b)
a[3].append('d')
print("-----------")
print(id(a), id(b))
print(a)
print(b)
print(a is b)
執(zhí)行結(jié)果:
2524323181384 2524323181384
[1, 2, 3, ['a', 'b', 'c']]
[1, 2, 3, ['a', 'b', 'c']]
-----------
2524323181384 2524323181384
[1, 2, 3, ['a', 'b', 'c'], 4]
[1, 2, 3, ['a', 'b', 'c'], 4]
-----------
2524323181384 2524323181384
[1, 2, 3, ['a', 'b', 'c', 'd'], 4]
[1, 2, 3, ['a', 'b', 'c', 'd'], 4]
True
通過上述的例子可以看出出嘹,在“賦值”的情況下席楚,變量b
的值始終隨著變量a
的值改變而改變,也就是內(nèi)存地址始終相同税稼。
圖解: b = a: 賦值引用烦秩,a 和 b 都指向同一個對象刁赦。
二、淺拷貝
淺拷貝闻镶,只拷貝父對象甚脉,不會拷貝父對象中的子對象。如果該對象沒有子對象的話铆农,其淺拷貝和賦值的結(jié)果是一樣的牺氨。淺拷貝可以通過導(dǎo)入copy
模塊中的copy()
方法來完成,或者調(diào)用對象本身的copy()
方法墩剖。例:
import copy # 導(dǎo)入copy模塊
a = [1, 2, 3, ['a', 'b', 'c']]
b = copy.copy(a) # a.copy()
print(id(a), id(b))
print(a is b)
print(a)
print(b)
a.append(4)
print("-----------")
print(id(a), id(b))
print(a)
print(b)
a[3].append('d')
print("-----------")
print(id(a), id(b))
print(a)
print(b)
print(a is b)
print(a[3] is b[3])
運(yùn)行結(jié)果:
1558199464776 1558199464904
False
[1, 2, 3, ['a', 'b', 'c']]
[1, 2, 3, ['a', 'b', 'c']]
-----------
1558199464776 1558199464904
[1, 2, 3, ['a', 'b', 'c'], 4]
[1, 2, 3, ['a', 'b', 'c']]
-----------
1558199464776 1558199464904
[1, 2, 3, ['a', 'b', 'c', 'd'], 4]
[1, 2, 3, ['a', 'b', 'c', 'd']]
False
True
通過上述的例子可以看出猴凹,我們改變變量a
中父對象的值,不會影響變量b
岭皂,但是改變變量a
中子對象的值郊霎,那么變量b
也會隨之改變,這就是淺拷貝爷绘,只拷貝父對象书劝,而不拷貝子對象。
圖解:b = copy.copy(a): 淺拷貝, a 和 b 是一個獨(dú)立的對象土至,但它們的子對象還是指向同一對象(內(nèi)存地址)购对。
三、深拷貝
深拷貝陶因,也就是完全拷貝骡苞,包括拷貝對象的父對象及其子對象】铮拷貝后是
兩個完全獨(dú)立的對象解幽,互不影響。我們可以通過copy
模塊中的deepcopy()
方法來完成烘苹。
import copy
a = [1, 2, 3, ['a', 'b', 'c']]
b = copy.deepcopy(a)
print(id(a), id(b))
print(a is b)
print(a)
print(b)
a.append(4)
print("-----------")
print(id(a), id(b))
print(a)
print(b)
a[3].append('d')
print("-----------")
print(id(a), id(b))
print(a)
print(b)
print(a is b)
print(a[3] is b[3])
執(zhí)行結(jié)果:
3143729499336 3143729558024
False
[1, 2, 3, ['a', 'b', 'c']]
[1, 2, 3, ['a', 'b', 'c']]
-----------
3143729499336 3143729558024
[1, 2, 3, ['a', 'b', 'c'], 4]
[1, 2, 3, ['a', 'b', 'c']]
-----------
3143729499336 3143729558024
[1, 2, 3, ['a', 'b', 'c', 'd'], 4]
[1, 2, 3, ['a', 'b', 'c']]
False
False
通過上述的例子可以看出躲株,不管我們改變變量a
中父對象的值,還是改變子對象的值螟加,都不會影響變量b
的值徘溢,那么說明此時變量a
和變量b
已經(jīng)完全獨(dú)立吞琐,這就是深拷貝捆探,拷貝父對象及其子對象。
圖解: b = copy.deepcopy(a): 深拷貝, a 和 b 完全拷貝了父對象及其子對象站粟,兩者是完全獨(dú)立的黍图。
總結(jié)
- 賦值:其實(shí)就是對象地址的引用。
-
淺拷貝(copy):調(diào)用
copy
模塊的copy()
方法奴烙,只拷貝父對象助被,不會拷貝對象內(nèi)部的子對象剖张。 -
深拷貝(deepcopy): 調(diào)用
copy
模塊的deepcopy()
方法,完全拷貝了父對象及其子對象揩环。