【整理】關於python的 賦值,淺複製,深複製
借花獻佛
轉載的文章,
https://www.jianshu.com/p/55db812f7f0a
https://www.jianshu.com/p/75a8b01d7899
從這2個作者聊到的 深複製,淺複製談起,我自己學到很多東西,非常感謝
另外總計一下,繼續學習
總結
(1) 直接賦值=,那就是指標指向物件而已
(2) 淺複製 shallow copy :
(3) 深複製 deep copy :
複製操作1
obj.copy()
obj.deepcopy()
複製操作2
import copy
copy.copy()
copy.deepcopy()
原理
都是指向物件的
(1) python其實沒有變數,這些"變數 variables "其實都是 "標籤" tag
( 標籤tag用來給obj 貼上去, just a name,not obj itself)
(2) python 沒有"賦值",其實都是 引用
(3) 賦值的時候發生了什麼:
如 listA1=[1,2,3]
listA2=[4,5,6]
1 首先建立了一個[1,2,3]的list的obj
2 賦值打標籤:把listA1 貼給這個obj
3 建立新列表物件[4,5,6]
4 再賦值打標籤:把listA1 貼給新的obj
5 老的[1,2,3]怎麼辦?有python的垃圾回收機制處理
實測
直觀差別
賦值:兩者關聯改動,listB=listA
淺複製:第一層,兩者獨立,方法1:使用copy()方法:listB=listA.copy()
方法2:使用切片操作 listB=listA[:] 或 listB=[0:len(listA)+1]
深複製:完全獨立,指向不同的物件
>>> import copy
>>> listA=[[1,2,3],4,5,6]
>>> listB=listA
>>> listC=listA.copy()
>>> listD=copy.deepcopy(listA)
>>> listA[-1]=999
>>> listA[0][0]=888
>>> listA
[[888, 2, 3], 4, 5, 999]
>>> listB
[[888, 2, 3], 4, 5, 999]
>>> listC
[[888, 2, 3], 4, 5, 6]
>>> listD
[[1, 2, 3], 4, 5, 6]
>>>
直接賦值
因為直接賦值會導致兩個變數,關聯,都指向同一個obj
無論哪個變數變化了,都會一起改變
但是如果某一個變數被重新賦值了---重新指向給了另外一個物件,那麼2個變數就不指向同一個obj了
2個變數分別指向了2個obj,意味著兩個obj任何變化,也都隻影響對應的1個變量了
>>> listC1=[1,2,3]
>>> listC2=listC1
>>> print(listC1,listC2)
[1, 2, 3] [1, 2, 3]
>>> listC1[0]="A"
>>> print(listC1,listC2)
['A', 2, 3] ['A', 2, 3]
>>> listC1=[4,5,6]
>>> print(listC1,listC2)
[4, 5, 6] ['A', 2, 3]
>>> listC1[0]="B"
>>> print(listC1,listC2)
['B', 5, 6] ['A', 2, 3]
為什麼會導致迴圈?
因為用的直接賦值--引用,會導致自己的某個 index 又指向自己
>>> listA1=[1,2,3]
>>> listA1[1]=listA1
>>> listA1
[1, [...], 3]
轉的這個圖,我始終覺得有點問題,或者是沒看懂,因為物件不應該指自己,而是index指著物件啊,這個圖有點混淆?
避免這種迴圈的辦法--淺複製
>>> listA1=[1,2,3]
>>> listA1[0]=listA1[:]
>>> listA1
[[1, 2, 3], 2, 3]
>>> listA1=[1,2,3]
>>> listA1[2]=listA1.copy()
>>> listA1
[1, 2, [1, 2, 3]]
多層時,非第1層外,淺複製會出錯
>>> listB1=[[1,2,3],2,3]
>>> listB1
[[1, 2, 3], 2, 3]
>>> listB2=listB1.copy()
>>> listB1[0][0]="a"
>>> listB1[2]="b"
>>> listB1
[['a', 2, 3], 2, 'b']
>>> listB2
[['a', 2, 3], 2, 3]
>>>