最近在刷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
深拷贝就是新建额外的内存空间,并将原对象的值复制过去。怎样改变都不会影响原对象的值。