別再弄不清Python 深拷貝和淺拷貝了!

一、結(jié)論
首先說(shuō)結(jié)論:深拷貝出來(lái)的對(duì)象就是完完全全的新對(duì)象,不管是對(duì)象本身(id),還是對(duì)象中包含的子對(duì)象,都和原始對(duì)象不一樣;
淺拷貝出來(lái)的對(duì)象就是外新內(nèi)舊的對(duì)象,對(duì)象本身(id)和原始對(duì)象完全不同,但是子對(duì)象和原始對(duì)象的子對(duì)象是一樣的。
再補(bǔ)充說(shuō)下賦值,賦值來(lái)的對(duì)象就是完完全全的原始對(duì)象,只是叫的名字不同了。
二、用實(shí)際例子聊聊
深拷貝是將對(duì)象本身(A)復(fù)制給另一個(gè)對(duì)象(B)。這意味著如果對(duì)對(duì)象本身或者子對(duì)象進(jìn)行更改時(shí)不會(huì)影響原對(duì)象。在 Python 中,我們使用 deepcopy()函數(shù)進(jìn)行深拷貝。
淺拷貝是將對(duì)象的引用復(fù)制給另一個(gè)對(duì)象。因此,如果我們?cè)谧訉?duì)象中進(jìn)行更改,則會(huì)影響原對(duì)象;但對(duì)對(duì)象本身修改并不會(huì)影響原始對(duì)象。使用 copy()函數(shù)進(jìn)行淺拷貝。
接下來(lái)用實(shí)際代碼給大家演示下(注意下代碼里的注釋和輸出結(jié)果):
import?copy
a?=?[1,?2,?3,?['a',?'b']]??#原始對(duì)象
b?=?a??#賦值,傳對(duì)象的引用
c?=?copy.copy(a)??#對(duì)象拷貝,淺拷貝
d?=?copy.deepcopy(a)??#對(duì)象拷貝,深拷貝
a.append(4)??#修改對(duì)象a
a[3].append('c')??#修改對(duì)象a中的['a',?'b']
print('a?=?',?a)
print('b?=?',?b)
print('c?=?',?c)
print('d?=?',?d)
a為原始對(duì)象,包含了四個(gè)元素,三個(gè)int和一個(gè)list;b為直接(a)賦值來(lái)的結(jié)果,c為淺拷貝(a)來(lái)的結(jié)果,d為深拷貝(a)來(lái)的結(jié)果。
然后我們對(duì)a列表進(jìn)行了修改,首先添加了一個(gè)int數(shù)據(jù)(4),然后對(duì)a的第四個(gè)元素(list)進(jìn)行了修改,給第四個(gè)元素列表添加了一個(gè)新元素‘c’,然后我們依次輸出a、b、c、d。
通過(guò)輸出結(jié)果我們可以發(fā)現(xiàn)直接賦值來(lái)的b和a是完全一樣的,同步修改了所有,說(shuō)明直接賦值來(lái)的新變量,不管是對(duì)象本身,還是對(duì)象中包含的子對(duì)象,都是一樣的、完全相同;
通過(guò)淺拷貝來(lái)的對(duì)象c只是子對(duì)象的修改和a保持了一致,對(duì)象本身的修改并沒(méi)有生效,說(shuō)明淺拷貝是將對(duì)象本身的引用復(fù)制給新對(duì)象,但是包含的子對(duì)象還是和之前一致的;
最后通過(guò)深拷貝來(lái)的對(duì)象完全沒(méi)有變化,說(shuō)明深拷貝來(lái)的對(duì)象本身以及包含的子對(duì)象都完完全全是新的,和原對(duì)象沒(méi)有一點(diǎn)關(guān)系。
接下來(lái)為我們進(jìn)一步看看,這幾個(gè)對(duì)象本身的id,以及對(duì)象中第四個(gè)元素的id,也可以很好的印證我們上面的結(jié)論。
# a b是完全一樣的對(duì)象;a c d 是不同的對(duì)象
print('id(a)?=?',?id(a))
print('id(b)?=?',?id(b))
print('id(c)?=?',?id(c))
print('id(d)?=?',?id(d))

#?a?c?內(nèi)的元素是一個(gè)對(duì)象?a?d?內(nèi)元素也不是同一個(gè)對(duì)象
print('id(a[3])?=?',?id(a[3]))
print('id(c[3])?=?',?id(c[3]))
print('id(d[3])?=?',?id(d[3]))

三、應(yīng)用場(chǎng)景
那么深拷貝和淺拷貝一般引用在那些地方呢?
從數(shù)據(jù)處理的角度來(lái)看,可以應(yīng)用在以下場(chǎng)景:
1)我們處理中間結(jié)果時(shí)往往不想對(duì)原始數(shù)據(jù)進(jìn)行修改,所以這個(gè)時(shí)候可以使用深拷貝;
2)如果我們只是想新增一個(gè)輔助列(只涉及對(duì)父對(duì)象的修改),那這時(shí)我們可以使用淺拷貝,節(jié)約系統(tǒng)內(nèi)存。
希望本文對(duì)你理解深拷貝與淺拷貝有所幫助。
點(diǎn)贊+留言+轉(zhuǎn)發(fā),就是對(duì)我最大的支持啦~好了,今天的學(xué)習(xí)就到這里,如果大家希望深度學(xué)習(xí)的話,可以加入我的社群,與900多位同學(xué)一起學(xué)習(xí);我是濤哥,我決定干一件大事:做最專業(yè)的Python社群!
往期文章將偷懶進(jìn)行到底,實(shí)現(xiàn)雙擊直接打開(kāi).ipynb文件怎么自學(xué)Python,大概要多久?思路推薦Python?制作國(guó)際空間站實(shí)時(shí)跟蹤器
