Python中的淺拷貝以及深拷貝

2022-08-19 02:00:19 字數 4372 閱讀 6457

python中資料型別

不可變資料物件

不可變指的是資料儲存到記憶體後無法進行修改。

python中的不可變資料型別有:int、float、str、tuple、bool

可變資料型別

可變指的是資料儲存後可以進行修改。

python中的可變資料型別有:list、dict、set

**表示

>>>print('

修改前:')

>>>i = 1

>>>f = 5.2

>>>s = '

hello

'>>>t = (1,2,3

)>>>b =true

>>>print('

i={},id(i)={}\nf={},id(f)={}\ns={}id(s)={}\nt={},id(t)={}\nb={},id(b)={}\n

'.format(i,id(i),f,id(f),s,id(s),t,id(t),b,id(b)))

>>>print('

修改後:')

>>>i = 2

>>>f = 5.3

>>>s = '

helloworld

'>>>t = (4,5,6

)>>>b =false

>>>print('

i={},id(i)={}\nf={},id(f)={}\ns={}id(s)={}\nt={},id(t)={}\nb={},id(b)={}\n

'.format(i,id(i),f,id(f),s,id(s),t,id(t),b,id(b)))

輸出結果

修改前:

i=1,id(i)=1596320880

f=5.2,id(f)=2558329694656

s=helloid(s)=2558344746464

t=(1, 2, 3),id(t)=2558344774928

b=true,id(b)=1596063952

修改後:

i=2,id(i)=1596320912

f=5.3,id(f)=2558329694920

s=helloworldid(s)=2558340497008

t=(4, 5, 6),id(t)=2558344775000

b=false,id(b)=1596063984

結論對python中不可變資料型別進行重複賦值(修改),實際上是重新將變數名指向了新的記憶體位址。

而對於python中可變資料型別,讀者自己動手嘗試後也會發現,修改前後變數名所指向的位址是不變的,這裡不再贅述。

ps:對於除tuple外的int、float、str、bool四種資料型別,相同的值在python中記憶體的位置是相同的。

淺拷貝與深拷貝

先明確一點,這裡討論的都是基於可變資料物件的,原因見上文。

根據官方文件對於copy.copy()以及copy.deepcopy()兩個方法的描述:

深淺拷貝間的差異僅僅反應在對於復合物件的拷貝中,即包含其他物件的物件。

其次,官方對於深淺拷貝也有著描述:

淺拷貝構造了乙個新的復合物件,然後將從從原始物件中找到的引用插入到新物件中。

深拷貝則是將原始物件的副本插入到了新物件中。

簡單來說,對於復合物件而言:

淺拷貝後,改變原始物件中可變型別的資料的值,會同時影響拷貝物件

深拷貝後,改變原始物件中可變型別的資料的值,不會同時影響拷貝物件。

**表示

>>>import copy

>>>print('

修改前:')

>>> list1 = [[1,2,3],'

wx',3

]>>> list2 =list1 # 直接將原列表的引用賦值給list2

>>> list3 =list1[:] # 切片後賦值給list3,效果與淺拷貝一樣

>>> list4 =copy.copy(list1) # 淺拷貝

>>> list5 =copy.deepcopy(list1) # 深拷貝

>>>print('

list1={},id(list1)={},id(list1[0])={}\nlist2={},id(list2)={},id(list2[0])={}\nlist3={},id(list3)={},id(list3[0])={}\nlist4={},id(list4)={},id(list4[0])={}\nlist5={},id(list5)={},id(list5[0])={}\n

'.format(list1,id(list1),id(list1[0]),list2,id(list2),id(list2[0]),list3,id(list3),id(list3[0]),list4,id(list4),id(list4[0]),list5,id(list5),id(list5[0

])))

