淺複製和深複製的區別在於,淺複製只複製引用到新的列表中(引用能夠理解爲地址),不會建立新對象。而深複製建立新的對象,並把對象保存在新的地址中。淺複製和深複製對可變和不可變序列的影響是不同的。對可變序列的淺複製會帶來意想不到的結果。看示例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。 app
由於淺複製只是複製了引用到新的列表中,他們的引用仍是同樣的,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。 code
由於淺複製的緣由,原本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
- l2修改對l2沒影響
- l2修改對l2有影響
- l2修改對l1有影響
- 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