一个列表让你搞懂浅拷贝深拷贝

本文详细介绍了Python中的浅拷贝和深拷贝概念,通过实例展示了它们的区别。浅拷贝仅复制复合对象的引用,而深拷贝则递归复制所有内容。当原对象或其子对象改变时,浅拷贝受影响,深拷贝保持不变。文章还提到了深拷贝可能遇到的递归循环和过多复制问题,并提供了相关代码实验来验证这些概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

官网链接: https://docs.python.org/zh-cn/3.9/library/copy.html

官网对深拷贝浅拷贝的解释:

浅层与深层复制的区别仅与复合对象(即包含列表或类的实例等其他对象的对象)相关:

  • 浅层复制 构造一个新的复合对象,然后(在尽可能的范围内)将原始对象中找到的对象的 引用 插入其中。

  • 深层复制 构造一个新的复合对象,然后,递归地将在原始对象里找到的对象的 副本 插入其中。

深度复制操作通常存在两个问题, 而浅层复制操作并不存在这些问题:

  • 递归对象 (直接或间接包含对自身引用的复合对象) 可能会导致递归循环。

  • 由于深层复制会复制所有内容,因此可能会过多复制(例如本应该在副本之间共享的数据)。

导入相关模块

import copy

展开讲讲

  1. 浅层与深层复制的区别仅与复合对象(即包含列表或类的实例等其他对象的对象)相关, 深拷贝、浅拷贝会构造一个新的复合对象
    什么是复合对象?官网也讲到了,嵌套的对象,比如列表,类的实例等


    非复合对象:
    初始化一下变量

    obj = 1
    copy1 = copy.copy(obj)
    copy2 = copy.deepcopy(obj)
    

    输出看一下

    print(id(obj))
    print(id(copy1))
    print(id(copy2))
    print(obj)
    print(copy1)
    print(copy2)
    

    输出结果

    1483367213360
    1483367213360
    1483367213360
    1
    1
    1
    

    由此可以看出对 整数1 进行深拷贝、浅拷贝是没有效果的,三个内存地址全部相同


    复合对象
    初始化一下变量

    obj = [1]
    copy1 = copy.copy(obj)
    copy2 = copy.deepcopy(obj)
    

    输出看一下

    print(id(obj))
    print(id(copy1))
    print(id(copy2))
    print(obj)
    print(copy1)
    print(copy2)
    

    输出结果

    2782767232384
    2782769860992
    2782769854336
    [1]
    [1]
    [1]
    

    根据输出结果我们可以发现对 列表 进行深拷贝、浅拷贝是有效果的,内存地址是不同的,正印证了这一句话深拷贝、浅拷贝会构造一个新的复合对象

  2. 浅层复制 构造一个新的复合对象,然后(在尽可能的范围内)将原始对象中找到的对象的 引用 插入其中。
    深层复制 构造一个新的复合对象,然后,递归地将在原始对象里找到的对象的 副本 插入其中。


    从官网的解释中不难看出,浅拷贝生成新的复合对象,是将原始对象中找到的对象引用 插入其中,
    在原始对象中找到的对象也可以称为 子对象 ,而引用就是直接引用原子对象内存地址,这种情况下,如果原对象中的子对象发生变化
    浅拷贝生成的对象也会发生变化。
    深拷贝则是将子对象的副本插入其中,不是直接引用内存地址, 所以原子对象发生变化,深拷贝的子对象也不会变。


    原对象发生变化
    初始化一下变量

    obj = [1, 2, [1, 2, [3]]]
    copy1 = copy.copy(obj)
    copy2 = copy.deepcopy(obj)
    

    输出看一下

    print(id(obj))
    print(id(copy1))
    print(id(copy2))
    print(obj)
    print(copy1)
    print(copy2)
    
    obj.append(9)
    
    print(id(obj))
    print(id(copy1))
    print(id(copy2))
    print(obj)
    print(copy1)
    print(copy2)
    

    输出结果

    1961225041536
    1961222432768
    1961225042240
    [1, 2, [1, 2, [3]]]
    [1, 2, [1, 2, [3]]]
    [1, 2, [1, 2, [3]]]
    1961225041536
    1961222432768
    1961225042240
    [1, 2, [1, 2, [3]], 9]
    [1, 2, [1, 2, [3]]]
    [1, 2, [1, 2, [3]]]
    

    原对象发生变化,深拷贝、浅拷贝的对象没有随之变化


    原对象中的子对象发生变化
    初始化一下变量

    obj = [1, 2, [1, 2, [3]]]
    copy1 = copy.copy(obj)
    copy2 = copy.deepcopy(obj)
    

    输出看一下

    print(id(obj))
    print(id(copy1))
    print(id(copy2))
    print(obj)
    print(copy1)
    print(copy2)
    
    obj[2].append(8)
    obj[2][2].append(7)
    
    print(id(obj))
    print(id(copy1))
    print(id(copy2))
    print(obj)
    print(copy1)
    print(copy2)
    

    输出结果

    2713593263872
    2713591707776
    2713593264576
    [1, 2, [1, 2, [3]]]
    [1, 2, [1, 2, [3]]]
    [1, 2, [1, 2, [3]]]
    2713593263872
    2713591707776
    2713593264576
    [1, 2, [1, 2, [3, 7], 8]]
    [1, 2, [1, 2, [3, 7], 8]]
    [1, 2, [1, 2, [3]]]
    

    可以看出,原对象内的子对象变化后,浅拷贝的随之变化,深拷贝却没有变化

  3. 深度复制操作通常存在两个问题

    深拷贝操作时多注意以上两个问题

实验代码

其实二维列表就够用了,多一层也没什么意义

import copy

obj = [1, 2, [1, 2, [3]]]
copy1 = copy.copy(obj)
copy2 = copy.deepcopy(obj)

print(id(obj))
print(id(copy1))
print(id(copy2))
print(obj)
print(copy1)
print(copy2)

obj.append(9)
obj[2].append(8)
obj[2][2].append(7)

print(id(obj))
print(id(copy1))
print(id(copy2))
print(obj)
print(copy1)
print(copy2)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值