Python 淺拷貝與深拷貝

2021-08-21 20:55:12 字數 3505 閱讀 9702

淺拷貝:構造方法或切片 [:] 做的是淺拷貝(即拷貝了最外層容器,副本中的元素是原容器中元素的引用

在 python 中,通過乙個物件向另外乙個物件賦值,實際僅僅是賦值了物件的引用,而非建立乙個物件並賦值。那如何真正拷貝物件呢?我們看一下兩種不同的拷貝方式。

先從乙個示例看起:

>>> anndy = ['anndy', ['age', 24]]

>>> tom = anndy[:]

>>> cindy = list(anndy)

>>>

>>>

print id(anndy), id(tom), id(cindy)

56466248

56466440

55883208

>>>

>>>

print [id(x) for x in anndy]

[56517256l, 56414152l]

>>>

print [id(x) for x in tom]

[56517256l, 56414152l]

>>>

print [id(x) for x in cindy]

[56517256l, 56414152l]

>>>

>>>

print anndy, tom, cindy

['anndy', ['age', 24]] ['anndy', ['age', 24]] ['anndy', ['age', 24]]

由此可見,是建立了三個不同的物件。但是事實真的是這樣嗎?讓我們修改一下名字和年齡看看。

3個物件的id56466248 56466440 55883208是不一樣的,

但是每個物件中名字和年齡的id是相同的,都是[56517256l, 56414152l]

修改名字:

>>> tom[0]="tom"

>>> cindy[0]="cindy"

>>>

print anndy, tom , cindy

['anndy', ['age', 24]] ['tom', ['age', 24]] ['cindy', ['age', 24]]

修改tom的名字沒有任何問題。

修改年齡:

修改tom的年齡為12歲

>>> tom[1][1] = 12

>>> print anndy, tom , cindy

['anndy', ['age', 12]] ['tom', ['age', 12]] ['cindy', ['age', 12]]

所有人的年齡都被修改了。這真是恐怖啊,並不是我們想要的結果。為啥會是這樣呢?列印一下列表中各個物件的id看一下:

>>> [id(x) for x in anndy]

[55599912l, 55496648l]

>>> [id(x) for x in tom]

[55581392l, 55496648l]

>>> [id(x) for x in cindy]

[55581952l, 55496648l]

可見,第二個列表的元素是相同的。這是為什麼呢?

原因就是淺拷貝

構造方法或切片 [:] 做的是淺拷貝(即拷貝了最外層容器,副本中的元素是原容器中元素的引用)。如果所有元素都是不可變的(比如名字字串,修改的時候會重新建立物件,僅僅包括原子物件的元組也屬於這種情況),那麼這樣沒有問題,還能節省記憶體。但是,如果有可變的元素,可能就會導致意想不到的問題,正如剛剛,修改乙個人的年齡,所有人的年齡都發生了變化。

那麼現在來看一下深拷貝。深拷貝,顧名思義,深層次的拷貝,不僅僅拷貝最外層容器,還會拷貝容器中的元素。這是利用copy中的deepcopy方法來實現的。

實現如下:

深拷貝

import

copy

anndy = ['anndy', ['age',24]]

tom = copy.deepcopy(anndy)

cindy = copy.deepcopy(anndy)

列印id,名字的id全是一樣的,但年齡的不一樣了

>>> 

print [id(x) for x in anndy]

[56517256l, 56414152l]

>>>

print [id(x) for x in tom]

[56517256l, 56502600l]

>>>

print [id(x) for x in cindy]

[56517256l, 56502216l]

修改名字

tom[0] = 'tom'

cindy[0] = 'cindy'

列印id;名字的id改變了,但是修改tom的名字不會影響其他人的

>>> 

print [id(x) for x in anndy]

[56517256l, 56414152l]

>>>

print [id(x) for x in tom]

[56498736l, 56502600l]

>>>

print [id(x) for x in cindy]

[56499296l, 56502216l]

>>>

print anndy, tom, cindy

['anndy', ['age', 24]] ['tom', ['age', 24]] ['cindy', ['age', 24]]

修改年齡

tom[1][1] = 12
列印id和資料;修改tom的年齡,不會影響其他人的年齡。

>>> 

print [id(x) for x in anndy]

[56517256l, 56414152l]

>>>

print [id(x) for x in tom]

[56498736l, 56502600l]

>>>

print [id(x) for x in cindy]

[56499296l, 56502216l]

>>>

print anndy, tom, cindy

['anndy', ['age', 24]] ['tom', ['age', 12]] ['cindy', ['age', 24]]

僅僅修改了tom的年齡,anndy和cindy的沒有被修改。

僅僅是tom的年齡被修改了。另外,還是需要注意一下,對於不可變的物件,比如字串,比如包括原子物件的元組,對其深拷貝不會進行

參考並感謝

Python 淺拷貝與深拷貝

以下例項是使用 copy 模組的 copy.copy 淺拷貝 和 copy.deepcopy usr bin python coding utf 8 import copy a 1,2,3,4,a b 原始物件 b a 賦值,傳物件的引用 c copy.copy a 物件拷貝,淺拷貝 d copy....

python 深拷貝與淺拷貝

當乙個變數 的時候,約定為 指向位址的過程 如果copy.copy 拷貝的是元組,那麼它不會進行淺拷貝,僅僅是指向 因為元組是不可變資料型別,那麼意味著資料一定不能修改,因此用copy.copy的 時候它會自動判斷,是指向。如果,用copy.copy copy.deepcopy 對乙個全部是不可變型...

Python深拷貝與淺拷貝

python有個內建的copy的模組專門用於處理深拷貝與淺拷貝,很實用,用起來也很方便,能為我們省去不少麻煩,不用自己再寫深拷貝或者淺拷貝物件的方法了。賦值,淺拷貝,深拷貝只針對可變變數,如list,dict,tuple python中賦值都是進行記憶體位址的傳遞 淺拷貝 copy,copy 只會賦...