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]]

Python 中,`deepcopy` 可用于创建嵌套对象(如列表、字典等)的深拷贝。如果你要复制的是一个表格结构的数据(例如由 `pandas.DataFrame` 表示),你可以结合 Pandas 库和 copy 模块中的 deepcopy 函数来进行操作。 以下是如何使用Python代码实现对包含数据的Pandas DataFrame做深度复制的例子: ```python import pandas as pd from copy import deepcopy # 创建原始DataFrame作为例子 data = {'Column1': [1, 2], 'Column2': ['A', 'B']} original_df = pd.DataFrame(data) print("Original Dataframe:") print(original_df) # 对这个DataFrame执行深拷贝 copied_df = deepcopy(original_df) print("\nCopied Dataframe after deep copying:") print(copied_df) # 修改原表内容 original_df.loc[0,'Column1'] = 999 print("\nAfter changing original dataframe") print("Changed Original Dataframe:") print(original_df) print("Unchanged Copied Dataframe (due to deep copy):") print(copied_df) ``` 在这个例子中,我们首先导入了必要的库并定义了一个简单的DataFrame。然后用 `deepcopy()` 方法对其进行了完全独立副本的创建。之后当我们在更改原有的DataFrame时发现被深拷贝后的对象没有受到影响,这证明两个变量指向的是不同内存地址处的内容。 需要注意一点,在大多数情况下对于Pandas的DataFrame可以直接调用其`.copy(deep=True)`方法得到同样的效果而无需引入额外模块;这里只是为了展示如何利用标准库提供的通用解法&mdash;&mdash;即`deepcopy`函数处理更复杂情况下的对象复制需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值