1. 程式人生 > >【整理】關於python的 賦值,淺複製,深複製

【整理】關於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]
>>>