Python對(duì)象的深拷貝和淺拷貝詳解
本文內(nèi)容是在《Python核心編程2》上看到的,感覺(jué)很有用便寫(xiě)出來(lái),給大家參考參考!
淺拷貝
首先我們使用兩種方式來(lái)拷貝對(duì)象,一種是切片,另外一種是工廠方法。然后使用id函數(shù)來(lái)看看它們的標(biāo)示符
# encoding=UTF-8
obj = ['name',['age',18]]
a=obj[:]
b=list(obj)
for x in obj,a,b:
print id(x)
35217032
35227912
29943304
他們的id都不同,按照正常的判斷,三個(gè)不同id的對(duì)象應(yīng)該都是獨(dú)立的。那么我們先給他們改改名看看
# encoding=UTF-8
obj = ['name',['age',18]]
a=obj[:]
b=list(obj)
for x in obj,a,b:
print id(x)
a[0] = 'lisi'
b[0] = 'zhangsan'
print a
print b
35217032
35227912
33547784
['lisi', ['age', 18]]
['zhangsan', ['age', 18]]
對(duì)象a與b分別賦予了不同的名字,下來(lái)我們來(lái)看看給a對(duì)象改一個(gè)年齡
# encoding=UTF-8
obj = ['name',['age',18]]
a=obj[:]
b=list(obj)
for x in obj,a,b:
print id(x)
a[0] = 'lisi'
b[0] = 'zhangsan'
print a
print b
a[1][1] = 25
print a
print b
35217032
35227912
29943304
['lisi', ['age', 18]]
['zhangsan', ['age', 18]]
['lisi', ['age', 25]]
['zhangsan', ['age', 25]]
細(xì)心的朋友應(yīng)該看出來(lái)了,改變a[0]元素與b[0]元素都互不影響,為何改變a[1][1]的元素會(huì)影響b[1][1]的元素呢?
要解開(kāi)這個(gè)問(wèn)題,只有先了解深拷貝與淺拷貝。以上實(shí)例中,我們創(chuàng)建的a與b都是從obj對(duì)象的淺拷貝,obj中第一個(gè)元素是字符串屬于不可變類(lèi)型,第二個(gè)元素是列表屬于可變類(lèi)型。因此我們進(jìn)行拷貝對(duì)象時(shí),字符串被顯示拷貝重新創(chuàng)建了一個(gè)字符串,而列表只是復(fù)制引用,所以改變列表的元素會(huì)影響所有引用對(duì)象。從下列的id值中,你就能看明白了
# encoding=UTF-8
obj = ['name',['age',18]]
a=obj[:]
b=list(obj)
for x in obj,a,b:
print id(x[0]),id(x[1])
a[0] = 'lisi'
b[0] = 'zhangsan'
for x in obj,a,b:
print id(x[0]),id(x[1])
a[1][1] = 25
b[1][1] = 30
for x in obj,a,b:
print id(x[0]),id(x[1])
32564088 34496008
32564088 34496008
32564088 34496008
32564088 34496008
34574704 34496008
33970672 34496008
32564088 34496008
34574704 34496008
33970672 34496008
復(fù)制對(duì)象的時(shí)候,我們可以看到所有元素的id都一直,我們分別改變了a與b對(duì)象的第一個(gè)字符串元素,因?yàn)樽址遣豢勺儗?duì)象,所以改變后等于新創(chuàng)建,于是a與b的第一個(gè)字符串元素id不一致。而a與b的第二個(gè)元素都是列表可變對(duì)象,所以無(wú)論修改任何一個(gè)id值都表示一個(gè)指針,始終影響其它引用對(duì)象的值。
因此也就為什么修改a對(duì)象的年齡會(huì)影響b對(duì)象的年齡值,或者修改b對(duì)象的年齡值也會(huì)影響a對(duì)象的年齡值,包括obj對(duì)象在內(nèi)。
深拷貝
以上都是淺拷貝,那么我們希望拷貝的對(duì)象是獨(dú)立的,修改時(shí)不要影響其它值,這種我們稱(chēng)為深拷貝。實(shí)現(xiàn)深拷貝我們需要引用一個(gè)copy模塊,copy模塊有兩個(gè)函數(shù)可用,一個(gè)是copy淺拷貝;另一個(gè)是deepcopy深拷貝。
# encoding=UTF-8
import copy
obj = ['name',['age',18]]
a=copy.deepcopy(obj)
b=copy.deepcopy(obj)
for x in a,b:
print id(x[0]),id(x[1])
a[1][1] = 25
b[1][1] = 30
print a
print b
33612664 35477256
33612664 35477640
['name', ['age', 25]]
['name', ['age', 30]]
使用深拷貝后,列表元素的id不一致,表示獨(dú)立對(duì)象,修改任何一個(gè)列表元素的值都不會(huì)影響其它對(duì)象。
以下是幾點(diǎn)拷貝操作的注意事項(xiàng):
第一、非容器類(lèi)型(比如數(shù)字、字符串和其它“院子”類(lèi)型的對(duì)象,像代碼、類(lèi)型和range對(duì)象等)沒(méi)有被拷貝一說(shuō),淺拷貝是用完全切片操作來(lái)完成。
第二、如果元祖變量只包含原子類(lèi)型對(duì)象,對(duì)它的深拷貝將不會(huì)進(jìn)行。
我們把上面的例子改成元祖,然后使用深拷貝試試
# encoding=UTF-8
import copy
obj = ['name',('age',18)]
a=copy.deepcopy(obj)
b=copy.deepcopy(obj)
for x in a,b:
print id(x),id(x[1])
34703752 34693000
34756616 34693000
相關(guān)文章
Python實(shí)現(xiàn)將Excel內(nèi)容批量導(dǎo)出為PDF文件
這篇文章主要為大家介紹了如何利用Python實(shí)現(xiàn)將Excel表格內(nèi)容批量導(dǎo)出為PDF文件,文中的實(shí)現(xiàn)步驟講解詳細(xì),感興趣的小伙伴可以了解一下2022-04-04Python socket實(shí)現(xiàn)的簡(jiǎn)單通信功能示例
這篇文章主要介紹了Python socket實(shí)現(xiàn)的簡(jiǎn)單通信功能,結(jié)合實(shí)例形式分析了Python socket通信的相關(guān)概念、原理、客戶(hù)端與服務(wù)器端實(shí)現(xiàn)技巧以及socketserver模塊多并發(fā)簡(jiǎn)單實(shí)現(xiàn)方法,需要的朋友可以參考下2018-08-08python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5布局控件QHBoxLayout詳細(xì)使用方法與實(shí)例
這篇文章主要介紹了python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5布局控件QHBoxLayout詳細(xì)使用方法與實(shí)例,需要的朋友可以參考下2020-03-03Python利用多進(jìn)程將大量數(shù)據(jù)放入有限內(nèi)存的教程
這篇文章主要介紹了Python利用多進(jìn)程將大量數(shù)據(jù)放入有限內(nèi)存的教程,使用了multiprocessing和pandas來(lái)加速內(nèi)存中的操作,需要的朋友可以參考下2015-04-04python實(shí)現(xiàn)自動(dòng)搶課腳本的示例代碼
本文主要介紹了python實(shí)現(xiàn)自動(dòng)搶課腳本的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12詳解多線程Django程序耗盡數(shù)據(jù)庫(kù)連接的問(wèn)題
這篇文章主要介紹了多線程Django程序耗盡數(shù)據(jù)庫(kù)連接的問(wèn)題,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-10-10pandas DataFrame索引行列的實(shí)現(xiàn)
這篇文章主要介紹了pandas DataFrame索引行列的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06