最近在刷leetcode的回溯題時,涉及到列表的拷貝,在此記錄下列表拷貝的不同。
下文的例子多數借鑑於https://www.cnblogs.com/dfc001/p/11526151.html
1. 列表的賦值
賦值主要是設定了一個變量的引用,賦值主要方式是通過等於號’=’。
a = [1, 2, [3]]
b = a
b.append(4)
print(a, id(a))
print(b, id(b))
輸出結果
[1, 2, [3], 4] 4457931016
[1, 2, [3], 4] 4457931016
可以看到,在賦值列表b
以後對b
進行了更改,但是輸出卻會發現a
也會同時改變,並且a
和b
的id是一樣的,也就是說在python中對於列表的賦值,實際上是改變了原指針的指向,而並不會重新開闢新的內存空間。因此對於賦值後的列表做增刪改操作,其實就是在原列表上做。
2. 列表的淺拷貝
python列表的淺拷貝方式一般是copy()
函數和列表切片。
例1
a = [1, 2, [3]]
b = a.copy() # b = a[:]
b.append(4)
b[2].append(4)
print(a, id(a))
print(b, id(b))
輸出結果
[1, 2, [3, 4]] 4410188040
[1, 2, [3, 4], 4] 4410340104
例2
a = [[1, 3], {'a': 'b'}, 4, {4}]
b = a[:]
b[0].append(5)
b[1]['c'] = 'd'
b[3].add(10)
b[2] = 6
print(a, id(a))
print(b, id(b))
輸出結果
[[1, 3, 5], {'a': 'b', 'c': 'd'}, 4, {10, 4}] 4316430600
[[1, 3, 5], {'a': 'b', 'c': 'd'}, 6, {10, 4}] 4316582664
可以看到,淺拷貝對於列表中存在的可變對象如列表,集合,字典也是引用的原對象的地址空間,所以會一同改變。而對於列表中存在的數值型數據這些不可變對象,淺拷貝會直接創建新的地址空間用以保存。
3. 列表的深拷貝
python列表的深拷貝就只有copy.deepcopy()
一種了。
import copy
a = [1, 2, [3]]
b = copy.deepcopy(a)
b.append(4)
b[2].append(4)
print(a, id(a))
print(b, id(b))
輸出結果
[1, 2, [3]] 4545831688
[1, 2, [3, 4], 4] 4545831816
深拷貝就是新建額外的內存空間,並將原對象的值複製過去。怎樣改變都不會影響原對象的值。