Python中的浅拷贝与深拷贝

一、浅拷贝

        浅拷贝是对于一个对象的顶层拷贝,通俗的理解是:拷贝了引用,并没有拷贝内容

浅拷贝内存图:


例子1:

In [1]: import copy

In [2]: a = [1,2,3]

In [3]: b =  [11,22,33]

In [4]: c = [a,b]

In [5]: c
Out[5]: [[1, 2, 3], [11, 22, 33]]

In [6]: d = copy.copy(c)

In [7]: d
Out[7]: [[1, 2, 3], [11, 22, 33]]

In [8]: id(c) # 用来显示a指向的数据内存地址
Out[8]: 1803852506696

In [9]: id(d) # 用来显示b指向的数据内存地址
Out[9]: 1803850684680

In [10]: a.append(4) # 向a列表中添加一个数据

In [11]: d
Out[11]: [[1, 2, 3, 4], [11, 22, 33]] # d是从c拷贝过来的,[a,b]列表指向c。d拷贝来的只是引用,所以数据会发生变化

例子2:

In [25]: a = [1,2,3]

In [26]: b = [11,22,33]

In [27]: c = [a,b]

In [28]: d = c[:] # 做切片

In [29]: a[0] = 0 # 修改a列表中的数据

In [30]: c
Out[30]: [[0, 2, 3], [11, 22, 33]]

In [31]: d
Out[31]: [[0, 2, 3], [11, 22, 33]]

In [32]: a.append(4)

In [33]: c
Out[33]: [[0, 2, 3, 4], [11, 22, 33]]

In [34]: d
Out[34]: [[0, 2, 3, 4], [11, 22, 33]] # 因为只是复制了顶层数据,其他的都是对象引用,所以数据会发生改变

因为是浅拷贝,所以只要通过一个引用的修改,那么另外一个变量就能看到的数据变化。

比如:有一个苹果,是小明和小马共有的,如果小马吃了一口苹果,小明的苹果也会少。


二:深拷贝

        深拷贝是对于一个对象所有层次的拷贝(递归)。

深拷贝内存图:


例子:

In [45]: a = [1,2,3]

In [46]: b = [11,22,33]

In [47]: c = [a,b]

In [48]: d = copy.deepcopy(c)

In [49]: id(c) # c列表的内存地址
Out[49]: 1803854612488

In [50]: id(d) # d列表的内存地址
Out[50]: 1803851663432

In [51]: a.append(4) # 向a添加一个数据

In [52]: c
Out[52]: [[1, 2, 3, 4], [11, 22, 33]] # 可以看出原始数据中的a列表被影响了

In [53]: d
Out[53]: [[1, 2, 3], [11, 22, 33]] # 而经过深拷贝的a列表不受影响

深拷贝使用deepcopy方法时会通过递归得到方法把整个数据结构全部都拷贝过来了。

比如:小明从冰箱里拿了一个苹果1。小马也想吃苹果,从冰箱里拿了一个和小明一样的苹果2。 初始是一样的,小明吃了一口,小马的苹果没有吃。

注意点:

浅拷贝对不可变类型和可变类型的copy不同
  1. copy.copy对于可变类型(列表、字典),会进行浅拷贝。
  2. copy.copy对于不可变类型(元祖、数字、字符串),不会拷贝,仅仅是指向。

In [54]: a = [11,22]

In [55]: b = [33,44]

In [56]: c = (a,b) # 此时c是元祖

In [57]: d = copy.copy(c)  

In [58]: id(c)
Out[58]: 1803854592584

In [59]: id(d)
Out[59]: 1803854592584

In [60]: a.append(33)

In [61]: c
Out[61]: ([11, 22, 33], [33, 44])

In [62]: d
Out[62]: ([11, 22, 33], [33, 44])

In [63]:

In [63]: e = copy.deepcopy(c)

In [64]: id(c)
Out[64]: 1803854592584

In [65]: id(e)
Out[65]: 1803853677512

In [66]: a.append(44)

In [67]: c
Out[67]: ([11, 22, 33, 44], [33, 44])

In [68]: e
Out[68]: ([11, 22, 33], [33, 44])

如果c是元祖,那么copy时仅仅是copy元祖的引用

而deepcopy依然是深copy,使用递归copy所有。

总结

基本上只要不是我们自已手动调用的deepcopy方法都是浅拷贝。




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值