Python中copy和deepcopy的使用分析
一、定義
淺拷貝:創(chuàng)建一個新的對象,只拷貝子對象的引用(內(nèi)部的內(nèi)存地址都不相同)。這意味著,如果原對象的子對象發(fā)生變化,拷貝后的對象也會受到影響。
深拷貝:創(chuàng)建一個新的對象,并遞歸地拷貝原對象的所有子對象(內(nèi)部以及外部的內(nèi)存地址都不相同)。這意味著,即使原對象的子對象發(fā)生變化,拷貝后的對象也不會受到影響。
二、區(qū)別
淺拷貝copy:
第一種情況:復(fù)制的 對象中無 復(fù)雜 子對象,原來值的改變并不會影響淺復(fù)制的值,同時淺復(fù)制的值改變也并不會影響原來的值。原來值的id值與淺復(fù)制原來的值不同。
第二種情況:復(fù)制的對象中有 復(fù)雜 子對象 (例如列表中的一個子元素是一個列表), 改變原來的值 中的復(fù)雜子對象的值 ,會影響淺復(fù)制的值。
深拷貝deepcopy:完全復(fù)制獨立,包括內(nèi)層列表和字典。
三、代碼分析深淺拷貝
淺拷貝僅拷貝對象本身
不可變類型的淺拷貝
如果復(fù)制不可變類型的數(shù)據(jù)(字符串、數(shù)值型、布爾值),和“=”賦值情況一樣,淺拷貝的對象和原數(shù)據(jù)對象是相同的內(nèi)存地址。
import copy
a = '哈哈'
b = a
c = copy.copy(a)
print('原數(shù)據(jù)的內(nèi)存地址:', id(a))
print('淺拷貝對象的內(nèi)存地址:', id(c))
print('=賦值對象的內(nèi)存地址:', id(c))
print('\n')
可變類型的淺拷貝
情況一:不存在嵌套類型的可變類型數(shù)據(jù)(列表、字典、集合)。列表本身的淺拷貝對象的地址
原對象的地址是不同的,因為列表是可變數(shù)據(jù)類型。因此改變原對象的值并不會影響淺復(fù)制的
值。
list1 = [1, 2, 3]
list2 = copy.copy(list1)
print('原數(shù)據(jù)的內(nèi)存地址:', id(list1))
print('淺拷貝的內(nèi)存地址:', id(list2))
# 測試,修改list1對象元素的值,不會改變list2的值(相互不影響)
list1[0] = 8
print(list1)
print(list2)
情況二:如果可變類型的數(shù)據(jù)中存在嵌套的結(jié)構(gòu)。淺拷貝只復(fù)制最外層的數(shù)據(jù),導(dǎo)致內(nèi)存地址發(fā)
變化,嵌套數(shù)據(jù)的內(nèi)存地址不會變。因此改變原對象中的嵌套對象的值,會影響淺復(fù)制的值。
list3 = [1, 2, [3, 4, 5]]
list4 = copy.copy(list3)
print('原數(shù)據(jù)的內(nèi)存地址:', id(list3))
print('淺拷貝的內(nèi)存地址:', id(list4))
print('\n')
print('原數(shù)據(jù)的內(nèi)存地址:', id(list3[0]))
print('淺拷貝的內(nèi)存地址:', id(list4[0]))
print('\n')
print('原數(shù)據(jù)的內(nèi)存地址:', id(list3[2]))
print('淺拷貝的內(nèi)存地址:', id(list4[2]))
# 測試
list3[2][0] = 8 # 改變list3嵌套列表的數(shù)值,淺拷貝的值也發(fā)生變化
print(list3)
print(list4)
深拷貝完全復(fù)制獨立
不可變類型的深拷貝
number = 5
number2 = copy.deepcopy(number)
print('原數(shù)據(jù)的內(nèi)存地址:', id(number))
print('深拷貝的內(nèi)存地址:', id(number2))
可變類型的深拷貝
原對象的值和復(fù)制后的值不相互影響。
情況一:不存在嵌套類型的可變類型數(shù)據(jù)(列表、字典、集合)
list1 = [1, 2, 3]
list2 = copy.copy(list1)
list33 = copy.deepcopy(list1)
print('原數(shù)據(jù)的內(nèi)存地址:', id(list1))
print('淺拷貝的內(nèi)存地址:', id(list2))
print('深拷貝的內(nèi)存地址:', id(list33))
情況二:如果可變類型的數(shù)據(jù)中存在嵌套的結(jié)構(gòu)
list3 = [1, 2, [3, 4, 5]]
list4 = copy.copy(list3)
list55 = copy.deepcopy(list3)
print('原數(shù)據(jù)的內(nèi)存地址:', id(list3))
print('淺拷貝的內(nèi)存地址:', id(list4))
print('深拷貝的內(nèi)存地址:', id(list55))
print('\n')
print('原數(shù)據(jù)的內(nèi)存地址:', id(list3[0]))
print('淺拷貝的內(nèi)存地址:', id(list4[0]))
print('深拷貝的內(nèi)存地址:', id(list55[0]))
print('\n')
print('原數(shù)據(jù)的內(nèi)存地址:', id(list3[2]))
print('淺拷貝的內(nèi)存地址:', id(list4[2]))
print('深拷貝的內(nèi)存地址:', id(list55[2]))
四、總結(jié)
只有淺拷貝拷貝有嵌套的可變類型時,改變原對象中嵌套內(nèi)的數(shù)據(jù),拷貝對象的值也會改變,即
原對象與拷貝對象的值相互影響。
到此這篇關(guān)于Python中copy和deepcopy的使用分析的文章就介紹到這了,更多相關(guān)Python copy deepcopy內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python編寫通訊錄通過數(shù)據(jù)庫存儲實現(xiàn)模糊查詢功能
數(shù)據(jù)庫存儲通訊錄,要求按姓名/電話號碼查詢,查詢條件只有一個輸入入口,自動識別輸入的是姓名還是號碼,允許模糊查詢。這篇文章主要介紹了Python編寫通訊錄,支持模糊查詢,利用數(shù)據(jù)庫存儲,需要的朋友可以參考下2019-07-07
Python調(diào)用C語言的方法【基于ctypes模塊】
這篇文章主要介紹了Python調(diào)用C語言的方法,涉及Python基于ctypes模塊調(diào)用C語言編譯后的動態(tài)鏈接庫文件相關(guān)操作技巧,需要的朋友可以參考下2018-01-01

