【Python】浅拷贝与深拷贝

 声明:以下内容均来自于《流畅的Python》一书

一、浅拷贝

1、例子一

l1 = [3, [66, 55, 44], (7, 8, 9)]
# 使用 list() 函数对 l1 进行浅拷贝,创建了新的列表 l2。
# 此时 l2 的内容与 l1 相同,但它们在内存中是两个不同的对象。
# 也就是说,对 l1 或 l2 的后续修改不会直接影响对方,除非涉及到嵌套对象的修改(因为浅拷贝只拷贝了最外层对象,嵌套对象是共享引用的)。
l2 = list(l1)

l1.append(100) # 对l1做的是最外层的修改,所以不会影响l2
l1[1].remove(55) # 对l1是对嵌套对象[66, 55, 44]的修改,所以会影响l2
print("l1:", l1) # l1:[3, [66, 44], (7, 8, 9), 100]
print("l2:", l2) # l2:[3, [66, 44], (7, 8, 9)]

从下图可知,嵌套对象列表[66,55,44]和嵌套对象元组(7,8,9)是列表 l1  l2 共享引用的

2、例子二

l1 = [3, [66, 55, 44], (7, 8, 9)]
# 使用 list() 函数对 l1 进行浅拷贝,创建了新的列表 l2。
# 此时 l2 的内容与 l1 相同,但它们在内存中是两个不同的对象。
# 也就是说,对 l1 或 l2 的后续修改不会直接影响对方,除非涉及到嵌套对象的修改
# (因为浅拷贝只拷贝了最外层对象,嵌套对象是共享引用的)。
l2 = list(l1)

l2[1] += [33, 22] # 对可变的对象来说,例如 l2[1] 引用的列表,+= 运算符就地修改列表。
# 这次修改在 l1[1] 中也有体现,因为它是 l2[1] 的别名。
print('l1:', l1) # l1: [3, [66, 55, 44, 33, 22], (7, 8, 9)]
print('l2:', l2) # l2: [3, [66, 55, 44, 33, 22], (7, 8, 9)]
l2[2] += (10, 11)# 对元组来说,+= 运算符创建一个新元组,然后重新绑定给变量l2[2]。
# 这等同于 l2[2] = l2[2] + (10, 11)。现在,l1 和 l2中最后位置上的元组不是同一个对象,
print('l1:', l1) # l1: [3, [66, 55, 44, 33, 22], (7, 8, 9)]
print('l2:', l2) # l2: [3, [66, 55, 44, 33, 22], (7, 8, 9, 10, 11)]

从下图可知,对于可变对象列表来说,+= 是就地修改嵌套列表;但对于不可变对象元组来说,它是新建了一个元组,然后重新绑定给 l2[2]。

二、深拷贝与浅拷贝

 结合以下代码例子来区分浅拷贝和深拷贝的区别

class Bus:
    def __init__(self, passengers=None):
        if passengers is None:
            self.passengers = []
        else:
            self.passengers = list(passengers)

    def pick(self, name):
        self.passengers.append(name)
    def drop(self, name):
        self.passengers.remove(name)

import copy
# 创建3个Bus的实例
bus1 = Bus(['Alice', 'Bill', 'Claire', 'David']) # 创建了一个bus对象的实例bus1
bus2 = copy.copy(bus1) # 浅拷贝
bus3 = copy.deepcopy(bus1) # 深拷贝
print(id(bus1), id(bus2), id(bus3)) # 2572463078992 2572463305920 2572463307504,
bus1.drop('Bill')
print(bus2.passengers) # ['Alice', 'Claire', 'David']
print(id(bus1.passengers), id(bus2.passengers), id(bus3.passengers)) # 2553117940608 2553117940608 2553117940416
# 查看 passengers 属性后发现,bus1 和 bus2 共享同一个列表对象,因为 bus2 是 bus1 的浅拷贝副本。
print(bus3.passengers) # ['Alice', 'Bill', 'Claire', 'David'].
# bus3 是 bus1 的深拷贝副本,因此它的 passengers 属性引用另一个列表。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值