在 Python 中,会存在如下情况:
- 例如复制语句:
b = a,只是让b指向和a一样的对象。- 如果
a和b指向的是一个可变对象,那通过修改b后,再通过a访问到的数据也是变化后的。
但是,很多时候,我们不希望是这样的,而是希望a和b修改任何一个,都不影响彼此,此时就需要用到拷贝。
在如下代码中:nums2 = nums1不是复制,是两个变量指向同一个列表,并且修改任何一个,都会影响另一个。
nums1 = [10, 20, 30, 40]
nums2 = nums1
nums2[3] = 90
print(nums1) # [10, 20, 30, 90]
print(nums2) # [10, 20, 30, 90]
# 打印内存地址: 2346908951744 2346908951744 True 它们的内存地址是同一个地址
print(id(nums1), id(nums2), id(nums1) == id(nums2))
浅拷贝会创建一个新的外层容器,但内部的元素仍然引用原来的对象。请看下面的测试代码:
import copy
nums3 = [10, 20, 30, 40]
nums4 = copy.copy(nums3)
nums4[3] = 90
print(nums3) # [10, 20, 30, 40]
print(nums4) # [10, 20, 30, 90]
# 打印内存地址:2032469602560 2032470409088 False 它们的内存地址不是同一个地址了
print(id(nums3), id(nums4), id(nums3) == id(nums4))
浅拷贝存在的问题是:嵌套数据仍然是共享的,修改嵌套数据会相互影响。测试代码如下:
import copy
nums5 = [10, 20, 30, [40, 50]]
nums6 = copy.copy(nums5)
nums6[2] = 300
nums6[3][1] = 90
print(nums5) # [10, 20, 30, [40, 90]]
print(nums6) # [10, 20, 300, [40, 90]]
# 打印内存地址:2032469602560 2032470409088 False 它们的内存地址不是同一个地址了,但是嵌套的数据还是影响了
print(id(nums5), id(nums6), id(nums6) == id(nums5))
如何解决这个问题呢?请看下面的深拷贝。
创建一个新的外层容器,同时对内部所有【可变对象】进行递归复制(不可变对象不复制,继续引用)。
import copy
nums7 = [10, 20, 30, [40, 50]]
nums8 = copy.deepcopy(nums7)
nums8[2] = 300
nums8[3][1] = 90
print(nums7) # [10, 20, 30, [40, 50]]
print(nums8) # [10, 20, 300, [40, 90]]
# 打印内存地址:2383166804288 2383166804352 False 它们的内存地址不是同一个地址了,但是嵌套的数据也不影响
print(id(nums7), id(nums8), id(nums8) == id(nums7))
特点:
❏ 深拷贝可以彻底消除拷贝前后数据之间的相互影响。
❏ 深拷贝遇到【不可变对象】不会复制,会直接引用。
注意点:
❏ 深拷贝只复制可变对象,不可变对象会直接引用。测试代码如下:
import copy
aa = 6
# aa是不可变对象,即便调用deepcopy也不会深拷贝,会直接引用
cc = copy.deepcopy(aa)
print(aa, cc) # 6 6
# 2346908951744 2346908951744 True 它们的内存地址是同一个地址
print(id(aa), id(cc), id(cc) == id(aa))
赋值、浅拷贝、深拷贝在实际开发中要根据具体业务场景选择合适方式使用,不能滥用,可能会造成数据异常。
🔥BuildAdmin是一个永久免费开源,无需授权即可商业使用,且使用了流行技术栈快速创建商业级后台管理系统。