鑑於對很多初學程式設計的小夥伴來說,對於賦值和深淺拷貝的用法有些疑問,所以我就結合python變數儲存的特性從記憶體的角度來談一談賦值和深淺拷貝~~~
一些基本的定義:
幾個術語的解釋
深淺拷貝的作用
對於不可變物件的深淺拷貝
不可變物件型別(這個不可變物件型別裡面不能包含可變物件型別,如元祖裡面包含列表就不滿足這個條件),沒有被拷貝的說法,即便是用深拷貝,檢視id的話也是一樣的,如果對其重新賦值,也只是新建立乙個物件,替換掉舊的而已。一句話就是,不可變型別,不管是深拷貝還是淺拷貝,位址值和拷貝後的值都是一樣的。
舉個栗子:
n1 = 123123n2 =n1在以上**塊當中,a2與a1所賦的值是一樣的,都是數字123123。因為python有乙個重用機制,對於同乙個數字,python並不會開闢一塊新的記憶體空間,而是維護同一塊記憶體位址,只是將該數字對應的記憶體位址的引用賦值給變數a1和a2。所以根據輸出結果,a1和a2其實對應的是同一塊記憶體位址,只是兩個不同的引用罷了。同樣的,對於a2 = a1,其實效果等同於「a1 = 123123; a2 = 123123」,它也就是將a1指向123123的引用賦值給a2。字串跟數字的原理雷同,如果把123123改成「abcabc」也是一樣的。(n1,n2)
(id(n1))
(id(n2))
輸出結果:
123123 123123
1607915318992
1607915318992
同樣的栗子:
import copy #通過使用copy模組裡的copy()函式來進行淺拷貝,把a1拷貝乙份賦值給a3,檢視輸出結果發現,a1和a3的記憶體位址還是一樣。使用淺拷貝需要匯入copy模組
n1 = 123123n3 = copy.copy(n1) #
使用copy模組裡的copy()函式就是淺拷貝了
(n1,n3)
(id(n1))
(id(n3))
輸出結果:
123123 123123
2735567515344
2735567515344
再來乙個栗子:
import這個。。。還用說嘛,直接看結論》copy
n1 = 123123n4 = copy.deepcopy(n1) #
深拷貝是用copy模組裡的deepcopy()函式
(n1,n4)
(id(n1))
(id(n4))
輸出結果:
123123 123123
2545114525392
2545114525392
原理圖:
再舉個栗子
n1 =1867471875528n2 = n1 #
賦值print
(n1,n2)
(id(n1))
(id(n2))
n1['
k1'] = 'c'
n1['
k3'][0] = 'd'
(n1,n2)
(id(n1))
(id(n2))
輸出結果:
1867471875528
1867471875528
1867471875528
我們的栗子當中用了乙個字典n1,字典裡面巢狀了乙個列表,當我們把n1賦值給n2時,記憶體位址並沒有發生變化,因為其實它也是只是把n1的引用拿過來賦值給n2而已(我們用了乙個字典來舉例,其他型別也是一樣的)。正因為如此,當我們修改字典裡面的資料時,n1和n2都會發生改變。栗子走起
importcopy
n1 =
n3 = copy.copy(n1) #
淺拷貝print
(n1,n3)
print("")
(id(n1))
(id(n3))
print("")
print(id(n1["k3"
]))print(id(n3["k3"
]))n1['k1
'] = '
tom'
n1['
k3'][0] = '
jack
'print('
***************')
(n1,n3)
輸出結果:
栗子:
import通過以上結果發現,進行深拷貝時,字典裡面的第一層和裡面巢狀的位址都已經變了。對於深拷貝,它會拷貝多層,將第二層的列表也拷貝乙份,如果還有第三層巢狀,那麼第三層的也會拷貝,但是對於裡面的最小元素,比如數字和字串,這裡就是「wu」,123,「alex」,678之類的,按照python的機制,它們會共同指向同乙個位置,它的記憶體位址是不會變的。原理如下圖:copy
n1 =
n4 = copy.deepcopy(n1) #
深拷貝print("")
(id(n1))
(id(n4))
print("")
print(id(n1["k3"
]))print(id(n4["k3"
]))n1['k1
'] = '
tom'
n1['
k3'][0] = '
jack
(n1,n4)
對於元祖來說,如果他裡面的元素都是不可變型別的元素,那麼不論是賦值,淺拷貝還是深拷貝,他們的id都是一樣的(不僅整個元祖的id是一樣的,裡面每乙個元素的id都是一樣的)。但是如果元祖裡面的元素有可變元素,如列表字典等,那麼對於賦值和淺拷貝來說,id仍然還是一樣的(不僅整個元祖的id是一樣的,裡面每乙個元素的id都是一樣的);對於深拷貝來說,元祖的id和列表字典的id是不一樣的,但是對於最底層的數字,字串位址還是一樣的。
python中的深淺拷貝與賦值。
賦值 賦值就是乙個變數引用乙個變數的值。這兩個變數共用乙個記憶體位址。當使用可變資料結構時 如 list,dict,set 其中乙個變數的值改變,會使另乙個變數的值也發生改變,但記憶體位址不改變。a 1 2,3 b ab 1 4print id a a,id b b 1992269718152 1,...
python中的賦值與深淺拷貝
在python中,只有在int和字串,元組等不可變型別中,與深淺拷貝的結果一樣 因為其是不可變型別,都是連記憶體位址一起 複製 了。而在list,dict,set中,深淺拷貝並沒有複製 位址 複製 記憶體位址的結果就是,之後的操作會影響原來的物件。以下所有的內容都是基於記憶體位址來說的。1.int型...
python中的賦值與深淺拷貝
python當中對於拷貝,分為兩種型別。一種是數字和字串,另一種就是列表 元組 字典等其他型別了。舉個栗子 a1 123123 a2 123123 a2 a1 賦值 print id a1 通過id 函式來列印變數在記憶體當中的位址 print id a2 輸出結果是 1959780298352 1...