【Python】python深拷贝与浅拷贝详解(必须掌握)


深拷贝和浅拷贝是python必须要掌握的内容,无论你是面试开发、测试、运维等职位,只要是python,深拷贝与浅拷贝是面试官常问的一个重要知识点。

(关注“测试开发自动化” 弓中皓,获取更多学习内容)



一、 深浅拷贝异同

相同点:

无论深拷贝还是浅拷贝都会创建一个新对象。即:拷贝出来的对象的id不同。

不同点:

浅拷贝:只拷贝了对象,对象内的元素并不会发生拷贝。
深拷贝:不仅拷贝对象,对象内的元素也会发生拷贝。


二、浅拷贝

2.1 浅拷贝举例

来看一个浅拷贝的例子:


import copy
a = [1, 2, [3, 4]]       
b = copy.copy(a)    # 浅拷贝
print(id(a))        # 输出结果:2401212115720
print(id(b))        # 输出结果:2401212116104

print(id(a[2]))     # 输出结果:1508928560
print(id(b[2]))     # 输出结果:1508928560

代码解释:
1)b通过浅拷贝a之后,a和b对象的id不同(与相同点吻合)
2)分别取a和b的第3个元素的id(第3个元素是可变对象),发现a和b的第3个元素的id值相同。说明并没有拷贝元素的id,也就是说a和b内部的元素id都是相同的。(与浅拷贝的不同点吻合)

2.2 浅拷贝修改元素值

上面说到了对象a和b内部的元素id都是相同的,那就意味着a、b对象内部的元素是同一个东西。
★重点★:但是并不代表浅拷贝下修改了a内元素元素的值,b元素内元素的值一定会发生变化,还要看被修改的值是否是可变对象:

【情况一】:如果是修改的元素是可变对象,那么修改了a内元素,b内元素会发生变化,该元素的在a、b内的id不会发生变化;
【情况二】:如果修改的元素是不可变对象,那么修改了a内元素,b内元素不会发生变化,该元素在a、b内的id会发生变化


# 情况1举例:修改的元素是可变对象
import copy
a = [1, 2, [3, 4]] 
b = copy.copy(a)     # 浅拷贝

a[2][1] = 4          # 修改a中[3, 4]元素,将3修改为4
print(a)             # 打印结果:[1, 2, [3, 4]]
print(b)             # 打印结果:[1, 2, [3, 4]]
print(id(a[2]))      # 打印结果:2561215900424
print(id(b[2]))      # 打印结果:2561215900424

代码解释:
a的元素[3, 4]是可变对象,所以修改了a元素,b元素也会同步修改,但是由于是浅拷贝,a、b内元素的id并不会发生变化。


# 情况2举例:修改的元素是不可变对象
import copy
a = [1, 2, [3, 4]]   
b = copy.copy(a)      # 浅拷贝

a[1] = 4              # 修改a中第1个位置上的元素,即将2修改为4
print(a)              # 打印结果:[1, 4, [3, 4]]
print(b)              # 打印结果:[1, 2, [3, 4]]
print(id(a[1]))       # 打印结果:1508928624
print(id(b[1]))       # 打印结果:1508928560

代码解释:
a元素的第一个元素是数值型(int类型),是不可变对象,所以修改了a元素,b并不会发生变化,a与b在第一个位置上的元素就属于两个不同的东西了,自然a、b的id就不相等。


三、深拷贝

3.1 深拷贝举例


import copy

a = [1, 2, [3, 4]]
b = copy.deepcopy(a)    # 深拷贝

print(id(a))            # 输出结果:2034433010824
print(id(b))            # 输出结果:2034433010248

print(id(a[2]))         # 输出结果:2463430159112
print(id(b[2]))         # 输出结果:2463430154184

代码解释:
1)b通过浅拷贝a之后,a和b对象的id不同(与2.1中相同点吻合)
2)分别取a和b的第3个元素的id(第3个元素是可变对象),发现a和b的第3个元素的id值不相同。说明a拷贝了元素b,也就是说a和b内部的元素id都是不同的个体。(与深拷贝的不同点吻合)

3.2 深拷贝修改值

与浅拷贝相反,可以将深拷贝也分为两种情况:

【情况一】:如果是修改的元素是可变对象,那么修改了a内元素,b内元素不会发生变化,该元素的在a、b内的id会发生变化;
【情况二】:如果修改的元素是不可变对象,那么修改了a内元素,b内元素不会发生变化,该元素在a、b内的id会发生变化(与浅拷贝相同)


# 情况1举例:修改的元素是可变对象
import copy
a = [1, 2, [3, 4]] 
b = copy.deepcopy(a)     # 深拷贝

a[2][0] = 4          # 修改a中[3, 4]元素,将3修改为4
print(a)             # 打印结果:[1, 2, [4, 4]]
print(b)             # 打印结果:[1, 2, [3, 4]]
print(id(a[2]))      # 打印结果:1975929744136
print(id(b[2]))      # 打印结果:1975929739208

代码解释:
a的元素[3, 4]是可变对象,是深拷贝,所以修改了a元素,b元素并不会同步修改。由于是深拷贝,修改a内可变对象元素,b内元素的id并不会发生变化。


欢迎点赞+关注+收藏

(关注“测试开发自动化” 弓中皓,获取更多学习内容)

  • 14
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

米码收割机

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值