圖解:python中的淺拷貝和深拷貝
首先,我們考慮這樣一個場景:在該場景中,我們各種列表的顏色,每個顏色代表假定顏色類的一個實例。比如,由一個warmtones列表表示現有的顏色,warmtones = list(''red","green","blue")
;
如圖所示:
我們希望創建一個名爲palette的新列表,複製一份warmtones列表。不過,我們可以在palette中添加額外的顏色,或修改、刪除一些現有的顏色,而不影響warmtones的內容。
如果我們這樣做:
patette = warmtones,就創建了一個別名,如圖所示:
如果在palette中添加或刪除顏色,會修改warmtones中的值。
代碼演示:
warmtones = ["Red","Green","Blue"]
palette = warmtones
print(id(warmtones))
print(id(palette))
palette.append("Pink")
print(palette)
print(warmtones)
輸出結果:
如果我們換一種方式,用list語法創建
palette = list(warmtones)
在這種情況下,我們顯式調用列表構造函數,將第一個列表作爲參數,這會導致一個新的列表被創建,如圖所示,這種就被稱爲 淺拷貝
在這一種情況中,我們可以合理地從palette添加或刪除元素而不影響warmtones。
代碼實例:
warmtones = ["Red","Green","Blue"]
palette = list(warmtones)
print(id(warmtones))
print(id(palette))
palette.append("Pink")
print('==========================')
print(id(palette[1]))
print(id(warmtones[1]))
print('=====================')
print(palette)
print(warmtones)
顯示效果:
可見,雖然warmtones和palette的地址不一樣了,但是它們列表中的元素還是指向同一個地址。
但是,如果是這樣情況下,warmtones的其中有一個列表元素的話,情況就不一樣了
代碼實例:
warmtones = ["Red","Green",["Blue","Orange"]]
palette = list(warmtones)
print(id(warmtones))
print(id(palette))
print('=====================')
palette[2].append("Yellow")
print(palette)
print(warmtones)
結果:
當對palette[2]中的列表作拓展操作時,warmtones[2]的列表也發生改變
我們更希望palette是warmtones的深拷貝(拷貝,包含對象裏面的自對象的拷貝,所以原始對象的改變不會造成深拷貝里任何子元素的改變
)。在深拷貝中,新副本引用的對象也是從原始版本中複製過來的。
圖片演示:
python中的copy模塊:
該模塊提供兩個函數:copy函數和deepcopy函數。copy函數創建對象的淺拷貝,deepcopy函數創建對象的深拷貝。
我們用深拷貝來重新編寫一下上面的代碼:
import copy
warmtones = ["Red","Green",["Blue","Orange"]]
palette = copy.deepcopy(warmtones)
print(id(warmtones))
print(id(palette))
print('=====================')
print(id(palette[1]))
print(id(warmtones[1]))
print('=====================')
palette[2].append("Yellow")
print(palette)
print(warmtones)
結果顯示:
發現,現在對palette[2]作append操作,warmtones就不會發生變換了