Python中deepcopy的用法及注意事项详细解释!
Python中deepcopy的用法及注意事项详细解释!
前言
deepcopy 是 Python 标准库中的 copy
模块提供的一个函数,它用于创建对象的深拷贝。
深拷贝与浅拷贝的区别在于,深拷贝会递归地复制对象及其包含的所有对象,而浅拷贝仅复制对象本身,而不会递归地复制对象内部的子对象。
具体来说,
deepcopy
会创建一个新的对象,并且确保新对象中的每个元素都是原对象中元素的独立副本,深度复制整个对象结构。
1. 浅拷贝与深拷贝的区别
- 浅拷贝(shallow copy):复制对象本身,但是对于对象内的可变对象(如列表、字典等),它们仍然指向原对象中的相同位置。即拷贝的对象是原对象的"第一层"的副本,而对于嵌套的可变对象,浅拷贝只是引用它们。
- 深拷贝(deep copy):复制对象及其嵌套对象,确保所有的层次结构都是独立的。也就是说,深拷贝会递归地拷贝对象及其所有子对象。
2. deepcopy 的用法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
import copy # 示例:使用 deepcopy original = { 'a' : 1 , 'b' : [ 2 , 3 ], 'c' : { 'd' : 4 }} # 创建原对象的深拷贝 deep_copied = copy.deepcopy(original) # 修改深拷贝的内容,不影响原对象 deep_copied[ 'b' ][ 0 ] = 100 deep_copied[ 'c' ][ 'd' ] = 200 print ( "Original:" , original) print ( "Deep Copied:" , deep_copied) |
输出:
1
2
|
Original: { 'a' : 1 , 'b' : [ 2 , 3 ], 'c' : { 'd' : 4 }} Deep Copied: { 'a' : 1 , 'b' : [ 100 , 3 ], 'c' : { 'd' : 200 }} |
解释:
original
是一个包含嵌套字典和列表的字典。deepcopy
创建了original
对象的一个新副本,其中包括了original
中所有嵌套结构(列表和字典)的独立副本。- 修改
deep_copied
中的b
列表和c
字典的值,不会影响到原始对象original
,因为它们已经是完全独立的对象。
3. 浅拷贝与深拷贝的对比
我们可以通过下面的例子进一步了解浅拷贝与深拷贝的区别:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
import copy # 示例对象:一个包含可变对象的字典 original = { 'a' : 1 , 'b' : [ 2 , 3 ], 'c' : { 'd' : 4 }} # 创建浅拷贝 shallow_copied = copy.copy(original) # 修改浅拷贝的内部结构 shallow_copied[ 'b' ][ 0 ] = 100 shallow_copied[ 'c' ][ 'd' ] = 200 print ( "Original:" , original) print ( "Shallow Copied:" , shallow_copied) |
输出:
1
2
|
Original: { 'a' : 1 , 'b' : [ 100 , 3 ], 'c' : { 'd' : 200 }} Shallow Copied: { 'a' : 1 , 'b' : [ 100 , 3 ], 'c' : { 'd' : 200 }} |
解释:
shallow_copied
是通过浅拷贝创建的,b
列表和c
字典仍然指向original
中的同一个对象,因此修改shallow_copied
内部的b
和c
也会影响original
。- 深拷贝不同,它会递归地复制所有的对象结构,避免了这种情况。
4. 为什么使用 deepcopy?
- 避免意外修改原始对象:如果对象是嵌套的(比如包含列表、字典等可变类型),使用浅拷贝可能导致修改深层对象时,原始对象被意外修改。
deepcopy
可以确保所有的层次结构都被独立复制,避免这种情况。 - 独立的副本:有些场景下,你需要对一个对象进行修改,但是又希望保留原始对象不受影响。使用
deepcopy
可以确保创建一个完全独立的副本。
5. deepcopy 的工作原理
deepcopy
实际上会递归地遍历对象的所有层级,并对每个元素进行拷贝。对于内置类型(如列表、字典、集合等),它会根据对象的类型来决定如何拷贝。如果对象中含有自定义的类或对象,deepcopy
会根据类的 __deepcopy__
方法来处理。
如果对象是不可变类型(如数字、字符串、元组等),deepcopy
会直接返回对象本身,因为它们本身就是不可变的。
6. __deepcopy__ 方法
对于某些自定义对象,你可以通过实现 __deepcopy__
方法来定义对象的深拷贝行为。这个方法会在 deepcopy
时被自动调用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import copy class MyClass: def __init__( self , value): self .value = value def __deepcopy__( self , memo): # 自定义深拷贝逻辑 new_obj = MyClass( self .value) print (f "Deep copying MyClass with value {self.value}" ) return new_obj # 创建一个 MyClass 对象 obj = MyClass( 42 ) # 对 MyClass 对象进行深拷贝 obj_copy = copy.deepcopy(obj) |
输出:
1
|
Deep copying MyClass with value 42 |
解释:
__deepcopy__
方法允许你自定义对象在深拷贝时的行为。在这个例子中,我们自定义了MyClass
的__deepcopy__
方法来创建一个新的MyClass
对象,并打印出深拷贝的相关信息。
7. 使用 deepcopy 时的注意事项
-
性能开销:
deepcopy
会递归复制对象的所有层次,因此对于包含大量嵌套对象的复杂数据结构,使用deepcopy
可能会带来较大的性能开销。在性能要求较高的场合,最好避免不必要的深拷贝。 -
引用计数:
deepcopy
会创建所有嵌套对象的新副本,因此原始对象和拷贝对象之间没有任何共享部分。若有大量对象需要复制,可能会导致内存消耗较大。 -
循环引用:
deepcopy
可以处理循环引用(即对象间相互引用),通过一个memo
字典来确保每个对象只会被复制一次。
总结
deepcopy
是一种创建对象完全独立副本的工具,特别适用于需要复制复杂数据结构(如包含嵌套列表、字典等可变对象)的场景。
与浅拷贝不同,深拷贝会递归地复制对象及其所有嵌套元素,确保原始对象和副本之间没有任何共享部分。
在处理复杂对象或需要完全独立副本的场景中,
deepcopy
是非常有用的工具。
到此这篇关于Python中deepcopy的用法及注意事项的文章就介绍到这了。
学习资料见知识星球。
以上就是今天要分享的技巧,你学会了吗?若有什么问题,欢迎在下方留言。
快来试试吧,小琥 my21ke007。获取 1000个免费 Excel模板福利!
更多技巧, www.excelbook.cn
欢迎 加入 零售创新 知识星球,知识星球主要以数据分析、报告分享、数据工具讨论为主;
1、价值上万元的专业的PPT报告模板。
2、专业案例分析和解读笔记。
3、实用的Excel、Word、PPT技巧。
4、VIP讨论群,共享资源。
5、优惠的会员商品。
6、一次付费只需129元,即可下载本站文章涉及的文件和软件。