淺拷貝:構造方法或切片 [:] 做的是淺拷貝(即拷貝了最外層容器,副本中的元素是原容器中元素的引用
)
在 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 只會賦...