針對Python的深淺拷貝問題
前些天做了個小程序,遇到了Python的深淺拷貝問題
感覺自己基礎不夠紮實,就翻了翻教程,真的是非常基礎的知識。。。(各位大佬下手輕點2333)
下面簡單說說:
首先有個字典a
1 a = {‘A‘:1,‘B‘:2,‘C‘:3,‘D‘:4}
然後我們把它賦值給另外一個空字典b
1 b = {} 2 b = a
當我們輸出b時,可以看到a和b直觀上看好像是相等了
按照常理,我們會認為a和b現在是兩個值相等的字典,如果我們對其中一個操作,另外一個應該不會受到影響才對,所以我們試一下:
我們嘗試刪除b中的一個鍵值對
1 b.pop(‘A‘)
輸出b
理所當然地b其中一個鍵值對被刪除了
然後我們試著輸出a,詭異的事情發生了
我們只是對b進行了鍵值對的刪除,怎麽a的值也變了?
原因就是Python的賦值原理
其實我們所謂的將a賦值給了b,賦給b的並不是a的值,而是a所存儲的值的地址
所以當我們輸出b的時候,輸出的是和a一樣的值
因此,我們對b進行的操作,都會影響到在內存中的{‘A‘:1,‘B‘:2,‘C‘:3,‘D‘:4}
當我們刪除b的一個鍵值對時,其實就是對{‘A‘:1,‘B‘:2,‘C‘:3,‘D‘:4}的鍵值對進行了刪除
此時a和b指向的就是新的字典{‘B‘: 2, ‘C‘: 3, ‘D‘: 4}
所以我們輸出的時候發現值的變更
那麽,如何真正的拷貝值呢?
這裏就涉及到Python的深淺拷貝問題
使用Python的copy()和deepcopy()方法可以實現淺拷貝和深拷貝
什麽是淺拷貝和深拷貝?
淺拷貝只對對象中的父對象進行拷貝,但不會連同其子對象一同復制
深拷貝則是對對象中的所有對象包括其子對象進行復制
舉個例子:
(因為copy()方法和deepcopy()方法需要調用copy模塊,故我們先提前引用)
import copy
定義字典a
1 a = {‘A‘:1,‘B‘:2,‘C‘:3,‘D‘:[1,2,3]}
作為對照組,我們創建b,同樣將a賦給它(其實是傳,你應該知道為什麽了)
b = a
現在我們先進行淺拷貝
創建c,接收a的淺拷貝
1 c = copy.copy(a)
接下來進行深拷貝
1 d = copy.deepcopy(a)
之後,我們對a進行一系列改動,觀察b,c,d的值的變化
首先我們對a的某鍵值對進行刪除
1 a.pop(‘A‘)
然後我們對a中鍵為D的子對象進行改動,我們在D中添加一個子對象
a[‘D‘].append(4)
現在,我們分別輸出a,b,c,d,觀察他們的區別
首先是a,很顯然的結果
其次是b,因為賦給引用的原因,同樣會被改變,與a的值相同
再輸出c,發現了端倪
再看看d
我們發現,a和b中的父對象及其子對象均受到了改變
c雖然父對象沒有受到影響,但是其中鍵值為D的元素值(列表)發生了改變,所以由此我們發現,淺拷貝只會復制對象中的父對象,而其子對象在源數據收到改變時,仍會收到相同的影響
再轉過來看d,與被我們改動前的a完全相同,所以說深拷貝非常完整地實現了對象的復制,由此我們發現,深拷貝可以復制對象的全部內容包括其子對象
為了更直觀一點,可以參考下面的圖:
所以,在進行數據拷貝時,可以視情況考慮拷貝的方式。當然這裏還涉及到數據類型的可變和不可變類型的因素,這裏不做過多討論。
本文部分內容參考了Alex大佬的博客,對Python的深淺拷貝進行了非常詳細的討論,十分推薦大家去學習
傳送門https://m.2cto.com/net/201606/515654.html
針對Python的深淺拷貝問題