说明
《Python 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
Python 的内置标准库 copy 提供了浅拷贝和深拷贝复制对象的功能, 分别对应模块中的两个函数 copy() 和 deepcopy()。
以下是一些示例:
import copy
a = [1, 2, ['a', 'b']] # 原对象
b = a # 赋值,传引用
c = copy.copy(a) # 浅拷贝
d = copy.deepcopy(a) # 深拷贝
a.append(3) # 修改对象a
a[2][0] = 0 # 修改原对象列表元素中的第一个值
print( '原内容:', a, '# 原对象修改后的值')
print( '再赋值:', b, '# 只是引用,就是原对象')
print( '浅拷贝:', c, '# 受到对象内部对象的变化,外部的不受影响')
print( '深拷贝:', d, '# 不受原对象的变化')
'''
原内容: [1, 2, [0, 'b'], 3] # 原对象修改后的值
再赋值: [1, 2, [0, 'b'], 3] # 只是引用,就是原对象
浅拷贝: [1, 2, [0, 'b']] # 受到对象内部对象的变化,外部的不受影响
深拷贝: [1, 2, ['a', 'b']] # 不受原对象的变化
'''
可以用 https://pythontutor.com/live.html 进行在线测试,观看实时效果。
Python 的赋值语句不复制对象,而是创建目标和对象的绑定关系。对于自身可变,或包含可变项的集合,有时要生成副本用于改变操作,而不必改变原始对象。
copy() 创建的 浅拷贝 是一个新的容器,它包含了对原始对象的内容的引用。也就是说仅拷贝父对象,不会拷贝对象的内部的子对象。即浅复制只复制对象本身,没有复制该对象所引用的对象。比如,当创建一个列表对象的浅拷贝时,将构造一个新的列表,并将原始对象的元素添加给它。内部元素的变化会影响到原数据和新复制的数据。
deepcopy() 创建的 深拷贝 是一个新的容器,它包含了对原始对象的内容的拷贝。深拷贝完全拷贝了父对象及其子对象。即创建一个新的组合对象,同时递归地拷贝所有子对象,新的组合对象与原对象没有任何关联。虽然实际上会共享不可变的子对象,但不影响它们的相互独立性。
总结如下:
再精减:
提供的接口有:
copy.copy(x)
:返回 x 的浅层复制。copy.deepcopy(x[, memo])
:返回 x 的深层复制。copy.Error
:针对模块特定错误引发。浅层与深层复制的区别仅与复合对象(即包含列表或类的实例等其他对象的对象)相关:
深度复制操作通常存在两个问题, 而浅层复制操作并不存在这些问题:
deepcopy() 函数用以下方式避免了这些问题:
此模块不复制诸如模块、方法、堆栈跟踪、堆栈帧、文件、套接字、窗口或任何类似类型的类型。它通过原封不动地返回原始对象来“复制”函数和类(浅层和深层);这与 pickle 模块处理这些问题的方式兼容。
字典的浅层复制可以使用 dict.copy() 方法,而列表的浅层复制可以通过赋值整个列表的切片完成,例如,copied_list = original_list[:]
。
类可以使用与控制序列化(pickling)操作相同的接口来控制复制操作,关于这些方法的描述信息请参考 pickle 模块。实际上,copy 模块使用的正是从 copyreg 模块中注册的 pickle 函数。
副本是一个数据的完整的拷贝,如果我们对副本进行修改,它不会影响到原始数据,物理内存不在同一位置。视图是数据的一个别称或引用,通过该别称或引用亦便可访问、操作原有数据,但原有数据不会产生拷贝。如果我们对视图进行修改,它会影响到原始数据,物理内存在同一位置。
有时我们要区分视图是不是只读视图。
可以通过自定义 _copy__()
和 __deepcopy__()
方法来改变默认的拷贝行为。
__copy()__
是一个无参数方法,它返回一个浅拷贝对象;__deepcopy()__
接受一个备忘(memo)字典参数,返回一个深拷贝对象。需要进行深拷贝的成员属性都应该传递给 copy.deepcopy()
,以及memo字典,以控制递归。(下面例子将解释memo字典)。想要为一个类定义它自己的拷贝操作实现,可以通过定义特殊方法 __copy__()
和 __deepcopy__()
。 调用前者以实现浅层拷贝操作;该方法不必传入额外参数。 调用后者以实现深层拷贝操作;它应转入一个参数,即 memo 字典。 如果 __deepcopy__()
实现需要创建一个组件的深层拷贝,它应当调用 deepcopy() 函数并以该组件作为第一个参数而以该 memo 字典作为第二个参数。。 memo 字典应当被当作不透明对象来处理。
更新时间:2022-06-09 16:43:52 标签:python copy 复制 拷贝