轉(zhuǎn)載請(qǐng)注明出處:http://www.itdecent.cn/p/db57f7f70a5c
本文出自Shawpoo的簡(jiǎn)書
我的博客:CSDN博客

【Python學(xué)習(xí)筆記專欄】:http://blog.csdn.net/column/details/17658.html
在學(xué)習(xí)Python的過(guò)程中,經(jīng)常會(huì)對(duì)變量進(jìn)行“賦值”,有時(shí)候又要對(duì)變量的值做臨時(shí)處理,而又不能改變?cè)瓉?lái)變量的值,這就可能用到了“淺拷貝”和“深拷貝”。所以下面通過(guò)具體的例子來(lái)區(qū)分它們?nèi)叩牟煌?/p>
另外,大多數(shù)面向?qū)ο蟮恼Z(yǔ)言都會(huì)涉及到變量的“賦值”、“淺拷貝”和“深拷貝”,如Python,Java或者C++等。
一、賦值
在Python中,賦值很簡(jiǎn)單,例如,將一個(gè)變量的值賦值給另一個(gè)變量,其實(shí)就是將這兩個(gè)變量指向同一個(gè)內(nèi)存地址。所以如果這個(gè)變量的值改變了,那么另一個(gè)變量的值也會(huì)跟著改變,因?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
通過(guò)上述的例子可以看出,在“賦值”的情況下,變量b的值始終隨著變量a的值改變而改變,也就是內(nèi)存地址始終相同。
圖解: b = a: 賦值引用,a 和 b 都指向同一個(gè)對(duì)象。

二、淺拷貝
淺拷貝,只拷貝父對(duì)象,不會(huì)拷貝父對(duì)象中的子對(duì)象。如果該對(duì)象沒(méi)有子對(duì)象的話,其淺拷貝和賦值的結(jié)果是一樣的。淺拷貝可以通過(guò)導(dǎo)入copy模塊中的copy()方法來(lái)完成,或者調(diào)用對(duì)象本身的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
通過(guò)上述的例子可以看出,我們改變變量a中父對(duì)象的值,不會(huì)影響變量b,但是改變變量a中子對(duì)象的值,那么變量b也會(huì)隨之改變,這就是淺拷貝,只拷貝父對(duì)象,而不拷貝子對(duì)象。
圖解:b = copy.copy(a): 淺拷貝, a 和 b 是一個(gè)獨(dú)立的對(duì)象,但它們的子對(duì)象還是指向同一對(duì)象(內(nèi)存地址)。

三、深拷貝
深拷貝,也就是完全拷貝,包括拷貝對(duì)象的父對(duì)象及其子對(duì)象??截惡笫?br>
兩個(gè)完全獨(dú)立的對(duì)象,互不影響。我們可以通過(guò)copy模塊中的deepcopy()方法來(lái)完成。
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
通過(guò)上述的例子可以看出,不管我們改變變量a中父對(duì)象的值,還是改變子對(duì)象的值,都不會(huì)影響變量b的值,那么說(shuō)明此時(shí)變量a和變量b已經(jīng)完全獨(dú)立,這就是深拷貝,拷貝父對(duì)象及其子對(duì)象。
圖解: b = copy.deepcopy(a): 深拷貝, a 和 b 完全拷貝了父對(duì)象及其子對(duì)象,兩者是完全獨(dú)立的。

總結(jié)
- 賦值:其實(shí)就是對(duì)象地址的引用。
-
淺拷貝(copy):調(diào)用
copy模塊的copy()方法,只拷貝父對(duì)象,不會(huì)拷貝對(duì)象內(nèi)部的子對(duì)象。 -
深拷貝(deepcopy): 調(diào)用
copy模塊的deepcopy()方法,完全拷貝了父對(duì)象及其子對(duì)象。