Python賦值、淺拷貝、深拷貝的區別
阿新 • • 發佈:2018-05-27
ID IV 元素 改變 拷貝 但是 int 需要 copy
一、賦值
- str例子
>>> 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‘的不變性,不會發生改變。
- list例
>>> 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) #深拷貝
a.append(5)
a[4].append('c')
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賦值、淺拷貝、深拷貝的區別