等等,這就是Python淺複製和深複製的區別!

淺複製和深複製的區別在於,淺複製只複製引用到新的列表中(引用能夠理解爲地址),不會建立新對象。而深複製建立新的對象,並把對象保存在新的地址中。淺複製和深複製對可變和不可變序列的影響是不同的。對可變序列的淺複製會帶來意想不到的結果。看示例1python

示例1
>>>a = [[1],2,3,4]
>>>b = list(a)
>>>a[0].append(0)
>>>a
[[1, 0], 2, 3, 4] 
>>>b
[[1, 0], 2, 3, 4]

對於複製列表,最簡單的方式是使用內置類型的構造方法list(),也能使用[:]複製副本。無論是構造方法仍是[:]都是淺複製。從示例1能夠看到,對a的第0個元素進行了修改,可是b也發生了改變。爲何呢?我先要理解a和b之間發生了什麼?見下面圖1。 圖1app

由於淺複製只是複製了引用到新的列表中,他們的引用仍是同樣的,a和b的第0個元素都是指向列表[1],由於列表是可變序列,能夠原地修改,因此修改後引用不變。這就致使了a的修改會帶來了b的改變。再看看示例2函數

示例2
>>>a = [1,2,3,4]
>>>b = list(a)
>>>a[0]=0
>>>a
[0, 2, 3, 4] 
>>>b
[1, 2, 3, 4]

示例2中a的修改並無帶有b的變化,他們之間有發生了什麼?看下面圖2。 圖2code

由於淺複製的緣由,原本a,b的引用都是同樣的,而後對a的第0元素進行了修改,因爲該元素是不可變序列,要改變只能從新建立新的對象,因此a的第0個元素的引用發生了改變,但這並不影響到b的第0個元素的引用。好了,再看一個複雜點的例子,看示例3對象

示例3
>>>l1=[1,[2,3,4],(5,6,7)]
>>>l2=list(l1)
>>>l1.append(10)#1
>>>l1[1].remove(3)#2
>>>l2[1] +=[8,9]#3
>>>l2[2] += (10,11)#4
  1. l2修改對l2沒影響
  2. l2修改對l2有影響
  3. l2修改對l1有影響
  4. l2修改對l1沒影響

淺複製的結果可能不是你想要的,那麼如何作深複製呢?。事實上,copy模塊提供的copy和deepcopy函數能爲任意對象作淺複製和深複製,看示例4。blog

示例4
>>>import copy 
>>>l1=[1,[2,3,4],(5,6,7)]
>>>l2=copy.deepcopy(l1)
>>>l3=copy.copy(l1)
>>>l1[1].remove(3)
>>>l1
>>>l1=[1,[2,4],(5,6,7)]
>>>l2
>>>l1=[1,[2,3,4],(5,6,7)]
>>>l3
[1,[2,4],(5,6,7)]

l2是l1的深複製,l3是l2的淺複製,對l1第1個元素進行了修改,雖然該元素是可變對象,影響了l3,可是沒有影響到l2。由於l2是深複製的緣由,因此是建立了新的對象,有了新的引用,能夠說是跟l2沒有一毛錢關係了,他們只是內容同樣而已。最後看一個有趣的現象,看示例5。圖片

示例5
>>>l1=[1,[2,3,4],(5,6,7)]
>>>l1.append(l1)
>>>l1
[1, [2, 4], (5, 6, 7), [...]]

看l2最後的元素竟然是神奇的[...],這到底是什麼回事?看看下面圖3的引用就知道了,來! 在這裏插入圖片描述rem

能夠看到,列表最後元素的引用指向了自身,自身的最有元素仍是指向自身,這是一個無限循環引用,因此出現了[...]class

以上,歡迎指出錯誤。import

更多精彩文章請關注我公衆號:CVpython 在這裏插入圖片描述

相關文章
相關標籤/搜索