1. 程式人生 > 其它 >python 直接賦值 深拷貝 淺拷貝

python 直接賦值 深拷貝 淺拷貝

目錄
python中的深拷貝與淺拷貝與C&C++中略有不同,後者主要是對於指標指向記憶體空間的重新開闢,否則兩個指標會共享一塊記憶體,而python中是三種不同層次的共享。其中直接複製是用 = ,淺拷貝和深拷貝則要使用copy模組實現。

直接賦值

d = {'country':'China', 'age': '18', 'name': 'Kang'}

a = d
print(a, d)
d['age'] = 100
print(a, d)
d['like'] = 'pingpong'
print(a, d)

輸出:

{'country': 'China', 'age': '18', 'name': 'Kang'} {'country': 'China', 'age': '18', 'name': 'Kang'}
{'country': 'China', 'age': 100, 'name': 'Kang'} {'country': 'China', 'age': 100, 'name': 'Kang'}
{'country': 'China', 'age': 100, 'name': 'Kang', 'like': 'pingpong'} {'country': 'China', 'age': 100, 'name': 'Kang', 'like': 'pingpong'}

直接賦值的時候 a與d完全相同,類似C中的引用概念,是一個物件的兩個別名,因此無論是改變d中原有元素還是給d新增新的元素,a都是隨之改變。

淺拷貝

直接賦值是兩個物件完全共享,淺拷貝則是共享拷貝時候已有的元素,對於新增的新元素則不共享。

import copy

d = {'country':'China', 'age': '18', 'name': 'Kang'}

a = copy.copy(d)
print(a, d)
d['age'] = 100
print(a, d)
d['like'] = 'pingpong'
print(a, d)

輸出:

{'country': 'China', 'age': '18', 'name': 'Kang'} {'country': 'China', 'age': '18', 'name': 'Kang'}
{'country': 'China', 'age': '18', 'name': 'Kang'} {'country': 'China', 'age': 100, 'name': 'Kang'}
{'country': 'China', 'age': '18', 'name': 'Kang'} {'country': 'China', 'age': 100, 'name': 'Kang', 'like': 'pingpong'}

嗯,第三行是對的,對於新新增的元素不會共享。但本來以為改變原字典d的age的值,a會跟著改變的,畢竟age是共享時已有的元素嘛,但這裡發現好像打臉了,第二行輸出d的age改變而a沒有改變,這是因為字典的值更改了以後就相當於一個新的元素了。以下小實驗可驗證:

d = {'age': 18}
print(id(d['age']))
d['age'] = 10000
print(id(d['age']))

輸出為:

93899669444160
139985819449552

可以認為id()函式輸出物件的地址,可以看到這裡地址已經改變了,所以d的age鍵值對改變前後是兩個元素。
即,淺拷貝時子元素共享是對的,但是要注意改變子元素時有沒有改變其地址,把原本共享的子元素物件直接改成另一個物件,那肯定不再共享了。

深拷貝

a = copy.deepcopy(d)

這種情況下a和d完全不相關,不存在任何共享。