>>>print('

修改後:')

))>>> print('

list1={},id(list1)={},id(list1[0])={}\nlist2={},id(list2)={},id(list2[0])={}\nlist3={},id(list3)={},id(list3[0])={}\nlist4={},id(list4)={},id(list4[0])={}\nlist5={},id(list5)={},id(list5[0])={}\n

'.format(list1,id(list1),id(list1[0]),list2,id(list2),id(list2[0]),list3,id(list3),id(list3[0]),list4,id(list4),id(list4[0]),list5,id(list5),id(list5[0])))

輸出結果

修改前:

list1=[[1, 2, 3], 『wx』, 3],id(list1)=1778195532040,id(list1[0])=1778195665224

list2=[[1, 2, 3], 『wx』, 3],id(list2)=1778195532040,id(list2[0])=1778195665224

list3=[[1, 2, 3], 『wx』, 3],id(list3)=1778195665032,id(list3[0])=1778195665224

list4=[[1, 2, 3], 『wx』, 3],id(list4)=1778195586696,id(list4[0])=1778195665224

list5=[[1, 2, 3], 『wx』, 3],id(list5)=1778195586760,id(list5[0])=1778195586888

修改後:

list1=[[1, 2, 3, 4], 『wx』, 3, 6],id(list1)=1778195532040,id(list1[0])=1778195665224

list2=[[1, 2, 3, 4], 『wx』, 3, 6],id(list2)=1778195532040,id(list2[0])=1778195665224

list3=[[1, 2, 3, 4], 『wx』, 3],id(list3)=1778195665032,id(list3[0])=1778195665224

list4=[[1, 2, 3, 4], 『wx』, 3],id(list4)=1778195586696,id(list4[0])=1778195665224

list5=[[1, 2, 3], 『wx』, 3],id(list5)=1778195586760,id(list5[0])=1778195586888

結論ok,**很好懂,但是輸出結果較多,我們先看修改前輸出的資料,根據位址來進行判斷。

list2相當於list1的引用,所以無論是淺層資料結構(不可變資料)還是深層資料結構(可變資料)都與list1相同。

list3、list4效果一樣,均為list1的淺拷貝,兩物件的位址均不同於list1,但當涉及到深層資料結構(可變資料list1[0]為列表)時,實際還是指向了原列表list1.

list5為list1的深拷貝,可以看出無論其本身物件還是其中的深層資料結構(可變資料list1[0]為列表)都為副本。

接著是修改後輸出的資料。

list1、list2不再贅述,兩者不管誰改變,都會互相影響。

深淺拷貝後,均生成了新的物件,所以原物件中的淺層次資料結構(不可變資料)的增加減少不會影響list3、list4,但是對於深層次資料結構(可變資料list1[0]為列表)來說,新列表list3、list4中的相應元素還是指向原列表list1,所以當原列表list1中的list1[0](深層次資料結構)發生改變時,淺拷貝出的list3、list4也會受到影響(反之亦然)。

對於深拷貝生成的list5,無論時深層次還是淺層次都為原物件的副本,所以兩者不會互相影響。

簡而言之,淺拷貝更像是「藕斷絲連」式的拷貝,而深拷貝則是完完全全的「複製貼上」。

轉 Python深複製淺複製or深拷貝淺拷貝

copy.copy 淺拷貝 只拷貝父物件,不會拷貝物件的內部的子物件。copy.deepcopy 深拷貝 拷貝物件及其子物件 用乙個簡單的例子說明如下 import copy a 1,2,3,4,a b c b a c copy.copy a d copy.deepcopy a 很容易理解 a是乙個...

前端的深拷貝和淺拷貝 前端面試 深拷貝和淺拷貝

面試題目 如何實現對乙個陣列或物件的淺拷貝和深拷貝?wtf,複製還分兩種,第一次遇到這種問題的時候很是無語呢,先來看看一般的答案的理解。淺拷貝是只拷貝一層,深層次的物件級別就只拷貝引用。深拷貝是拷貝多層,每一級別的資料都拷貝出來。也就是說,基本資料型別其實不存在深淺拷貝的問題,只有物件和陣列才存在深...

vue物件深拷貝 vue陷阱 深拷貝vs淺拷貝

案例重現 看下面的乙個例子 data this.info m this.info.attr1 8 console.log m 這是vue的部分 我們猜測m會輸出什麼,你會驚奇的發現m會和this.info繫結,也就是對this.info.attr1的修改,會導致m的值變化,控制台輸出的結果是 att...