Python中的拷贝

这篇博客介绍了Python中三种拷贝方式:赋值拷贝、浅拷贝和深拷贝。通过示例解释了不同拷贝方式下内存的变化,强调了对于可变类型子对象的影响。浅拷贝仅复制对象本身和可变类型子对象的引用,而深拷贝则对所有层级的对象进行完全复制,确保两个对象的独立性。

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

个人理解一共是有三种拷贝:拷贝(赋值),浅拷贝,深拷贝

a = [1, 2, 3, 4, ['a', 'b']] 为例;

import copy
a = [1, 2, 3, 4, ['a', 'b']]

b = a  		#赋值。传对象的引用
c = copy.copy(a)  	#对象拷贝,浅拷贝
d = copy.deepcopy(a)  	#对象拷贝,深拷贝
e = a[:] 		#利用分片操作进行拷贝(浅拷贝)
a.append(5)  		#改动对象a
a[4].append('c') 	#改动对象a中的['a', 'b']列表子对象

print 'a = ', a
print 'b = ', b
print 'c = ', c
print 'd = ', d
print "e = ", e
执行结果:
a =  [1, 2, 3, 4, ['a', 'b', 'c'], 5]
b =  [1, 2, 3, 4, ['a', 'b', 'c'], 5]
c =  [1, 2, 3, 4, ['a', 'b', 'c']]
d =  [1, 2, 3, 4, ['a', 'b']]
e =  [1, 2, 3, 4, ['a', 'b', 'c']]

首先了解一下python各数据类型在内存中的存储方式:

基本类型 :
基本类型在内存中分别占有固定大小的空间,他们的值保存在栈空间,我们是通过按值来访问的。
引用类型 :
引用类型,值大小不固定,栈内存中存放地址指向堆内存中的对象。是按引用访问的。
栈内存中存放的只是该对象的访问地址,在堆内存中为这个值分配空间。由于这种值的大小不固定,
因此不能把它们保存到栈内存中。但内存地址大小的固定的,因此可以将内存地址保存在栈内存中。
这样,当查询引用类型的变量时, 先从栈中读取内存地址, 然后再通过地址找到堆中的值。对于这种,
我们把它叫做按引用访问。

浅拷贝只复制指向某个对象的引用地址,而不复制对象本身(只复制一层对象的属性),新旧对象还是共享同一块内存。
但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
浅复制只复制一层对象的属性,而深复制则递归复制了所有层级。

分析:b赋值:是对a对象的内存地址的引用,两者必然相同
c浅拷贝:把a对象本身完全拷贝,开辟新的内存空间,如果a中有子对象是可变类型,浅拷贝也只拷贝子对象的引用地址,故在子对象可变类型值改变后,浅拷贝对象也改变。切片原理就是浅拷贝,同上
d深拷贝:不仅把a对象完全拷贝,而且对a的子对象也完全拷贝。之后a的任何元素改变都不影响d的值,两个已经是完全独立的对象了。

*****总结:*****拷贝从引用类型出发,依据程度的不同,呈现不同的效果!

### 深拷贝与浅拷贝的区别及实现方法 在 Python 中,数组或列表的拷贝可以通过浅拷贝(shallow copy)和深拷贝(deep copy)两种方式实现。以下是两者的详细对比及实现方法。 #### 浅拷贝(Shallow Copy) 浅拷贝会创建一个新的对象,但该对象中的元素仍然是原对象中元素的引用。如果原对象包含嵌套结构(如列表中包含列表),修改嵌套结构中的元素会影响浅拷贝的对象[^2]。 ##### 示例代码 ```python import copy # 定义一个嵌套列表 original_array = [[1, 2], [3, 4]] # 使用浅拷贝 shallow_copy = copy.copy(original_array) # 修改原始数组中的嵌套列表 original_array[0][0] = 99 # 输出结果 print("Original Array:", original_array) # 输出: Original Array: [[99, 2], [3, 4]] print("Shallow Copy:", shallow_copy) # 输出: Shallow Copy: [[99, 2], [3, 4]] ``` 从上述示例可以看出,修改 `original_array` 中的嵌套列表也会影响到 `shallow_copy`。 #### 深拷贝(Deep Copy) 深拷贝会递归地复制对象及其所有子对象,确保原始对象和副本之间完全独立。即使原对象包含嵌套结构,修改原对象中的嵌套结构也不会影响深拷贝的对象[^1]。 ##### 示例代码 ```python import copy # 定义一个嵌套列表 original_array = [[1, 2], [3, 4]] # 使用深拷贝 deep_copy = copy.deepcopy(original_array) # 修改原始数组中的嵌套列表 original_array[0][0] = 99 # 输出结果 print("Original Array:", original_array) # 输出: Original Array: [[99, 2], [3, 4]] print("Deep Copy:", deep_copy) # 输出: Deep Copy: [[1, 2], [3, 4]] ``` 从上述示例可以看出,`deep_copy` 不受 `original_array` 修改的影响[^1]。 #### 其他实现浅拷贝的方法 除了使用 `copy.copy`,还可以通过切片操作或 `list.copy()` 方法实现浅拷贝[^4]。 ##### 示例代码 ```python # 使用切片操作实现浅拷贝 shallow_copy_slice = original_array[:] # 使用 list.copy() 方法实现浅拷贝 shallow_copy_method = original_array.copy() # 验证浅拷贝行为 original_array[0][0] = 99 print("Original Array:", original_array) # 输出: Original Array: [[99, 2], [3, 4]] print("Shallow Copy Slice:", shallow_copy_slice) # 输出: Shallow Copy Slice: [[99, 2], [3, 4]] print("Shallow Copy Method:", shallow_copy_method) # 输出: Shallow Copy Method: [[99, 2], [3, 4]] ``` #### 性能比较 深拷贝比浅拷贝更耗时且占用更多内存,因为它需要递归地复制所有子对象。如果仅需复制顶层对象而不涉及嵌套结构,浅拷贝通常更为高效[^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值