Python 提高篇学习笔记(一):深拷贝和浅拷贝

文章目录

  • 一、什么是对象的引用
  • 二、深拷贝和浅拷贝
    • 2.1 浅拷贝(Shallow Copy)
    • 2.2 深拷贝(Deep Copy)
    • 2.3 copy.copy和copy.deepcopy的区别

一、什么是对象的引用

在 Python 中,对象的引用是指变量指向内存中某个对象的地址或标识符。当你创建一个新的对象(比如一个整数、字符串、列表等),Python 会分配一块内存来存储这个对象,并且给这个对象分配一个唯一的标识符(也就是对象的地址)。当你将这个对象赋值给一个变量时,实际上这个变量就存储了对该对象的引用,而不是对象本身。这意味着变量并不直接包含对象的值,而是指向存储这个值的内存地址。

举例:

In [19]: x = [1, 2, 3] # 创建一个列表对象,并将其引用赋给变量x
In [20]: y = x # y和x现在指向同一个列表对象
In [21]: # 修改x所指向的列表对象
In [22]: x.append(4)
In [23]: print(y) # 输出[1, 2, 3, 4],因为y引用的是和x相同的列表对象
[1, 2, 3, 4]

在这个例子中,[1, 2, 3] 是一个列表对象,在内存中有自己的地址。x 这个变量包含了对这个列表对象的引用,而不是列表对象本身。如果你创建一个新的变量 y = x,那么 y 实际上也会指向同一个列表对象,即它们共享相同的引用。图示:
在这里插入图片描述
因此,对于可变对象(如列表、字典等), 如果多个变量引用了同一个对象,当你通过一个变量修改这个对象时,其他引用了相同对象的变量也会反映出这个修改。这是因为它们引用的是同一个对象,而不是对象的副本。对于不可变对象(如整数、字符串等), 由于对象本身是不可变的,任何修改都会导致新对象的创建,而不会影响原始对象,因为对不可变对象的修改实际上是创建了一个新对象并将变量重新指向新对象的地址。举例:

In [33]: x = 300
In [34]: y = x
In [35]: y = 400
In [36]: print(x, y)
300 400

图示:
在这里插入图片描述
补充:在 Python 中,== 和 is 是用于比较对象的运算符,但它们的作用不同:

== 操作符用于比较两个对象的值是否相等。
is 操作符用于检查两个对象是否是同一个对象,也就是比较它们的身份标识(即内存地址/引用)是否相同。示例如下:

In [39]: a = [1, 2, 3]
In [40]: b = [1, 2, 3]
In [41]: # 比较值是否相等
In [42]: print(a == b) # 输出True,因为列表a和列表b中的元素都相同
True
In [43]: # 检查是否是同一个对象
In [44]: print(a is b) # 输出False,因为a和b是不同的对象,即在内存地址/引用不一样
False

注意: 在 Python 中,有一个特定的机制用于缓存一定范围内的小整数对象,这个范围通常是 -5~256 (这个范围可能会因 Python 版本和具体实现而略有不同)。 这意味着在这个范围内的整数对象在 Python 程序中的生命周期中会被缓存并重用,而不是每次都创建新的对象。这个缓存机制是为了提高性能和节省内存。因为这些小整数在许多情况下是常用的,Python 会在启动时预先创建这些对象并将其缓存起来,当你需要使用这些整数时,Python 会直接返回缓存中的对象而不是创建新的对象。这种缓存机制使得在相同范围内的整数对象比较时,使用 is 操作符可能返回 True,因为它们指向相同的对象:

In [45]: x = 10
In [46]: y = 10
In [47]: print(x is y) # 输出True,因为x和y是同一个对象,由于小整数的缓存机制(有些也称为常量池)
True
In [48]: a = 300
In [49]: b = 300
In [50]: print(a is b) # 输出False,因为超出了小整数的缓存范围,a和b是不同的对象
False

二、深拷贝和浅拷贝

在 Python 中,深拷贝和浅拷贝是用于创建对象副本的概念。在理解这两者之间的区别之前,让我们先来看看它们的定义和用法。

2.1 浅拷贝(Shallow Copy)

