Python的深复制和浅复制

前言

在Python编程中,理解对象的复制是至关重要的。Python提供了两种主要的复制方法:浅复制(shallow copy)和深复制(deep copy)。这两种方法在处理可变对象时有着显著的区别。下面我们简单看一下两者的使用。

什么是浅复制

浅复制指是指创建一个新对象,这个新对象是原对象的一部分或者全部的副本,但对于原对象中嵌套的对象(比如列表中的列表),浅复制仅仅复制它们的引用,也就是说浅复制不会递归复制所有的子对象。

浅复制示例代码

import copy

lst1 = [1,2,[4,5],[6,7]]

lst2 = copy.copy(lst1)

lst1[1] = 1
print(lst1) # [1,1,[4,5],[6,7]]
print(lst2) # [1,2,[4,5],[6,7]]

lst2[2].append(8)
print(lst1)  # [1, 1, [4, 5, 8], [6, 7]]
print(lst2)  # [1, 2, [4, 5, 8], [6, 7]]

print(id(lst1[2])) # 2626206798336
print(id(lst2[2])) # 2626206798336

输出结果

更新非嵌套对象
原对象[1, 1, [4, 5], [6, 7]]  
复制对象[1, 2, [4, 5], [6, 7]]


更新嵌套对象
原对象[1, 1, [4, 5, 8], [6, 7]]
复制对象[1, 2, [4, 5, 8], [6, 7]]
lst1[2]的id:2838000534784
lst1[2]的id:2838000534784

我们看到,lst1和lst2中的非嵌套对象都互不干扰,说明浅复制中非嵌套对象都指向了不同的地址,而嵌套对象的修改是同步的,而且id是相同的,说明浅复制中,原对象和复制对象共享着嵌套对象。

什么是深复制

深复制则是创建一个新对象,并递归地复制所有子对象。这样,无论原对象中的嵌套对象如何变化,深复制的对象都不会受影响。

深复制代码示例

import copy

lst1 = [1,2,[4,5],[6,7]]

lst2 = copy.deepcopy(lst1)

print('更新非嵌套对象')
lst1[1] = 1
print(f'原对象{lst1}') 
print(f'复制对象{lst2}') 
print('\n')
print('更新嵌套对象')
lst2[2].append(8)
print(f'原对象{lst1}') 
print(f'复制对象{lst2}') 

id1 = id(lst1[2])
id2 = id(lst2[2])
print(f'lst1[2]的id:{id1}') 
print(f'lst1[2]的id:{id2}') 

输出结果

更新非嵌套对象
原对象[1, 1, [4, 5], [6, 7]]
复制对象[1, 2, [4, 5], [6, 7]]


更新嵌套对象
原对象[1, 1, [4, 5], [6, 7]]
复制对象[1, 2, [4, 5, 8], [6, 7]]
lst1[2]的id:1863229589376
lst1[2]的id:1863229564992

我们可以看到,深复制和浅复制相比,不管是嵌套对象还是非嵌套对象都是互不干扰的,复制对象完全重新生成了原对象里面的所有子对象。

深复制和浅复制的应用

什么时候使用浅复制

  • 当对象中没有嵌套的可变对象时。
  • 当你希望新对象和原对象共享嵌套对象时。

什么时候使用深复制

  • 当对象中包含嵌套的可变对象,且希望完全独立的副本时。
  • 当你不希望两个对象之间有任何共享的引用时。

复制对象的注意事项

  • 性能:深复制因为要递归地复制对象及其子对象,可能会带来较大的性能开销。在处理大型数据结构时,应慎重使用深复制。
  • 对象类型:不是所有对象都可以被深复制。例如,文件对象、数据库连接等往往不支持深复制。
  • 循环引用:如果对象之间存在循环引用,深复制可能会导致递归错误。Python的copy模块可以处理这类情况,但需要注意潜在的性能和内存问题。

总结

浅复制和深复制是Python中处理对象复制的两种重要方法。了解它们的区别及使用场景,对于编写健壮且高效的代码至关重要。在使用复制时,一定要结合自己的场景,谨慎选择复制对象的方式。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值