python中淺復(fù)制copy與深復(fù)制deepcopy
簡介
在使用列表或者字典進(jìn)行傳遞參數(shù)的時候,可能會遇到函數(shù)改變了列表的值,但是不希望印象原來列表中的值,所以,python提供了copy模塊,其中包含copy()和deepcopy()兩函數(shù),顧名思義copy()指的就是淺復(fù)制,deepcopy()指的就是深復(fù)制。
copy.copy()詳解
copy.copy()主要是用來復(fù)制一維列表或者一維元組,即 像[‘A’,‘B’,‘C’,‘D’]這種,如果列表中再套列表,比如這種[‘A’,‘B’,[‘d’,‘e’,‘f’],‘C’] 就不能進(jìn)行復(fù)制更改。下面來做一個簡單的測試。
import copy lis_A = ['A','B','C','D'] lis_B = ['A','B',['d','e','f'],'C'] # 使用copy.copy()復(fù)制lis_A copy_A = copy.copy(lis_A) print('lis_A的值', lis_A) print('copy_A的值', copy_A) # 打印出lis_A和copy_A的ID值 print('lis_A的ID值', id(lis_A)) print('copy_A的ID值', id(copy_A))
輸出結(jié)果是:
lis_A的值 ['A', 'B', 'C', 'D']
copy_A的值 ['A', 'B', 'C', 'D']
lis_A的ID值 1347357010368
copy_A的ID值 1347357613888
這里可以看出。copy_A的值與lis_A的值是一樣的,但是它們的ID值是不一樣的,說明copy_A指向了一個獨立的列表。那么改變copy_A的值是不會去影響lis_A的列表的值,可以做試驗:
從上面可以看出,我改變了copy_A中的 ‘B’ 的值,但是并沒有影響到lis_A中的值。
使用copy()復(fù)制嵌套列表會是什么結(jié)果呢?
lis_B = ['A', 'B', ['d', 'e', 'f'], 'C'] # 使用copy_B復(fù)制 lis_B copy_B = copy.copy(lis_B) # 分別打印lis_B和copy_B的值 print('lis_B的值', lis_B) print('copy_B的值', copy_B) # 打印出lis_B和copy_B的ID值 print('lis_B的ID值', id(lis_B)) print('copy_B的ID值', id(copy_B))
輸出的結(jié)果是:
lis_B的值 ['A', 'B', ['d', 'e', 'f'], 'C']
copy_B的值 ['A', 'B', ['d', 'e', 'f'], 'C']
lis_B的ID值 2116281195712
copy_B的ID值 2116321275968
咦,也復(fù)制出來了呀,怎么回事?別急,接著看,我們 改變一下copy_B中的 B 的值試試。
lis_B = ['A', 'B', ['d', 'e', 'f'], 'C'] # 使用copy_B復(fù)制 lis_B copy_B = copy.copy(lis_B) # 改變copy_B中的 B 的值 copy_B[1] = '改變B' # 分別打印lis_B和copy_B的值 print('lis_B的值', lis_B) print('copy_B的值', copy_B) # 打印出lis_B和copy_B的ID值 print('lis_B的ID值', id(lis_B)) print('copy_B的ID值', id(copy_B))
輸出結(jié)果:
lis_B的值 ['A', 'B', ['d', 'e', 'f'], 'C']
copy_B的值 ['A', '改變B', ['d', 'e', 'f'], 'C']
lis_B的ID值 2258614705408
copy_B的ID值 2258654720640
從上可以看出,copy_B中B的值已經(jīng)被改變了,怎么回事?要翻車了嗎?我們再改變一下copy_B中的的整個列表試試?
lis_B = ['A', 'B', ['d', 'e', 'f'], 'C'] # 使用copy_B復(fù)制 lis_B copy_B = copy.copy(lis_B) # # 改變copy_B中的 B 的值 # copy_B[1] = '改變B' # 改變lis_B中嵌套的列表 試試? copy_B[2] = ['1', '2', '3'] # 分別打印lis_B和copy_B的值 print('lis_B的值', lis_B) print('copy_B的值', copy_B) # 打印出lis_B和copy_B的ID值 print('lis_B的ID值', id(lis_B)) print('copy_B的ID值', id(copy_B))
輸出的結(jié)果是:
lis_B的值 ['A', 'B', ['d', 'e', 'f'], 'C']
copy_B的值 ['A', 'B', ['1', '2', '3'], 'C']
lis_B的ID值 1860576959872
copy_B的ID值 1860618301312
copy_B的列表也變了。在改變一下copy_B嵌套列表 [‘1’, ‘2’, ‘3’] 中的‘2’的值呢?
lis_B = ['A', 'B', ['d', 'e', 'f'], 'C'] # 使用copy_B復(fù)制 lis_B copy_B = copy.copy(lis_B) # # 改變copy_B中的 B 的值 # copy_B[1] = '改變B' # 改變lis_B中嵌套的列表 試試? copy_B[2] = ['1', '2', '3'] # 改變lis_B中嵌套的列表中的值 試試? copy_B[2][1] = '改變2' # 分別打印lis_B和copy_B的值 print('lis_B的值', lis_B) print('copy_B的值', copy_B) # 打印出lis_B和copy_B的ID值 print('lis_B的ID值', id(lis_B)) print('copy_B的ID值', id(copy_B))
輸出結(jié)果:
lis_B的值 ['A', 'B', ['d', 'e', 'f'], 'C']
copy_B的值 ['A', 'B', ['1', '改變2', '3'], 'C']
lis_B的ID值 2763457256768
copy_B的ID值 2763497140352
啊,‘2’也改變了,沒有影響lis_B的值,怎么回事啊,翻車了嗎?我們直接改變復(fù)制出來的copy_B的嵌套列表的值,不先改變嵌套列表試試呢。
lis_B = ['A', 'B', ['d', 'e', 'f'], 'C'] # 使用copy_B復(fù)制 lis_B copy_B = copy.copy(lis_B) # # 改變copy_B中的 B 的值 # copy_B[1] = '改變B' # # 改變lis_B中嵌套的列表 試試? # copy_B[2] = ['1', '2', '3'] # # 改變lis_B中嵌套的列表中的值 試試? # copy_B[2][1] = '改變2' # 直接改變copy_B的值,將上兩步注釋掉,此時copy_B = lis_B = ['A', 'B', ['d', 'e', 'f'], 'C'] copy_B[2][1] = '改變2' # 改變2 是改變 ['A', 'B', ['d', 'e', 'f'], 'C'] 中的 e # 分別打印lis_B和copy_B的值 print('lis_B的值', lis_B) print('copy_B的值', copy_B) # 打印出lis_B和copy_B的ID值 print('lis_B的ID值', id(lis_B)) print('copy_B的ID值', id(copy_B))
輸出結(jié)果:
lis_B的值 ['A', 'B', ['d', '改變2', 'f'], 'C']
copy_B的值 ['A', 'B', ['d', '改變2', 'f'], 'C']
lis_B的ID值 2342836779328
copy_B的ID值 2342878850496
神奇的一幕發(fā)生了,改變的是copy_B中的e的值,但是lis_B中e的值也發(fā)生了改變。
看懂了嗎?這就是使用copy.copy()復(fù)制嵌套列表的弊端,表面看復(fù)制了lis_B[但是有沒有完全復(fù)制 lis_B ,這種情況就要使用deepcopy()來進(jìn)行復(fù)制。
但是,為什么之前的情況.為什么能將嵌套列表[‘d’, ‘e’, ‘f’]改為[‘1’, ‘2’, ‘3’],再將[‘1’, ‘2’, ‘3’]的 ‘2’ 變?yōu)?‘改變2’呢。
(1)為什么能將 [‘A’, ‘B’, [‘d’, ‘e’, ‘f’], ‘C’] 變?yōu)?[‘A’, ‘B’, [‘1’, ‘2’, ‘3’], ‘C’]?
簡單理解,在整體改變[‘d’, ‘e’, ‘f’] 可以把他看做為一個整體,由X來代替,[‘1’, ‘2’, ‘3’]由Y來代替。所以此時的變更相當(dāng)于把[‘A’, ‘B’, X, ‘C’] 變更為 [‘A’, ‘B’, Y, ‘C’]。實際上變更的還是一維列表。copy.copy()是可以復(fù)制一維列表的。
(2)為什么 copy_B = [‘A’, ‘B’, [‘d’, ‘e’, ‘f’], ‘C’] 變?yōu)?[‘A’, ‘B’, [‘1’, ‘2’, ‘3’], ‘C’],再去變[‘1’, ‘2’, ‘3’]中的‘2’時,不會影響lis_B = [‘A’, ‘B’, [‘d’, ‘e’, ‘f’], ‘C’]?
原因是第一步將 copy_B = [‘A’, ‘B’, [‘d’, ‘e’, ‘f’], ‘C’] 變?yōu)?[‘A’, ‘B’, [‘1’, ‘2’, ‘3’], ‘C’] 此時已經(jīng)產(chǎn)生了一個新的列表 [‘A’, ‘B’, [‘1’, ‘2’, ‘3’], ‘C’] ,與列表 lis_B = [‘A’, ‘B’, [‘d’, ‘e’, ‘f’], ‘C’] 是兩個完全不相同的兩個列表。自然不回影響。
如果說有個列表 lis_C = [‘A’, ‘B’, [‘d’, ‘e’, ‘f’], [‘x’,‘y’]],先變?yōu)?[‘A’, ‘B’, [‘1’, ‘2’, ‘3’], [‘x’,‘y’]],再去改變 'x’變會對源列表產(chǎn)生影響
# 定義一個lis_C lis_C = ['A', 'B', ['d', 'e', 'f'], ['x', 'y']] # 復(fù)制一個 copy_C copy_C = copy.copy(lis_C) # copy_C = ['A', 'B', ['d', 'e', 'f'], ['x', 'y']] 變?yōu)?['A', 'B', ['1', '2', '3'], ['x', 'y']] copy_C[2] = ['1', '2', '3'] # 在來改變 ['A', 'B', ['1', '2', '3'], ['x', 'y']] 中 'x'的值 copy_C[3][0] = '改變x' # 分別打印copy_C和copy_C的值 print('lis_C的值', lis_C) print('copy_C的值', copy_C) # 打印出lis_C和copy_C的ID值 print('lis_C的ID值', id(lis_C)) print('copy_C的ID值', id(copy_C))
輸出結(jié)果:
lis_C的值 ['A', 'B', ['d', 'e', 'f'], ['改變x', 'y']]
copy_C的值 ['A', 'B', ['1', '2', '3'], ['改變x', 'y']]
lis_C的ID值 2790729135616
copy_C的ID值 2790729135424
從可以看出,copy_C 中[‘d’, ‘e’, ‘f’] 變成[ ‘1’, ‘2’, ‘3’]時,并不影響lis_C,在 將 [‘x’, ‘y’] 變?yōu)?[‘改變x’, ‘y’]時就會印象lis_C
copy.deepcopy()詳解
上面說到,在使用copy.copy()復(fù)制嵌套的二維列表[‘A’, ‘B’, [‘d’, ‘e’, ‘f’], [‘x’, ‘y’]],然后改變嵌套列表中的值是,會影響到源列表的值,那么使用copy.deepcopy()是否會影響源列表呢?
import copy # 定義一個lis_D lis_D = ['A', 'B', ['d', 'e', 'f'], ['x', 'y']] # 使用deepcopy()復(fù)制一個 copy_C copy_D = copy.deepcopy(lis_D) # 直接改變 copy_D 中嵌套列表 ['d', 'e', 'f'] 中的值d copy_D[2][0] = '改變d' # 分別打印copy_D和copy_D的值 print('lis_D的值', lis_D) print('copy_D的值', copy_D) # 打印出lis_D和copy_D的ID值 print('lis_D的ID值', id(lis_D)) print('copy_D的ID值', id(copy_D))
輸出結(jié)果:
lis_D的值 ['A', 'B', ['d', 'e', 'f'], ['x', 'y']]
copy_D的值 ['A', 'B', ['改變d', 'e', 'f'], ['x', 'y']]
lis_D的ID值 2335362856512
copy_D的ID值 2335362856320
從上述結(jié)果可以很明顯的看出,使用deepcopy()復(fù)制列表lis_之后,直接改變二維列表中的值 d,不會影響到源列表lis_D
到此這篇關(guān)于python中淺復(fù)制copy與深復(fù)制deepcopy的文章就介紹到這了,更多相關(guān)python淺復(fù)制與深復(fù)制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python Numpy:找到list中的np.nan值方法
今天小編就為大家分享一篇Python Numpy:找到list中的np.nan值方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-10-10使用Python在Excel工作表中創(chuàng)建數(shù)據(jù)透視表的方法
在數(shù)據(jù)處理和分析工作中,Excel作為一個廣泛使用的工具,提供了強大的功能來管理和解析數(shù)據(jù),當(dāng)面對大量復(fù)雜的數(shù)據(jù)集時,為了更高效地總結(jié)、分析和展示數(shù)據(jù),創(chuàng)建數(shù)據(jù)透視表成為一種不可或缺的方法,本文將介紹如何使用Python在Excel工作表中創(chuàng)建數(shù)據(jù)透視表2025-01-01Python進(jìn)程間通信 multiProcessing Queue隊列實現(xiàn)詳解
這篇文章主要介紹了python進(jìn)程間通信 mulitiProcessing Queue隊列實現(xiàn)詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-09-09Python基礎(chǔ)學(xué)習(xí)之條件控制語句小結(jié)
如果我需要設(shè)置一個死循環(huán),然后靠條件來終止,怎么辦?一個很簡單的問題,但是我卻沒有說,這一篇本應(yīng)該在分支控制語句里面的,現(xiàn)在只能拿出來水文再寫一篇了,需要的朋友可以參考下2021-05-05