浅拷贝创建一个新对象,但是只复制了对象的引用。这意味着原始对象及其副本引用了相同的子对象。当你对原始对象或副本对象做出改变时,子对象的改变会反映在两者之间。

在 Python 中,可以使用 copy 模块中的 copy() 方法来进行浅拷贝:

In [65]: import copy
In [66]: original_list = [1, 2, [3, 4]]
In [67]: new_list = original_list  # 赋值是最简单的浅拷贝
In [68]: id(original_list) # 用来显示original_list指向的数据的内存地址
Out[68]: 1837971633856
In [69]: id(new_list) # 用来显示new_list指向的数据的内存地址
Out[69]: 1837971633856In [70]: shallow_copied_list = copy.copy(original_list)
In [71]: # 修改shallow_copied_list副本中的元素
In [72]: shallow_copied_list[0] = 5
In [73]: # 修改子对象(原始对象和副本对象共享的对象)
In [74]: shallow_copied_list[2][0] = 6
In [77]: print(original_list, new_list)
[1, 2, [6, 4]] [1, 2, [6, 4]]
In [78]: print(shallow_copied_list)
[5, 2, [6, 4]]

图示:
在这里插入图片描述
字典示例:

In [131]: import copy
In [132]: d = dict(name='AmoXiang',age=19,hobby_list=['dance', 'sing'])
In [133]: co = copy.copy(d)
In [134]: d
Out[134]: {'name': 'AmoXiang', 'age': 19, 'hobby_list': ['dance', 'sing']}
In [135]: co
Out[135]: {'name': 'AmoXiang', 'age': 19, 'hobby_list': ['dance', 'sing']}
In [136]: id(d),id(co)
Out[136]: (1838005229056, 1838001691136)
In [137]: d['name'] = 'Amo'
In [138]: d
Out[138]: {'name': 'Amo', 'age': 19, 'hobby_list': ['dance', 'sing']}
In [139]: co
Out[139]: {'name': 'AmoXiang', 'age': 19, 'hobby_list': ['dance', 'sing']}
In [140]: co['hobby_list'].append('swim')
In [141]: co
Out[141]: {'name': 'AmoXiang', 'age': 19, 'hobby_list': ['dance', 'sing', 'swim']}
In [142]: d
Out[142]: {'name': 'Amo', 'age': 19, 'hobby_list': ['dance', 'sing', 'swim']}
In [143]: id(d['name']),id(co['name'])
Out[143]: (1837976233200, 1837949658800)
In [144]: id(d['age']),id(co['age'])
Out[144]: (1837896002416, 1837896002416)
In [145]: id(d['hobby_list']),id(co['hobby_list'])
Out[145]: (1837979180480, 1837979180480)
In [146]: co['age'] = 20
In [147]: co
Out[147]: {'name': 'AmoXiang', 'age': 20, 'hobby_list': ['dance', 'sing', 'swim']}
In [148]: d
Out[148]: {'name': 'Amo', 'age': 19, 'hobby_list': ['dance', 'sing', 'swim']}

浅拷贝对不可变类型和可变类型的 copy 不同:
copy.copy 对于可变类型,会进行浅拷贝
copy.copy 对于不可变类型,不会拷贝,仅仅是指向

In [159]: import copy
In [160]: a = [1,2,3]
In [161]: b = copy.copy(a)
In [162]: id(a),id(b)
Out[162]: (1838001649984, 1837979060672)
In [163]: a.append(4)
In [164]: a
Out[164]: [1, 2, 3, 4]
In [165]: b
Out[165]: [1, 2, 3]
In [166]: a = (1,2,3)
In [167]: b = copy.copy(a)
In [168]: id(a),id(b)
Out[168]: (1838005603584, 1838005603584)

2.2 深拷贝(Deep Copy)

深拷贝创建一个全新的对象,同时递归地复制了所有子对象。这意味着原始对象及其副本不共享任何子对象。无论你对原始对象还是副本对象做出任何改变,都不会影响对方。同样使用 copy 模块中的 deepcopy() 方法进行深拷贝:

