標籤:har 賦值 拷貝 學python port python語言 初學 ++ 修改
初學Python,和C++還是有許多不同。直接賦值、淺拷貝和深拷貝,這三種拷貝對象的操作之間還是有許多的區別。Python語言的版本為2.7,在Pycharm中進行實驗。
一、直接賦值
用下面的代碼來實驗:
1 origin = [1, "string", [1, 3, 5]] 2 Copy = origin 3 print Copy 4 print id(origin), id(Copy) 5 Copy[0] = 5 6 print origin, Copy 7 Copy[1] = "changed" 8 print origin, Copy 9 Copy[2][0] = 11110 print origin, Copy11 print id(origin), id(Copy)
啟動並執行結果如下:
[1, ‘string‘, [1, 3, 5]]38994824 38994824[5, ‘string‘, [1, 3, 5]] [5, ‘string‘, [1, 3, 5]][5, ‘changed‘, [1, 3, 5]] [5, ‘changed‘, [1, 3, 5]][5, ‘changed‘, [111, 3, 5]] [5, ‘changed‘, [111, 3, 5]]38994824 38994824
可見,直接賦值的新變數完完全全就是一個原對象的引用,任何對複製對象的引用都會影響到原對象。
二、淺拷貝
用相同的代碼來測試,僅僅把拷貝方式改成了copy.copy():
1 import copy 2 origin = [1, "string", [1, 3, 5]] 3 Copy = copy.copy(origin) 4 print Copy 5 print id(origin), id(Copy) 6 Copy[0] = 5 7 print origin, Copy 8 Copy[1] = "changed" 9 print origin, Copy10 Copy[2][0] = 11111 print origin, Copy12 print id(origin), id(Copy)
啟動並執行結果如下:
[1, ‘string‘, [1, 3, 5]]39453768 39510280[1, ‘string‘, [1, 3, 5]] [5, ‘string‘, [1, 3, 5]][1, ‘string‘, [1, 3, 5]] [5, ‘changed‘, [1, 3, 5]][1, ‘string‘, [111, 3, 5]] [5, ‘changed‘, [111, 3, 5]]39453768 39510280
這次可以發現,兩個對象指向的記憶體並不相同,也就是說,淺拷貝的對象是一個新的對象。另外,可以發現,對新對象的元素進行替換並不會影響到原對象,而對子物件——列表的修改會影響到原對象。
三、深拷貝
同樣,只是把拷貝方式換成copy.deepcopy():
1 import copy 2 origin = [1, "string", [1, 3, 5]] 3 Copy = copy.deepcopy(origin) 4 print Copy 5 print id(origin), id(Copy) 6 Copy[0] = 5 7 print origin, Copy 8 Copy[1] = "changed" 9 print origin, Copy10 Copy[2][0] = 11111 print origin, Copy12 print id(origin), id(Copy)
結果如下:
[1, ‘string‘, [1, 3, 5]]39978056 39994504[1, ‘string‘, [1, 3, 5]] [5, ‘string‘, [1, 3, 5]][1, ‘string‘, [1, 3, 5]] [5, ‘changed‘, [1, 3, 5]][1, ‘string‘, [1, 3, 5]] [5, ‘changed‘, [111, 3, 5]]39978056 39994504
同樣,兩個對象指向的記憶體位置並不相同,說明建立了新對象。此外,新對象的任何改動都不影響到原有的對象。
結論:
(1)直接賦值是一個完完全全的引用,對新變數的任何改動都會影響到原對象。
(2)淺拷貝建立了新的對象,但是只拷貝了序列的元素,對於元素也是一個序列的情況(即子物件),只複製了對這個序列的引用!
(3)深拷貝是完完全全的拷貝,把原對象完整地拷貝到了新對象中。
Python 賦值、淺拷貝和深拷貝