一、賦值
>>> 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...