背景
在運用Python進行開發代碼過程中,會遇到變量復制備份的場景,但并沒有得到預期的結果,例如下面的例子:
![]()
lista = ['a', 'b', [1, 2, 3]]
listb = lista.copy()
lista[2].append(4)
print(lista) # ['a', 'b', [1, 2, 3, 4]]
print(listb) # ['a', 'b', [1, 2, 3, 4]]
代碼本意是將lista復制給listb做個備份,再修改liasta,但是修改后發現listb也一并被修改了,沒有達到備份的效果,這個是什么原因呢?
存儲方式
首先了解一下Python的變量在內存中的存儲方式。在基本數據類型中(包括set、list(tuple, str)、dict)都是采用引用的方式。
也就是說,每個變量都存儲的是這個變量的地址,而不是值本身,就算更復雜的嵌套結構,也是存儲是每個元素的地址而已,用一幅圖來表示。
![]()
如上圖所示,用戶看到的是 lista的4個元素值,但是內存中保存的卻是4個元素地址。
當元素是列表時,第一層保存的是列表的地址,第二層保存的是列表元素的地址,第三層才是列表的值。當元素是字典的時候,與列表類似。
列表的增刪改
在明白了變量存儲方式后,繼續看下內存下的增刪改是怎么變化的。
列表修改已有值
新增一個內存塊,再將引用的地址修改為新內存塊的地址。
![]()
列表新增一個值
新增一個內存塊,新增一個地址引用。
![]()
列表整體重新賦值
刪除變量地址和引用的值,新增地址和引用值的內存塊。
![]()
copy與deepcopy的區別
基于以上的理解,再來看兩種copy的區別就會更容易理解了,首先記住一個原則:
copy:不管多么復雜的數據結構,淺拷貝都只會copy一層。
deepcopy:將整個變量內存全部復制一遍,新變量與原變量沒有任何關系。
舉個例子來驗證一下上面的結論:有如下的一段代碼,最終的4個列表值是多少?
注意:引用deepcopy需要導入copy庫。
import copy
a = [1, 2, 3, 4, ['a', 'b']]
b = a
c = copy.copy(a)
d = copy.deepcopy(a)
a.append(5)
a[1] = 20
a[4].append('c')
del a[0]
print(a)
print(b)
print(c)
print(d)
列表b
表示b也引用的a的地址,兩者引用的內存地址是一樣的。因此b和a的關系是緊密相連的,一模一樣。可以通過 id(a) 和id(b)比較,兩者是一樣的。
列表c
由于c是淺拷貝的a列表,因此只copy了第一層,也就是地址層。
所以,當a.append(5)時,新增了一個內存塊,但是c只有前5個內存塊,因此c沒有變化。
繼續a修改了a[1],然而這個值是屬于第一層,已經copy給了c,因此c也沒有變化。
繼續a修改了子列表,這個時候a復制給c的只是列表的地址,且a中的子列表地址和c中的子列表地址是指向同一個地方的,因此修改了a中子列表,c中的子列表也會相應的改變。
最后刪除a[0],與修改a[1]一致,與c無關。可以用圖再說明一下。
![]()
列表d
由于d是深拷貝的a列表,因此d是將a的地址和值一并復制過來,與a沒有半點關系,也就是說d和a是兩個完全獨立的內存塊,沒有任何交集。因此,后面a的任意修改都與d無關,用圖表示如下。
![]()
因此,程序運行出來后的結果就是:
a:[20,3,4,['a','b','c'],5]
b:[20,3,4,['a','b','c'],5]
c:[1,2,3,4,['a','b','c']]
d:[1,2,3,4,['a','b']]
總結
綜上,我們在使用copy的時候,一定要記住:copy只是拷貝了第一層,而deepcopy才是拷貝的全部數據。
因此就不難發現,文章背景中的代碼使用備份功能時,備份列表需要使用deepcopy,而不是簡單的copy。
最后:在我的V :atstudy-js,可以免費領取一份10G軟件測試工程師面試寶典文檔資料。以及相對應的視頻學習教程免費分享!其中包括了有基礎知識、Linux必備、Shell、互聯網程序原理、Mysql數據庫、抓包工具專題、接口測試工具、測試進階-Python編程、Web自動化測試、APP自動化測試、接口自動化測試、測試高級持續集成、測試架構開發測試框架、性能測試、安全測試等。
![]()
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.