轉載請注明出處:http://www.lxweimin.com/p/db57f7f70a5c
本文出自Shawpoo的簡書
我的博客:CSDN博客
【Python學習筆記專欄】:http://blog.csdn.net/column/details/17658.html
在學習Python的過程中,經常會對變量進行“賦值”,有時候又要對變量的值做臨時處理,而又不能改變原來變量的值,這就可能用到了“淺拷貝”和“深拷貝”。所以下面通過具體的例子來區分它們三者的不同。
另外,大多數面向對象的語言都會涉及到變量的“賦值”、“淺拷貝”和“深拷貝”,如Python,Java或者C++等。
一、賦值
在Python中,賦值很簡單,例如,將一個變量的值賦值給另一個變量,其實就是將這兩個變量指向同一個內存地址。所以如果這個變量的值改變了,那么另一個變量的值也會跟著改變,因為它們的內存地址始終相同。例:
a = [1, 2, 3, ['a', 'b', 'c']]
b = a
print(id(a), id(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)
執行結果:
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
的值改變而改變,也就是內存地址始終相同。
圖解: b = a: 賦值引用,a 和 b 都指向同一個對象。
二、淺拷貝
淺拷貝,只拷貝父對象,不會拷貝父對象中的子對象。如果該對象沒有子對象的話,其淺拷貝和賦值的結果是一樣的。淺拷貝可以通過導入copy
模塊中的copy()
方法來完成,或者調用對象本身的copy()
方法。例:
import copy # 導入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])
運行結果:
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 是一個獨立的對象,但它們的子對象還是指向同一對象(內存地址)。
三、深拷貝
深拷貝,也就是完全拷貝,包括拷貝對象的父對象及其子對象。拷貝后是
兩個完全獨立的對象,互不影響。我們可以通過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])
執行結果:
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
已經完全獨立,這就是深拷貝,拷貝父對象及其子對象。
圖解: b = copy.deepcopy(a): 深拷貝, a 和 b 完全拷貝了父對象及其子對象,兩者是完全獨立的。
總結
- 賦值:其實就是對象地址的引用。
-
淺拷貝(copy):調用
copy
模塊的copy()
方法,只拷貝父對象,不會拷貝對象內部的子對象。 -
深拷貝(deepcopy): 調用
copy
模塊的deepcopy()
方法,完全拷貝了父對象及其子對象。