Python - 拷贝 - 浅拷贝(Shallow Copy)和深拷贝(Deep Copy)
前言
假设我以这样的方式创建一个3 x 5
的二维数组:
a = [[0] * 5] * 3
然后我修改 a [ 2 ] [ 3 ] a[2][3] a[2][3]的值为 1 1 1:
a[2][3] = 1
结果会发现数组 a a a中第二维坐标为 3 3 3的数全部被修改为了 1 1 1,而没有发生“第一维坐标为 2 2 2的数全部被改成了 1 1 1”
print(a) # [[0, 0, 0, 1, 0], [0, 0, 0, 1, 0], [0, 0, 0, 1, 0]]
原因
这就涉及到了Python中的拷贝机制。
Python中的数据按照其是否可以更改,可以分为两类:
- 可变类型包括列表(list)、字典(dict)和集合(set)
- 不可变类型包括整数(int)、浮点数(float)、布尔值(bool)、元组(tuple)和字符串(str)
深拷贝: 对于不可变类型(例如整数)进行复制操作时,会产生一个新的对象。对新对象的更改不会对旧对象造成影响:
a = 2
b = a
b = 1
print(a, b) # 2 1
print(id(a), id(b)) # 2474931349840 2474931349808 # 不同
浅拷贝: 然而对于可变类型(例如列表)进行复制时,只会将对象的引用复制一份,它们实际指向同意对象。因此修改新的对象会对旧对象产生影响:
a = [1, 2, 3]
b = a
b[2] = 0
print(a, b) # [1, 2, 0] [1, 2, 0]
print(id(a), id(b)) # 2537310019904 2537310019904 # 相同
注意对新对象
的修改是指修改对象中的一部分,而不是让新对象指向另一个对象
a = [1, 2, 3]
b = a
b[0] = 0 # 修改对象中的一部分,这时a = [0, 2, 3]
b = [0] # b指向了一个新的对象,原来的对象并没有被修改,这时a = [0, 2, 3]
这就解释了前言中的问题:
[ 0 ] ∗ 5 [0] * 5 [0]∗5是将 0 0 0复制为5份, 0 0 0是不可变的整数,因此新列表 [ 0 , 0 , 0 , 0 , 0 ] [0, 0, 0, 0, 0] [0,0,0,0,0]中的每个 0 0 0都是独立的,修改其中一个 0 0 0不会影响到其他 0 0 0的值
但是 [ [ 0 , 0 , 0 , 0 , 0 ] ∗ 3 ] [[0, 0, 0, 0, 0] * 3] [[0,0,0,0,0]∗3]是将 [ 0 , 0 , 0 , 0 , 0 ] [0, 0, 0, 0, 0] [0,0,0,0,0]复制为5份, [ 0 , 0 , 0 , 0 , 0 ] [0, 0, 0, 0, 0] [0,0,0,0,0]是可变的列表,因此实质上是创建了 3 3 3个指向 [ 0 , 0 , 0 , 0 , 0 ] [0, 0, 0, 0, 0] [0,0,0,0,0]的对象,因此修改其中一个,另外两个也会随之变化。
但是:
a = [0] * 5
for i in range(5):
print(id(a[i]), end=' ')
# 2977374300432 2977374300432 2977374300432 2977374300432 2977374300432 # 完全相同!!!
print(id(a[0] == id(a[1]))) # True
a[0] = 1
print(a) # [1, 0, 0, 0, 0]
print(id(a[0])) # 2977374300464
print(id(a[1])) # 2977374300432
print(id(a[2])) # 2977374300432
print(id(a[0]) == id(a[1])) # False
也许是Py的优化?只有当修改不可变元素时才真的深拷贝?
TODO: import copy
可以研究一下 copy.copy()和copy.deepcopy()文章来源:https://www.toymoban.com/news/detail-402819.html
原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/129972641文章来源地址https://www.toymoban.com/news/detail-402819.html
到了这里,关于Python - 拷贝 - 浅拷贝(Shallow Copy)和深拷贝(Deep Copy)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!