Python 浅复制(Copy)与深复制(Deepcopy)的附代码解析

Deepcopy

寻常意义的复制就是深复制,即将被复制对象完全再复制一遍作为独立的新个体单独存在。所以改变原有被复制对象不会对已经复制出来的新对象产生影响。

Shallowcopy

shallow copy并不会产生一个独立的对象单独存在,他只是将原有的数据块打上一个新标签,所以当其中一个标签被改变的时候,数据块就会发生变化,另一个标签也会随之改变。这就和我们寻常意义上的复制有所不同了。

Deepcopy VS Shallowcopy

对于简单的 object,用shallow copy 和 deep copy 没区别;而对于复杂的 object, 如 list 中套着 list 的情况,shallow copy 中的 子list,并未从原 object 真的「独立」出来。也就是说,如果你改变原 object 的子 list 中的一个元素,你的 copy 就会跟着一起变。这跟我们直觉上对「复制」的理解不同。

import copy
from copy import deepcopy
# origin里面有三个元素,1,2,[3,4]
origin = [1,2,[3,4]]

# list对象本身自带copy方法,该方法也是浅复制,换而言之,下面的copy1是等价的
# copy1 = origin.copy()
copy1 = copy.copy(origin)
copy2 = deepcopy(origin)

print(copy1 == copy2)   # True
print(copy1 is copy2)   # False
# copy1 和copy2看上去相同,但已经不是同一个object
origin[2][0] = "hey!"
print(origin)   # [1, 2, ['hey!', 4]]
print(copy1)    # [1, 2, ['hey!', 4]]
print(copy2)    # [1, 2, [3, 4]]

有一个法则,即浅复制会拷贝一级Object的信息,但是不会拷贝二级Object的信息。也就是说,上述的案例中如果不修改被嵌套的List的话,是不会出问题的。这个法则也适用于别的Object,比如字典嵌套列表,自定义Class嵌套字典等等。

这和Python内部的参数传递机制有关,对于一个较为复杂的高级类,Python的复制一向是以地址传递为主,因此对于二级嵌套对象,一级对象仅拥有一个内存地址而已,当进行浅Copy的时候,该内存对象是不变的,因此访问的仍然是同一个数据。

class People:  
    def __init__(self, name):  
        self.name = name  
  
# 创造三个名字为[0, 1, 2]的People类  
a = [People(i) for i in range(3)]  
b = a.copy()  
b.pop()  
  
# 下面的例子可以看到,b的pop仅仅是弹出了一个内存地址,而前两个内存地址仍然与a相同  
print(a)  
"""
输出
[<__main__.People object at 0x0000015C0EA62E50>,
<__main__.People object at 0x0000015C0EA62610>, 
<__main__.People object at 0x0000015C0EA621F0>]
"""

print(b)
"""
输出
[<__main__.People object at 0x0000015C0EA62E50>,
<__main__.People object at 0x0000015C0EA62610>
"""
print([i.name for i in a])  # 输出[0, 1, 2]  
 
# 因此在修改b的people对象的时候,a同样会受影响  
b[0].name = 'hey'  
print([i.name for i in a]) # 输出['hey', 1, 2]

Tips:

  • " = " 即一般意义的复制,浅复制
  • 列表切片等价于深复制
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值