In [90]: import copy
In [91]: original_list = [1, 2, [3, 4]]
In [92]: deep_copied_list = copy.deepcopy(original_list)
In [93]: id(original_list)
Out[93]: 1838005694912
In [94]: id(deep_copied_list)
Out[94]: 1838005773312
In [95]: # 修改副本的元素
In [96]: deep_copied_list[0] = 5
In [97]: # 修改子对象(原始对象和副本对象共享的对象)
In [98]: deep_copied_list[2][0] = 6
In [99]: print(original_list)  # 输出:[1, 2, [3, 4]]
[1, 2, [3, 4]]
In [100]: print(deep_copied_list)  # 输出:[5, 2, [6, 4]]
[5, 2, [6, 4]]
In [101]: print(id(original_list[2]))
1838004780096
In [102]: print(id(deep_copied_list[2]))
1838001793984

图示:
在这里插入图片描述

2.3 copy.copy和copy.deepcopy的区别

copy.copy 图示:
在这里插入图片描述
copy.deepcopy 有兴趣的可以自己画一下,这里我就不再进行赘述(图太难画了,偷下懒)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/160492.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Qt开发流程】之富文本处理

描述 Scribe框架提供了一组类,用于读取和操作结构化的富文本文档。与Qt中以前的富文本支持不同,新的类集中在QTextDocument类上,而不是原始文本信息。这使开发者能够创建和修改结构化的富文本文档,而不必准备中间标记格式的内容。…

busybox制作根文件系统2

上篇内容使用busybox制作好了根文件系统,接下来需要进行一些测试和功能的完善! 根文件系统的测试 测试根文件系统的时候不是直接烧写到EMMC里面,这样测试效率太低了,Ubuntu的rootfs目录已经保存了根文件系统,只需要在…

向量数据库,展望AGI时代

无论是向量数据库,还是大模型,归根结底,大家在追捧它时的心态,焦虑大于需求。 向量数据库的热潮,在一定程度上“外化”了人们的焦虑。 但这并不能否定向量数据库的实际价值,甚至更长远来看,向…

RedisTemplate使用详解

RedisTemplate介绍StringRedisTemplate介绍RedisConnectionFactory介绍RedisConnectionFactory源码解析 RedisOperations介绍RedisOperations源码解析 RedisTemplate使用连接池配置RedisTemplate连接池连接池配置 RedisTemplate应用场景RedisTemplate主要特点RedisTemplate使用…

redis运维(十六) 有序集合

一 有序集合 把握一点: 各种redis 命令都提供各种语言对应的API 接口,后续API是关键 ① 概念 1、sorted set --> 有序集合2、redis有序集合也是集合类型的一部分,所以它保留了集合中元素不能重复的特性3、但是不同的是,有序集合给每个元素多设置…

转型做视频了,博客就是稿子,继续坚持写博客,同时发布视频,能写博客说明思路清晰了,能再讲明白,理解就更透彻了,紧跟上时代发展。

1,今天特别记录下,B站给开通了《合集》功能 最近使用视频制作了几个视频。播放量还不错,最好的已经到了 2.6K了。 然后粉丝也涨到了 200个。 添加链接描述 紧跟时代:从写博客到录视频,粉丝大涨,突破200个&…

接口自动化测试 —— 工具、请求与响应

一、工具: 1.工具介绍 postman :很主流的API测试工具,也是工作里面使用最广泛的研发工具。 JMeter: ApiPost: 2.安装postman: 安装好直接打开,不用注册。 二、通信模式: 1、…

【Java 进阶篇】从Java对象到JSON:Jackson的魔法之旅

在现代的软件开发中,处理数据的能力是至关重要的。而当我们谈及数据格式时,JSON(JavaScript Object Notation)通常是首选。为了在Java中轻松地将对象转换为JSON,我们需要一种强大而灵活的工具。这时,Jackso…

【Java 进阶篇】Redis:打开缓存之门

介绍 Redis(Remote Dictionary Server)是一个高性能的键值对存储系统,被广泛用作缓存、消息中间件和数据库。它以其快速的读写能力、支持多种数据结构和丰富的功能而闻名。在这篇博客中,我们将深入了解Redis的概念、安装以及基本…

