複製須要區分,,複製的是源文件的數據,仍是指向源文件數據的地址python
1.引用 b=a時,理解爲b指向了a指向的數據,至關於引用複製app
a=[1,2] b=a #驗證複製的是數據仍是地址 #1.查看ab的地址 id(a) #2677646858824 id(b) #2677646858824
#2. a增長1個元素,查看b是否增長
a.append(3)
a #[1,2,3]
b #[1,2,3]
2. 淺拷貝--copy.copy()函數
import copy a=[1,2] b=[3,4] c=[a,b] d=copy.copy(c) #驗證問題1:d是否執行c地址 #驗證方法1 id(d) #2677647114120 id(c) #2677644514824 #驗證方法2 c.append(6) c #[[1, 2], [3, 4], 6] d #[[1, 2], [3, 4]] 結論:d沒有指向c的地址 驗證問題2:d執行a,b的地址,仍是隻是複製了a,b的值 #驗證方法1 id(d[0]) #2677647113672 id(c[0]) #2677647113672 #驗證方法2 a.append(5) c #[[1, 2, 5], [3, 4]] d #[[1, 2, 5], [3, 4]] 結論:,d中的a與c中的a,地址相同,說明d中的a,與c中的a均指向a的地址的
淺拷貝僅僅把最外面1層進行了copy,並無把裏面多層嵌套進行遞歸拷貝,裏面的仍是指向原來的地址spa
3.深拷貝 copy.deepcopy()code
import copy a=[1,2] b=[3,4] c=[a,b] d=copy.deepcopy(c) #驗證問題1:d是否執行c地址 #驗證方法1 id(d) #2677647114120 id(c) #2677644514824 #驗證方法2 c.append(6) c #[[1, 2], [3, 4], 6] d #[[1, 2], [3, 4]] 結論:d沒有指向c的地址 驗證問題2:d執行a,b的地址,仍是隻是複製了a,b的值 #驗證方法1
id(c[0]) #2677647113672 id(d[0]) #2677645539912 #驗證方法2 a.append(5) c #[[1, 2, 5], [3, 4]] d #[[1, 2], [3, 4]] 結論:,d中的a與c中的a,地址不一樣,說明d中的a是複製了a的值,並無指向a的地址
深拷貝遞歸拷貝, 多層時,每層都拷貝對象的值對象
4.深拷貝和淺拷貝的應用 blog
a=[1,2] def aa(num): num.append(3) a #[1, 2] aa(a) a #[1, 2, 3] #結論:函數傳遞的實參,必定傳遞的是引用地址,因此函數會改變原數據 #若是想不改變源數據須要複製,最好用深複製 aa(copy.deepcopy(a)) a #[1, 2]
5.注意事項遞歸
a=(1,2) b=[1,2] a1=copy.copy(a) b1=copy.copy(b) id(a) #2677645526152 id(a1) #2677645526152 id(b) #2677645754888 id(b1) #2677647113800 #結論:元組即便是1層,copy不拷貝,至關實用"=" #驗證:元組中嵌套列表是都拷貝 a=[1,2] b=(3,4,a) b1=copy.copy(b) id(b) #2677645507248 id(b1) #2677645507248 #結論是不拷貝
列表是可變的,,因此能夠copy,元祖是不可變的,copy後改變不了,因此copy先後的2個set均不能被修改,但佔用了2個空間,,沒有意義可是浪費空間,因此不能copyclass
a=(1,2) a1=copy.deepcopy(a) id(a) #2677645531976 id(a1) #2677645531976 a=[1,2] b=(3,4,a) b1=copy.deepcopy(b) id(b) #2677645547848 id(b1) #2677645507896
結論:若是copy的是對象多層嵌套中的對象都不可變,則深拷貝和淺拷貝都失效,僅僅指向引用,若是最外層不可變,內層嵌套中包含可變對象,淺拷貝不拷貝,指向引用,深拷貝進行copy import
總結論:
淺拷貝
若是最外層是list可變的,淺拷貝只拷貝最外層,內部的指向引用,若是最外層是set不可變的,不論裏面嵌套的可不可變,淺拷貝都不進行copy,只是指向引用
深拷貝
若是最外層是list可變的,深拷貝遞歸拷貝,若是最外層是set不可變的,裏面嵌套的包含可變的,深拷貝進行copy,若是裏面嵌套的也無可變的,深copy也不copy