当前位置: 首页 > news >正文

【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() 时,原始对象和拷贝对象的内部结构是完全独立的。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【牛客_c++_string】HJ1字符串最后一个单词的长度
  • Spring Boot使用拦截器(Interceptor)
  • mysql中group by语句使用
  • 结果一。6.will,begoingto,betodo,beabouttodo结构的区别
  • 在CentOS 7上安装MongoDB的方法
  • ROS imu传感器节点
  • 书生大模型实战营-进阶关卡-6-MindSearch 快速部署
  • 力扣8.27
  • 阿里云对象存储服务(Aliyun OSS):企业级云存储解决方案
  • Spring Boot 集成 JdbcTemplate(盘它!)
  • 敏捷架构开发方法和实践:迎接数字化时代的挑战
  • 东芝玉兔2.0明日震撼开售,洗衣机界的全新革命
  • 本地化云桌面系统环境VMware horizon搭建
  • Golang反射:运行时类型检查与操作
  • 虚幻5|制作玩家血量,体力(还未编辑,只用于引用)
  • classpath对获取配置文件的影响
  • express如何解决request entity too large问题
  • JavaScript中的对象个人分享
  • orm2 中文文档 3.1 模型属性
  • python docx文档转html页面
  • Sublime Text 2/3 绑定Eclipse快捷键
  • V4L2视频输入框架概述
  • 面试题:给你个id,去拿到name,多叉树遍历
  • 手写双向链表LinkedList的几个常用功能
  • 吴恩达Deep Learning课程练习题参考答案——R语言版
  • 云栖大讲堂Java基础入门(三)- 阿里巴巴Java开发手册介绍
  • 如何用纯 CSS 创作一个货车 loader
  • ​2021半年盘点,不想你错过的重磅新书
  • ​DB-Engines 12月数据库排名: PostgreSQL有望获得「2020年度数据库」荣誉?
  • ​LeetCode解法汇总518. 零钱兑换 II
  • # 利刃出鞘_Tomcat 核心原理解析(二)
  • #100天计划# 2013年9月29日
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • ${ }的特别功能
  • (02)Hive SQL编译成MapReduce任务的过程
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (poj1.3.2)1791(构造法模拟)
  • (八)Spring源码解析:Spring MVC
  • (纯JS)图片裁剪
  • (附源码)ssm捐赠救助系统 毕业设计 060945
  • (过滤器)Filter和(监听器)listener
  • (力扣)1314.矩阵区域和
  • (欧拉)openEuler系统添加网卡文件配置流程、(欧拉)openEuler系统手动配置ipv6地址流程、(欧拉)openEuler系统网络管理说明
  • (贪心 + 双指针) LeetCode 455. 分发饼干
  • ***微信公众号支付+微信H5支付+微信扫码支付+小程序支付+APP微信支付解决方案总结...
  • .bat批处理(五):遍历指定目录下资源文件并更新
  • .net core webapi 大文件上传到wwwroot文件夹
  • .NET 的静态构造函数是否线程安全?答案是肯定的!
  • .set 数据导入matlab,设置变量导入选项 - MATLAB setvaropts - MathWorks 中国
  • ??myeclipse+tomcat
  • @for /l %i in (1,1,10) do md %i 批处理自动建立目录
  • @Valid和@NotNull字段校验使用
  • [ Linux ] Linux信号概述 信号的产生
  • [1]从概念到实践:电商智能助手在AI Agent技术驱动下的落地实战案例深度剖析(AI Agent技术打造个性化、智能化的用户助手)
  • [240607] Jina AI 发布多模态嵌入模型 | PHP 曝新漏洞 | TypeScript 5.5 RC 发布公告