Python賦值 淺拷貝 深拷貝的區別

2022-09-04 17:54:14 字數 1739 閱讀 1980

一、賦值

>>> a = 'hello'

>>> b = 'hello'

>>> c = a

>>> [id(x) for x in (a,b,c)]

[42654216, 42654216, 42654216]

a,b,c三者位址一樣,相當於a=b=c。賦值系統先給變數或物件(這裡的hello)分配了記憶體,然後將位址賦給a,b,c。所以他們的位址是相同的。

>>> a = 'world'

>>> [id(x) for x in (a,b,c)]

[42654384, 42654216, 42654216]

>>> print(a,b,c)

world hello hello

這時只有a的位址和值變了,但是b,c位址和值都沒有變。因為str的不可變性,a要重新賦值則需重新開闢記憶體空間,所以a的值改變,a指向的位址改變。b, c由於'hello'的不變性,不會發生改變。

>>> a = ['hello']

>>> b = ['hello']

>>> c = a

>>> [id(x) for x in (a,b,c)]

[42670920, 42671816, 42670920]

但是這種情況卻不一樣了,a和b的位址不同。為何?

因為str是不可變的,所以同樣是'hello'只有乙個位址,但是list是可變的,所以必須分配兩個位址。

>>> a[0] = 'world'

>>> [id(x) for x in (a,b,c)]

[42670920, 42671816, 42670920]

>>> print(a,b,c)

['world'] ['hello'] ['world']

這時a,c的值和位址均改變,但二者仍相同,b不改變。由於list的可變性,所以修改list的值不需要另外開闢空間,只需修改原位址的值。所以a,c均改變。

二、淺拷貝與深拷貝

import copy

a = [1,2,3,4,['a','b']] #原始物件

b = a #賦值

c = copy.copy(a) #淺拷貝

d = copy.deepcopy(a) #深拷貝

print('a = ',a)

print('b = ',b)

print('c = ',c)

print('d = ',d)

a =  [1, 2, 3, 4, ['a', 'b', 'c'], 5]

b = [1, 2, 3, 4, ['a', 'b', 'c'], 5]

c = [1, 2, 3, 4, ['a', 'b', 'c']]

d = [1, 2, 3, 4, ['a', 'b']]

copy.copy 淺拷貝 只拷貝父物件,不會拷貝物件的內部的子物件。

copy.deepcopy 深拷貝 拷貝物件及其子物件

總結:賦值是將乙個物件的位址賦值給乙個變數,讓變數指向該位址( 舊瓶裝舊酒 )。

淺拷貝是在另一塊位址中建立乙個新的變數或容器,但是容器內的元素的位址均是源物件的元素的位址的拷貝。也就是說新的容器中指向了舊的元素( 新瓶裝舊酒 )。

深拷貝是在另一塊位址中建立乙個新的變數或容器,同時容器內的元素的位址也是新開闢的,僅僅是值相同而已,是完全的副本。也就是說( 新瓶裝新酒 )。

Python 賦值 淺拷貝 深拷貝

賦值 a b,只拷貝了物件的引用,沒有拷貝內容。兩個物件的id一樣 淺拷貝 copy.copy 構造乙個新的復合物件,然後將子物件引用插入到原始物件的副本中。深拷貝 copy.deepcopy 構造乙個新的復合物件,然後遞迴地將子物件副本插入原始物件的副本。給個栗子 從這個栗子可以看出,對c進行修改...

python賦值 淺拷貝 深拷貝

視覺化 首先了解知識點 可變 list,dict 和不可變 string,int,tuple 淺拷貝 對於string int來說沒有意義,因為它們資料就一層,對於tuple由於是不可變型別所以新的物件會指向原來的物件位址,對於list和dict,新的物件會在記憶體中開闢乙個新的記憶體空間,並且只拷...

淺拷貝 深拷貝和淺賦值 深賦值

include includeusing namespace std class string else 淺拷貝 也就是系統預設的拷貝,可寫可不寫。string const string s 預設的拷貝構造 深拷貝 string const string s string s2 s1 深賦值 str...