一、深複制與淺複制
清單是Python中自帶的一種資料結構,在使用清單時,拷貝操作不可避免,下面簡單讨論一下清單的深複制(拷貝)與淺複制
首先看代碼:
l1 = [5, 4, 3, 2, 1]
# 用兩種方法實作對清單l1的拷貝
l2 = l1
l3 = l1[:]
print(l1) # [5, 4, 3, 2, 1]
print(l2) # [5, 4, 3, 2, 1]
print(l3) # [5, 4, 3, 2, 1]
#修改l1
l1[0] = 9
print(l1) # [9, 4, 3, 2, 1]
print(l2) # [9, 4, 3, 2, 1]
print(l3) # [5, 4, 3, 2, 1]
我們發現修改l1的第一個元素後,l2的第一個元素跟着改變,而l3并沒有發生變化。Python内置函數id()可以傳回元素的位址,那麼我們使用這個函數來看一下三個清單的位址:
print(id(l1)) # 2927957162504
print(id(l2)) # 2927957162504
print(id(l3)) # 2927923243528
從結果來看,l1和l2位址是一樣的,也就是說l1和l2指向的是同一塊記憶體區域,顯然,通過 l2 = l1 操作,l1和l2都成了指向同一塊記憶體位址的“指針”,也就是說這個操作是為l1取了一個别名,也可以說l2是l1的一個引用。用一張圖來解釋:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5CZkRzN3UDNlhTOzQWOyQjZ5gTZ1UjZldTZ5ATZ0YjM48CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
那麼修改l1也就是在修改l2:
接下來看一下建立l3的過程,l3 = l1[:] ,這是将l1進行切片,并将切片後的清單拷貝到l3所指向的記憶體區域,同樣看圖:
也就是說l1和l3指向不同的記憶體區域,那麼修改l1并不會影響到l3:
通俗的來講,像l2這種,拷貝出來的對象和原對象的位址相同,為淺複制,像l3這種,配置設定新的記憶體空間并拷貝原始内容的,拷貝出來的對象和原對象的位址不同,為深複制。
二、複制清單内元素的淺複制
在複制清單中的所有元素的時候,進行淺複制
看一個比較有意思的東西,看代碼:
l1 = [1,2,3,[1,3]]
l2 = l1[:]
l1[3][1] = 9
print(l1) # [1, 2, 3, [1, 9]]
print(l2) # [1, 2, 3, [1, 9]]
按照前面的了解,修改l1某個元素後,l2應該不會發生改變,可結果卻與我們預想的結果大相徑庭,于是,我們不得不思考一下l2深複制到底複制了什麼東西。實際上清單其實可以了解為一個“指針”,l1[3]是一個清單元素,l2[3]也是一個清單元素,執行以下代碼:
print(id(l2[3])) # 2014816956232
print(id(l1[3])) # 2014816956232
我們發現l1[3]和l2[3]指向的位址是一樣的,也就是說在執行 l2 = l1[:] 的時候,将一個位址拷貝了,是以修改l1[3]相當于修改l2[3],是以才會出現上述結果,這更加說明了清單其實就是一個指向一片記憶體區域的“指針”。那麼我們是不是可以說清單l2深複制l1,但是對清單中每個元素進行複制時進行的是淺複制呢?答案顯而易見。
修改l1[3]中的元素:
三、copy()和deepcopy()
copy子產品可以幫助我們實作對象的複制操作
列舉一下其他的拷貝清單的方式:
l4 = l1 * 1
print(id(l4)) # 2927957916296
l5 = list(l1)
print(id(l5)) # 2927957767816
import copy
l6 = copy.copy(l1)
print(id(l6)) # 2927956854024
l7 = copy.deepcopy(l1)
print(id(l7)) # 2927958503368
我們可以看到,這幾種拷貝方式所得到的的新對象與原對象的位址都不相同了,并沒有按照字面意思(copy進行淺複制,deepcopy進行深複制),那麼copy()和deepcopy()究竟有什麼差別呢,繼續看代碼:
list1 = [1,2,3,[1,3]]
list2 = list1[:]
list3 = copy.copy(list1)
list4 = copy.deepcopy(list1)
list1[3][0] = 9
print(list1) # [1, 2, 3, [9, 3]]
print(list2) # [1, 2, 3, [9, 3]]
print(list3) # [1, 2, 3, [9, 3]]
print(list4) # [1, 2, 3, [1, 3]]
print(id(list1[3])) # 2927923172616
print(id(list2[3])) # 2927923172616
print(id(list3[3])) # 2927923172616
print(id(list4[3])) # 2927967190728
可以發現copy()和前面提到的用 [:] 進行拷貝沒有本質上的差別,對清單中的每個元素進行複制時進行的是淺拷貝,而deepcopy()在複制清單中的每個元素的時候,進行的是深拷貝。
總結
到此這篇關于Python清單的深複制和淺複制的文章就介紹到這了,更多相關Python清單深複制和淺複制内容請搜尋雲海天教程以前的文章或繼續浏覽下面的相關文章希望大家以後多多支援雲海天教程!