Python对象拷贝——深拷贝与浅拷贝

1. 对象赋值

对象的赋值实际上是对对象的引用。也就是说当把一个对象赋值给另一个对象时,只是拷贝了引用。如:

>>> t1 = tuple('furzoom')
>>> t2 = t1
>>> id(t1),id(t2)
(139792198303936, 139792198303936)

上面t1和t2代表的是同一个对象。

2. 浅拷贝

除了上面将一个对象直接赋值给另一个对象外,还有两种常用的方法对对象进行拷贝:使用切片操作和工厂方法。

>>> car = ['grand', ['length', 4.85]]
>>> a4 = car[:]
>>> a6 = list(car)
>>> [hex(id(x)) for x in car, a4, a6]
['0x7f23e84da2d8', '0x7f23e84da128', '0x7f23e84da3f8']

通过创建汽车a4和a6,确实表示是不同的对象。现在继续完善a4和a6,修改它们的名字,和汽车长度。

>>> a4[0] = 'a4'
>>> a6[0] = 'a6'
>>> a4, a6
(['a4', ['length', 4.85]], ['a6', ['length', 4.85]])
>>> a4[1][1] = 4.761
>>> a4, a6
(['a4', ['length', 4.761]], ['a6', ['length', 4.761]])

修改汽车名字时,他们表现是正常的,而修改汽车车长时,发生了不期望的结果,修改a4的长度,同时也影响了a6的长度。

为什么会这样呢?原因在于只是针对序列做了浅拷贝。序列类型对象的浅拷贝是默认的拷贝,体现在:使用切片操作[:]、工厂函数、copy模块的copy函数。当改变a6汽车名字时,为什么没有体现在a4汽车上呢?这是因为名字是字符串类型,它是一个不可变类型,改变其内容将引用新建的对象。如下:

>>> a8 = list(car)
>>> [hex(id(x)) for x in car]
['0x7f23e84d7a80', '0x7f23e84da320']
>>> [hex(id(x)) for x in a8]
['0x7f23e84d7a80', '0x7f23e84da320']
>>> [hex(id(x)) for x in a4]
['0x7f23e84d4d78', '0x7f23e84da320']
>>> [hex(id(x)) for x in a6]
['0x7f23e84d4e40', '0x7f23e84da320']

在a4和a6的第二项,它们引用的是同一个对象。

3. 深拷贝

要想避免上面的这种影响,需要对列表进行深拷贝。需要使用copy模块的deepcopy()函数。

如:

>>> car = ['grand', ['length', 4.85]]
>>> a4 = car
>>> import copy
>>> a6 = copy.deepcopy(car)
>>> [hex(id(x)) for x in car, a4, a6]
['0x7f23e84da098', '0x7f23e84da098', '0x7f23e84da440']
>>> a4[0] = 'a4'
>>> a6[0] = 'a6'
>>> a4,a6
(['a4', ['length', 4.85]], ['a6', ['length', 4.85]])
>>> a4[1][1] = 4.761
>>> a4,a6
(['a4', ['length', 4.761]], ['a6', ['length', 4.85]])

另,在copy模块中,只有两个函数,copydeepcopy

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枫竹梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值