【Python】copy()浅拷贝与深拷贝

前言

由于python关于传参的方面和C语言有些出入,对于先学C在学Python的可能需要做些笔记,比如Python中def传参是直接传址,而不是传值创建局部变量等等...而到了copy函数感觉又是个新概念...

1. copy介绍

1.1 copy() 浅拷贝

Python 的 copy() 函数是 copy 模块提供的一个用于创建对象浅拷贝的工具。浅拷贝意味着新创建的对象与原始对象在内存中是两个独立的实体,但是它们包含的数据如果是可变的(比如列表、字典等),那么这些可变数据内部的元素仍然是指向原始对象的引用。

1.2 deepcopy()深拷贝

Python 的 deepcopy() 函数是 copy 模块提供的另一个工具,用于创建对象的深拷贝。与浅拷贝不同,深拷贝会递归地复制对象及其所有子对象,直到所有的元素都是新的副本,新对象和原始对象不再共享任何数据。

2.代码实现

2.1 浅拷贝

首先创建一个list类型a里面要存放[10,20]并另外一个list对象[5,6],进行浅拷贝到b

import copy
# 浅拷贝
print("浅拷贝:")
a = [10,20,[5,6]]
b = copy.copy(a)
print("a = ",a)
print("b = ",b)
# 由于浅拷贝,只是会拷贝表象,所以把a的对象是直接引用,不会拷贝的,
#在b中修改对象之后就会直接修改掉a引用的对象
b.append(30)
b[2].append(7)
print("Aftercopy_a = ",a)
print("Aftercopy_b = ",b)

在对list b最后添加一个30,和在[5,6]中添加一个7,发现输出:

浅拷贝:
a =  [10, 20, [5, 6]]
b =  [10, 20, [5, 6]]
Aftercopy_a =  [10, 20, [5, 6, 7]]
Aftercopy_b =  [10, 20, [5, 6, 7], 30]

拷贝之后不正常的地方在于,a中的[5,6]对象也被修改了,这是因为浅拷贝时 b会直接引用源对象的引用而不会拷贝一份,所以改变b的引用也会改变a的引用。

当创建变量a时,会在堆中创建对象(从左往右),栈中创建变量,指向堆中的对象,而对象开始会开辟三块空间,前两块存放10,20,第三块存放的地方指向另外一个对象,就是[5,6]

当浅拷贝后b就不一样了,b会拷贝表象(就是只开辟第一层的对象),但是第二层的对象([5,6])则会直接进行引用,所以当b.append(30)之后,b会在自己开辟的对象进行添加,而执行b[2].append(7),因为b[2]指向的就是a的[5,6],所以,a也会一起被添加7,而没有添加30。

2.2 深拷贝

理解完浅拷贝深拷贝就很好理解了,就是一模一样全部对象拷贝过来,互不影响

# 深拷贝
print("深拷贝:")
c = [10,20,[5,6]]
d = copy.deepcopy(c)
print("c = ",c)
print("d = ",d)
# 深拷贝就会把拷贝源头实现再复现一遍,在拷贝过后怎么修改都不会影响拷贝源
d.append(30)
d[2].append(7)
print("Aftercopy_c = ",c)
print("Aftercopy_d = ",d)

深拷贝:
c =  [10, 20, [5, 6]]
d =  [10, 20, [5, 6]]
Aftercopy_c =  [10, 20, [5, 6]]
Aftercopy_d =  [10, 20, [5, 6, 7], 30]

a,b指向的对象相互独立,所以只会添加在b中

3. 区别总结

  1. 拷贝深度:

    • copy() 创建的是浅拷贝(Shallow Copy)。这意味着新对象只会复制原始对象中的引用,而不是引用所指向的对象本身。因此,如果原始对象包含任何可变对象,如列表或字典,修改这些可变对象会影响到原始对象和拷贝对象。
    • deepcopy() 创建的是深拷贝(Deep Copy)。新对象会递归地复制原始对象以及所有被引用的对象。这意味着新对象和原始对象完全独立,修改新对象不会影响原始对象。
  2. 性能:

    • 由于 copy() 只是复制引用,它通常比 deepcopy() 快,并且使用的内存较少。
    • deepcopy() 需要递归地复制所有对象,这可能会消耗更多的时间和内存,特别是当对象包含大量数据或复杂嵌套结构时。
  3. 用途:

    • 当你只需要复制对象的顶层结构,并且不需要关心对象内部的可变子对象时,使用 copy()
    • 当你需要完全独立的副本,包括对象内部的所有嵌套对象时,使用 deepcopy()
  4. 自定义行为:

    • 如果对象是自定义类实例,copy() 可以通过定义对象的 __copy__() 方法来自定义其行为。
    • 对于 deepcopy(),则可以通过定义 __deepcopy__() 方法来自定义深拷贝的行为。
  5. 对不可变数据的影响:

    • 对于不可变数据类型(如整数、字符串、元组等),copy() 和 deepcopy() 之间没有区别,因为这些类型的数据不可更改,复制只是创建了数据的引用。
  6. 对内部结构的影响:

    • 使用 copy() 时,原始对象和拷贝对象共享内部的可变子对象。
    • 使用 deepcopy() 时,原始对象和拷贝对象的内部结构是完全独立的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值