Python中的賦值與深淺拷貝

2022-07-24 05:36:10 字數 3657 閱讀 9053

鑑於對很多初學程式設計的小夥伴來說,對於賦值和深淺拷貝的用法有些疑問,所以我就結合python變數儲存的特性從記憶體的角度來談一談賦值和深淺拷貝~~~

一些基本的定義:

幾個術語的解釋

深淺拷貝的作用

對於不可變物件的深淺拷貝

不可變物件型別(這個不可變物件型別裡面不能包含可變物件型別,如元祖裡面包含列表就不滿足這個條件),沒有被拷貝的說法,即便是用深拷貝,檢視id的話也是一樣的,如果對其重新賦值,也只是新建立乙個物件,替換掉舊的而已。一句話就是,不可變型別,不管是深拷貝還是淺拷貝,位址值和拷貝後的值都是一樣的。

舉個栗子:

n1 = 123123n2 =n1

print

(n1,n2)

print

(id(n1))

print

(id(n2))

輸出結果:

123123 123123

1607915318992

1607915318992

在以上**塊當中,a2與a1所賦的值是一樣的,都是數字123123。因為python有乙個重用機制,對於同乙個數字,python並不會開闢一塊新的記憶體空間,而是維護同一塊記憶體位址,只是將該數字對應的記憶體位址的引用賦值給變數a1和a2。所以根據輸出結果,a1和a2其實對應的是同一塊記憶體位址,只是兩個不同的引用罷了。同樣的,對於a2 = a1,其實效果等同於「a1 = 123123; a2 = 123123」,它也就是將a1指向123123的引用賦值給a2。字串跟數字的原理雷同,如果把123123改成「abcabc」也是一樣的。

同樣的栗子:

import copy  #

使用淺拷貝需要匯入copy模組

n1 = 123123n3 = copy.copy(n1) #

使用copy模組裡的copy()函式就是淺拷貝了

print

(n1,n3)

print

(id(n1))

print

(id(n3))

輸出結果:

123123 123123

2735567515344

2735567515344

通過使用copy模組裡的copy()函式來進行淺拷貝,把a1拷貝乙份賦值給a3,檢視輸出結果發現,a1和a3的記憶體位址還是一樣。

再來乙個栗子:

import

copy

n1 = 123123n4 = copy.deepcopy(n1) #

深拷貝是用copy模組裡的deepcopy()函式

print

(n1,n4)

print

(id(n1))

print

(id(n4))

輸出結果:

123123 123123

2545114525392

2545114525392

這個。。。還用說嘛,直接看結論》

原理圖:

再舉個栗子

n1 = 

n2 = n1 #

賦值print

(n1,n2)

print

(id(n1))

print

(id(n2))

n1['

k1'] = 'c'

n1['

k3'][0] = 'd'

print

(n1,n2)

print

(id(n1))

print

(id(n2))

輸出結果:

1867471875528

1867471875528

1867471875528

1867471875528

我們的栗子當中用了乙個字典n1,字典裡面巢狀了乙個列表,當我們把n1賦值給n2時,記憶體位址並沒有發生變化,因為其實它也是只是把n1的引用拿過來賦值給n2而已(我們用了乙個字典來舉例,其他型別也是一樣的)。正因為如此,當我們修改字典裡面的資料時,n1和n2都會發生改變。

栗子走起

import

copy

n1 =

n3 = copy.copy(n1) #

淺拷貝print

(n1,n3)

print("")

print

(id(n1))

print

(id(n3))

print("")

print(id(n1["k3"

]))print(id(n3["k3"

]))n1['k1

'] = '

tom'

n1['

k3'][0] = '

jack

'print('

***************')

print

(n1,n3)

輸出結果:

栗子:

import

copy

n1 =

n4 = copy.deepcopy(n1) #

深拷貝print("")

print

(id(n1))

print

(id(n4))

print("")

print(id(n1["k3"

]))print(id(n4["k3"

]))n1['k1

'] = '

tom'

n1['

k3'][0] = '

jack

'print

(n1,n4)

通過以上結果發現,進行深拷貝時,字典裡面的第一層和裡面巢狀的位址都已經變了。對於深拷貝,它會拷貝多層,將第二層的列表也拷貝乙份,如果還有第三層巢狀,那麼第三層的也會拷貝,但是對於裡面的最小元素,比如數字和字串,這裡就是「wu」,123,「alex」,678之類的,按照python的機制,它們會共同指向同乙個位置,它的記憶體位址是不會變的。原理如下圖:

對於元祖來說,如果他裡面的元素都是不可變型別的元素,那麼不論是賦值,淺拷貝還是深拷貝,他們的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...