学习笔记——深拷贝与浅拷贝
在平時工作中,經常涉及到數據的傳遞,在數據傳遞使用過程中,可能會發生數據被修改的問題。為了防止數據被修改,就需要在傳遞一個副本,即使副本被修改,也不會影響原數據的使用。為了生成這個副本,就產生了拷貝。
一、淺拷貝
淺復制有兩種方式:
①直接賦值:默認淺拷貝傳遞對象的引用而已,原始列表改變,被賦值的b也會做相同的改變;
②copy淺拷貝:沒有拷貝子對象,所以原始數據改變,子對象會改變。
1.1、不可變對象的拷貝
不可變對象只在修改的時候才會在內存中開辟新的空間, 而拷貝實際上是讓多個對象同時指向一個引用,和對象的賦值沒區別。
示例:
import copy a = 10 b = copy.copy(a) c = a print('id(a)=',id(a)) print('id(b)=',id(b)) print('id(c)=',id(c))結果:
id(a)= 1740485984 id(b)= 1740485984 id(c)= 1740485984a與b指向相同的引用,不可變對象的拷貝就是對象賦值。
1.2、可變對象的拷貝
通過下面這個實例可以看出:可變對象的拷貝,會在內存中開辟一個新的空間來保存拷貝的數據。當再改變之前的對象時,對拷貝之后的對象沒有任何影響。
import copy a = [1,3] b = copy.copy(a) a[0] = 2 print('a = ',a,end=' ') print('id(a) = ',id(a)) print('b = ',b,end=' ') print('id(b) = ',id(b))--------結果------------ a = [2, 3] id(a) = 2644868542984 b = [1, 3] id(b) = 2644868543048那么我們來看看用直接賦值的方式會不會和 copy 拷貝一樣,改變之前的對象時,對拷貝之后的對象沒有任何影響?
import copy a = [1,3] b = a a.append(4) print('a = ',a,end=' ') print('id(a) = ',id(a)) print('b = ',b,end=' ') print('id(b) = ',id(b))---------結果-------------- a = [1, 3, 4] id(a) = 2115236409864 b = [1, 3, 4] id(b) = 2115236409864通過觀察我們可以看到,隨著 a 原始列表改變,被賦值的b也會做相同的改變。
那么疑問來了,為什么都是淺拷貝copy 拷貝后 a 原始列表改變,被賦值的b不會變?
其實copy拷貝可以使被賦值的b改變的只是我們剛剛使用方式不對,原因:復雜對象在拷貝時,并沒有解決數據在傳遞之后,數據改變的問題。 出現這種原因,是copy() 函數在拷貝對象時,只是將指定對象中的所有引用拷貝了一份,如果這些引用當中包含了一個可變對象的話,那么數據還是會被改變。
下面來看看這個例子你就懂了:
import copy n = [4,5] a = [1,3,n] b = copy.copy(a) n[0] = 2 print('a = ',a,end=' ') print('id(a) = ',id(a)) print('b = ',b,end=' ') print('id(b) = ',id(b))--------結果--------- a = [1, 3, [2, 5]] id(a) = 2950477460040 b = [1, 3, [2, 5]] id(b) = 2950477460168二、深拷貝
區別于淺拷貝只拷貝頂層引用,深拷貝會逐層進行拷貝,直到拷貝的所有引用都是不可變引用為止。
接下來我們看看,要是將上邊的拷貝實例用使用深拷貝的話,原始數據改變的問題還會不會存在了?下面的實例清楚的告訴我們:不會
示例 1
import copy n = [4,5] a = [1,3,n] b = copy.deepcopy(a) n[0] = 2 print('a = ',a,end=' ') print('id(a) = ',id(a)) print('b = ',b,end=' ') print('id(b) = ',id(b))----------結果------------ a = [1, 3, [2, 5]] id(a) = 2196123693640 b = [1, 3, [4, 5]] id(b) = 2196123693768示例 2
import copy a = [1,3] b = copy.deepcopy(a) a[0] = 2 print('a = ',a,end=' ') print('id(a) = ',id(a)) print('b = ',b,end=' ') print('id(b) = ',id(b))----------結果------------ a = [2, 3] id(a) = 1764347359752 b = [1, 3] id(b) = 1764347359816三、查漏補缺
為什么Python默認的拷貝方式是淺拷貝?
- 時間角度:淺拷貝花費時間更少
- 空間角度:淺拷貝花費內存更少
- 效率角度:淺拷貝只拷貝頂層數據,一般情況下比深拷貝效率高。
本文知識點總結:
- 不可變對象在賦值時會開辟新空間
- 可變對象在賦值時,修改一個的值,另一個也會發生改變
- 深、淺拷貝對不可變對象拷貝時,不開辟新空間,相當于賦值操作
- 淺拷貝在拷貝時,只拷貝第一層中的引用,如果元素是可變對象,并且被修改,那么拷貝的對象也會發生變化
- 深拷貝在拷貝時,會逐層進行拷貝,直到所有的引用都是不可變對象為止。
- Python 中有多種方式實現淺拷貝,copy模塊的copy 函數 ,對象的 copy 函數 ,工廠方法,切片等。
- 大多數情況下,編寫程序時,都是使用淺拷貝,除非有特定的需求
- 淺拷貝的優點:拷貝速度快,占用空間少,拷貝效率高
總結
以上是生活随笔為你收集整理的学习笔记——深拷贝与浅拷贝的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学习笔记(三)——CSS进阶
- 下一篇: 学习笔记(四)——JavaScript(