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...