python 深、淺拷貝,python拷貝
Python的資料結構總體分為兩類:
1、字串和數字
2、列表、元組、字典等
一、字串和數字
對於字串和數字而言,賦值(=)、淺拷貝(copy)和深拷貝(deepcopy)其實都沒有意義,因為它們都永遠指向同一個記憶體位址。
>>> import copy>>> a1 = 100>>> id(a1)1426656816 # a1的記憶體位址# 賦值>>> a2 = a1>>> id(a2)1426656816# 淺拷貝>>> a3 = copy.copy(a1)>>> id(a3)1426656816# 深拷貝>>> a4 = copy.deepcopy(a1)>>> id(a4)1426656816
二、列表、元組、字典等
對於列表、字典而言,進行賦值(=)、淺拷貝(copy)和深拷貝(deepcopy),其引起的變化是不一樣的。
2.1、賦值(=)
names = ['Angle', 'Zous', 'Athena', ['Banana', 'apple']]name2 = namesnames[1] = "Pear"print(names)print(name2)print("-----------------")names[3][1] = "Dog"print(names)print(name2)print(id(names))print(id(name2))# 輸出['Angle', 'Pear', 'Athena', ['Banana', 'apple']]['Angle', 'Pear', 'Athena', ['Banana', 'apple']]-----------------['Angle', 'Pear', 'Athena', ['Banana', 'Dog']]['Angle', 'Pear', 'Athena', ['Banana', 'Dog']]15043874065361504387406536# 可以看到names 的每一次變化,name2也會改變,因為他們的記憶體位址是一樣的
這和字串和數字是不一樣的,當我們定義 a =1 ,b = a ,改變a時,b是不會有變化的。列表和字典等會跟著變化,因為他們的記憶體位址是一樣的。
a = 1b = a a = 100print(a)print(b)# 輸出1001
2.2、淺拷貝(copy)
import copynames = ['Angle', 'Zous', 'Athena', ['Banana', 'apple']]name2 = copy.copy(names)names[1] = "宙斯"print(names, "names的記憶體位址是{}".format(id(names)))print(name2, "name2的記憶體位址是{}".format(id(name2)))#輸出['Angle', '宙斯', 'Athena', ['Banana', 'apple']] names的記憶體位址是1764417452744['Angle', 'Zous', 'Athena', ['Banana', 'apple']] name2的記憶體位址是1764416035080我們淺copy了一個name2,同時我們將names中的Zous的值改為中文,但是name2的沒有改變。因為他們的記憶體位址是不一樣的,改變其中一個不影響另外一個。
我們接下來看:
import copynames = ['Angle', 'Zous', 'Athena', ['Banana', 'apple']]name2 = copy.copy(names)names[1] = "宙斯"print(names, "names的記憶體位址是{}".format(id(names)))print(name2, "name2的記憶體位址是{}".format(id(name2)))names[3][1] = '蘋果'print(names, id(names[3]))print(name2, id(name2[3]))# 輸出['Angle', '宙斯', 'Athena', ['Banana', 'apple']] names的記憶體位址是2306153560776['Angle', 'Zous', 'Athena', ['Banana', 'apple']] name2的記憶體位址是2306152155528['Angle', '宙斯', 'Athena', ['Banana', '蘋果']] 2306153648968['Angle', 'Zous', 'Athena', ['Banana', '蘋果']] 2306153648968# 這次我們不僅改變了最外層的列表的值,還改變了列表中一個列表的值。# 這次的結果是 裡層的列表跟著做了改變
我們通過列印的記憶體位址可以明顯看出,整個外層列表的記憶體位址是不一樣的,但是裡層的列表記憶體位址是一致的。
總結:淺拷貝(copy.copy(x))只是將列表等資料類型的第一層copy了一下,記憶體位址改變了。但是對於裡層的資料類型的記憶體位址沒有改變。
2.3、深拷貝(deepcopy)
深拷貝(copy.deepcopy(x))其實就是重新開闢了一個新的記憶體位址,儲存deepcopy後的資料,和原來資料的記憶體位址完全不一樣了,包括裡層資料類型的記憶體位址。
import copynames = ['Angle', 'Zous', 'Athena', ['Banana', 'apple']]name2 = copy.deepcopy(names)names[1] = "宙斯"print(names, "names的記憶體位址是{}".format(id(names)))print(name2, "name2的記憶體位址是{}".format(id(name2)))names[3][1] = '蘋果'print(names, id(names[3]))print(name2, id(name2[3]))#輸出['Angle', '宙斯', 'Athena', ['Banana', 'apple']] names的記憶體位址是2379824216776['Angle', 'Zous', 'Athena', ['Banana', 'apple']] name2的記憶體位址是2379824217160['Angle', '宙斯', 'Athena', ['Banana', '蘋果']] 2379824304968['Angle', 'Zous', 'Athena', ['Banana', 'apple']] 2379824305032#可以看出,names不論是改變外層還是裡層列表的資料,都不會影響到name2。
: