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-07Python調(diào)用C語言的方法【基于ctypes模塊】
這篇文章主要介紹了Python調(diào)用C語言的方法,涉及Python基于ctypes模塊調(diào)用C語言編譯后的動態(tài)鏈接庫文件相關(guān)操作技巧,需要的朋友可以參考下2018-01-01