python中的浅拷贝和深拷贝

为什么需要拷贝(克隆)对象?

Python中的赋值语句不会创建对象(包括不可变对象)的副本,而只是将名称绑定到对象上。当我们需要用到对象的副本,以便修改副本时不会改动主体,就需要拷贝对象。

制作浅副本

用list()工厂函数制作浅副本

>>> list_1 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> list_2 = list(list_1)  #浅副本
>>> list_1
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> list_2
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

可以看到list_1list_2具有相同的内容

>>> list_1.append(['new sublist'])
>>> list_1
[[1, 2, 3], [4, 5, 6], [7, 8, 9], ['new sublist']]
>>> list_2
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

list_1添加新列表的改动并不影响副本list_2,可见副本list_2与原对象list_1互相独立。

>>> list_1[1][0] = 'X'
>>> list_1
[[1, 2, 3], ['X', 5, 6], [7, 8, 9], ['new sublist']]
>>> list_2
[[1, 2, 3], ['X', 5, 6], [7, 8, 9]]

改动list_1中的子对象list_2也会受到影响,浅副本和原对象并不完全独立,这是因为两个列表共享相同的子对象list_2仍然有list_1子对象的引用,并且这些子对象没有复制,只是在list_2中再次引用。

tips:也可以使用copy.copy()函数创建对象的浅副本,但是使用list,dict和set这样的工厂函数创建浅副本更具Python的特色。

制作深副本

用Python标准库中的copy模块中定义的deepcopy()函数制作深副本

>>> import copy
>>> list_1 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> list_3 = copy.deepcopy(list_1)
>>> list_1
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> list_3
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

同样的可以看到list_1list_3具有相同的内容

>>> list_1[1][0] = 'X'
>>> list_1
[[1, 2, 3], ['X', 5, 6], [7, 8, 9]]
>>> list_3
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

改动原对象list_1的子对象不会影响深副本list_3。可见原对象和深副本是完全独立的,list_3复制过程中递归复制了list_1,包括list_1的所有子对象。

浅拷贝和深拷贝的区别

浅拷贝:构建一个新的容器对象,然后填充原对象中子对象的引用。本质上浅复制只执行一层,复制过程不会递归,因此不会创建子对象的副本。

深拷贝:递归复制,首先构造一个新的容器对象,然后递归地填充原始对象中子对象的副本。这种方式会遍历整个对象树,以此来创建原对象及其所有子项的完全独立的副本。


参考书籍:Python Tricks

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值