MQTT协议消息代理服务远程连接

目录 1. Linux 搭建 Mosquitto 2. Linux 安装Cpolar 3. 创建MQTT服务公网连接地址 4. 客户端远程连接MQTT服务 5. 代码调用MQTT服务 6. 固定连接TCP公网地址 7. 固定地址连接测试 Mosquitto是一个开源的消息代理,它实现了MQTT协议版本3.1和3.1.1。它可以在不…

第二十章:多线程

进程 线程的特点 1.进程是资源分配的最小单位&#xff0c;线程是最小的执行单位 2.一个进程可以有多个线程 3.线程共享进程资源 package twentyth; public class ThreadTest extends Thread { public void run() { for (int i 1; i < 10; i) {//继承重…

Unity开发之C#基础-File文件读取

前言 今天我们将要讲解到c#中 对于文件的读写是怎样的 那么没接触过特别系统编程小伙伴们应该会有一个疑问 这跟文件有什么关系呢&#xff1f; 我们这样来理解 首先 大家对电脑或多或少都应该有不少的了解吧 那么我们这些软件 都是通过变成一个一个文件保存在电脑中 我们才可以…

Spring Boot创建和使用(重要)

Spring的诞生是为了简化Java程序开发的&#xff01; Spring Boot的诞生是为了简化Spring程序开发的&#xff01; Spring Boot就是Spring框架的脚手架&#xff0c;为了快速开发Spring框架而诞生的&#xff01;&#xff01; Spring Boot的优点&#xff1a; 快速集成框架&#x…

2023年G2电站锅炉司炉证考试题库及G2电站锅炉司炉试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年G2电站锅炉司炉证考试题库及G2电站锅炉司炉试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特种设备作业人员上岗证考试大纲…

MySQL 事务的底层原理和 MVCC(一)

在事务的实现机制上&#xff0c;MySQL 采用的是 WAL&#xff08;Write-ahead logging&#xff0c;预写式日志&#xff09;机制来实现的。 在使用 WAL 的系统中&#xff0c;所有的修改都先被写入到日志中&#xff0c;然后再被应用到系统中。通常包含 redo 和 undo 两部分信息。 …

【Java开发】 Springboot集成Mybatis-Flex

1 Mybatis-Flex 介绍 1.1简介 Mybatis-Flex 是一个优雅的 Mybatis 增强框架&#xff0c;它非常轻量、同时拥有极高的性能与灵活性。我们可以轻松的使用 Mybaits-Flex 链接任何数据库&#xff0c;其内置的 QueryWrapper 亮点帮助我们极大的减少了 SQL 编写的工作的同时&#xff…

cocos2dx ​​Animate3D(二)

Twirl 扭曲旋转特效 // 持续时间(时间过后不会回到原来的样子) // 整个屏幕被分成几行几列 // 扭曲中心位置 // 扭曲的数量 // 振幅 static Twirl* create(float duration, const Size& gridSize, const Vec2& position, unsigned int twirls, float amplitude)…

基于springboot实现摄影跟拍预定管理系统【项目源码+论文说明】计算机毕业设计

基于springboot实现摄影跟拍预定管理系统演示 摘要 首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了系统的需求基础上需要进一步地设计系统,主要…

【2018年数据结构真题】

方法一 给定一个含n(n>1)个整数的数组&#xff0c;请设计一个在时间上尽可能高效的算法&#xff0c;找出数组中未出现的最小正整数。例如&#xff0c;数组{-5&#xff0c;3&#xff0c;2&#xff0c;3}中未出现的最小正整数是1&#xff1b;数组{1&#xff0c;2&#xff0c;…

AIGC变革BI行业,永洪发布vividime全球化品牌

大数据产业创新服务媒体 ——聚焦数据 改变商业 国内BI商业智能市场&#xff0c;一直有着“内永洪&#xff0c;外Tableau”的说法。成立于2012年的永洪科技经过十多年的发展&#xff0c;早已崛起为国内大数据行业的一支劲旅。 ChatGPT火爆出圈之后&#xff0c;AIGC快速渗透&am…