1. 程式人生 > >針對Python的深淺拷貝問題

針對Python的深淺拷貝問題

對象 接收 數據 info pan 發現 相同 引用 詭異

前些天做了個小程序,遇到了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的深淺拷貝問題