最近面試被問(wèn)到python
中深拷貝和淺拷貝的知識(shí)
這里進(jìn)行下總結(jié)壳咕,以便今后復(fù)習(xí)
python
中的深拷貝和淺拷貝和java
里面的概念是一樣的买窟,所謂淺拷貝就是對(duì)引用的拷貝责蝠,所謂深拷貝就是對(duì)對(duì)象的資源的拷貝应民。
首先克握,對(duì)賦值操作我們要有以下認(rèn)識(shí):
- 賦值是將一個(gè)對(duì)象的地址賦值給一個(gè)變量但校,讓變量指向該地址( 舊瓶裝舊酒 )螃诅。
- 修改不可變對(duì)象(
str
、tuple
)需要開(kāi)辟新的空間 - 修改可變對(duì)象(
list
等)不需要開(kāi)辟新的空間
- 淺拷貝僅僅復(fù)制了容器中元素的地址
>>> a=['hello',[1,2,3]]
>>> b=a[:]
>>> [id(x) for x in a]
[55792504, 6444104]
>>> [id(x) for x in b]
[55792504, 6444104]
>>> a[0]='world'
>>> a[1].append(4)
>>> print(a)
['world', [1, 2, 3, 4]]
>>> print(b)
['hello', [1, 2, 3, 4]]
這里可以看出,未修改前术裸,a
和b
中元素的地址都是相同的倘是,不可變的hello
和可變的list
地址都一樣,說(shuō)明淺拷貝知識(shí)將容器內(nèi)的元素的地址復(fù)制了一份袭艺。這可以通過(guò)修改后搀崭,b
中字符串沒(méi)改變,但是list
元素隨著a
相應(yīng)改變得到驗(yàn)證猾编。
淺拷貝是在另一塊地址中創(chuàng)建一個(gè)新的變量或容器瘤睹,但是容器內(nèi)的元素的地址均是源對(duì)象的元素的地址的拷貝。也就是說(shuō)新的容器中指向了舊的元素( 新瓶裝舊酒 )答倡。
- 深拷貝轰传,完全拷貝了一個(gè)副本,容器內(nèi)部元素地址都不一樣
>>> from copy import deepcopy
>>> a=['hello',[1,2,3]]
>>> b=deepcopy(a)
>>> [id(x) for x in a]
[55792504, 55645000]
>>> [id(x) for x in b]
[55792504, 58338824]
>>> a[0]='world'
>>> a[1].append(4)
>>>
>>> print(a)
['world', [1, 2, 3, 4]]
>>> print(b)
['hello', [1, 2, 3]]
這里可以看出瘪撇,深拷貝后获茬,a
和b
的地址以及a
和b
中的元素地址均不同,這是完全拷貝的一個(gè)副本倔既,修改a
后锦茁,發(fā)現(xiàn)b
沒(méi)有發(fā)生任何改變,因?yàn)?code>b是一個(gè)完全的副本叉存,元素地址與a
均不同码俩,a
修改不影響b
。
深拷貝是在另一塊地址中創(chuàng)建一個(gè)新的變量或容器歼捏,同時(shí)容器內(nèi)的元素的地址也是新開(kāi)辟的稿存,僅僅是值相同而已,是完全的副本瞳秽。也就是說(shuō)( 新瓶裝新酒 )瓣履。