Python——copy/deepcopy

本文深入解析Python中的浅复制与深复制概念,通过实例演示两者在处理列表和其他数据结构时的区别,重点强调深复制如何避免原始对象修改对副本的影响。

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

Shallow Copy

浅复制,也就是copy,指的是创建一个对象以指向原有对象中各元素的地址。

>>> from copy import copy, deepcopy
>>> old_instance = ['copyme', [1, 2, 3]]
>>> new_instance = copy(old_instance)
>>> [id(i) for i in old_instance]
[48374208, 48698272]
>>> [id(i) for i in new_instance]
[48374208, 48698272]

可以看到,我们创建了一个new_instance来接收浅复制返回的old_instance,其new_instance中各元素的地址与old_instance中对应元素相同。

当我们试图修改old_instance中可变元素的值时,会相应地反映在new_instance中:

>>> old_instance[1][0] = 4
>>> old_instance
['copyme', [4, 2, 3]]
>>> new_instance
['copyme', [4, 2, 3]]

 请注意字符串和元组是不可变元素!当我们试图修改字符串时,必然会引发异常:

>>> old_instance[0][4:] = ''
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

但我们可以将这个元素的地址指向其他字符串对象,以达到”修改“字符串的目的:

>>> old_instance[0] = 'copyyou'
>>> old_instance
['copyyou', [4, 2, 3]]
>>> new_instance
['copyme', [4, 2, 3]]

明显地可以观察到,new_instance[0]仍然指向原来字符串的地址,并没有跟随着old_instance[0]指向新的字符串对象,这是因为我们将[0]元素的地址指向了新的字符串对象,而非在原地址上修改对象。故上述修改添加引号。可自行使用id函数检查地址变化。

请注意这点特性!

 Deep Copy

深复制,将要复制的对象复制到其他内存地址上,实际上是创建一个副本,对原有对象的变动不会影响到副本。

>>> old_instance = ['copyme', [1, 2, 3]]
>>> new_instance = deepcopy(old_instance)
>>> new_instance
['copyme', [1, 2, 3]]
>>> [id(x) for x in old_instance]
[48374208, 48699232]
>>> [id(x) for x in new_instance]
[48374208, 48699152]

 可以看到,嵌套列表中的内层列表的地址已经不同。而字符串的地址相同,这是因为字符串是不可变对象,没有必要为其再开辟新的地址空间存储一份副本。

深复制的新对象在新地址不跟随原对象在原地址的变动:

>>> old_instance[1][0] = 4
>>> old_instance
['copyme', [4, 2, 3]]
>>> new_instance
['copyme', [1, 2, 3]]

也适用于嵌套结构:

>>> inner = [6, 6, 6]
>>> old_instance = [9, 9, 9, inner]
>>> new_instance = deepcopy(old_instance)
>>> old_instance
[9, 9, 9, [6, 6, 6]]
>>> new_instance
[9, 9, 9, [6, 6, 6]]
>>> [id(x) for x in old_instance]
[1507470608, 1507470608, 1507470608, 48736096]
>>> [id(x) for x in new_instance]
[1507470608, 1507470608, 1507470608, 48699032]
>>> inner[0] = 9
>>> old_instance
[9, 9, 9, [9, 6, 6]]
>>> new_instance
[9, 9, 9, [6, 6, 6]]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值