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.rhkb.cn/news/202486.html

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

相关文章

k8s无法删除pv,pvc问题

问题: 在k8s里面创建了pv,pvc删除时报错:error: resource(s) were provided, but no name was specified 解决: 正确的删除顺序:1.先删除pod2.再删除pv 3.在删除pvc 删除pv,pvc命令: kubect…

“下一代云”白皮书发布:PaaS成为核心增长动力,腾讯云市场份额第二

“市场需求进一步向PaaS和SaaS层进发,使之成为公有云服务市场增长的主要动力。”11月22日,全球领先的IT研究和咨询公司国际数据公司(IDC)联合腾讯云发布“下一代云”白皮书——《聚焦平台能力,支撑智能化业务发展》指出…

电大搜题——让学习变得轻松高效

作为一名现代学者,您一定时刻关注着教育领域的进展和创新。今天,我将向大家介绍一个名为“电大搜题”的神奇工具,它将为您的学习之路带来一场完美的革命。 在快节奏的现代社会中,学习已经成为每个人追求成功的必经之路。然而&…

微服务实战系列之加密RSA

前言 在这个时代,我们选择的人生目标已丰富多彩,秉持的人生态度也千差万别: 除了吃喝玩乐,还有科技探索; 除了CityWalk,还有“BookWalk”; 除了走遍中国,还有走遍世界; …

leetCode 2925. 在树上执行操作以后得到的最大分数 + 正则难反 + 树形 DP

2925. 在树上执行操作以后得到的最大分数 - 力扣(LeetCode) 有一棵 n 个节点的无向树,节点编号为 0 到 n - 1 ,根节点编号为 0 。给你一个长度为 n - 1 的二维整数数组 edges 表示这棵树,其中 edges[i] [ai, bi] 表示…

浅谈能源智能管理系统在大学高校中的应用

安科瑞 华楠 摘要:结合深圳南方科技大学能效系统工程设计实例,针对校园中电耗、热量消耗、冷量消耗及水资源消耗数据的采集、传输、分析管理系统,分析了系统中的水、电、气在高校中的能耗分布,并阐述了节能应用方案,可…

「纯电」厮杀,广州车展的年末大戏

作者 |张祥威 编辑 |德新 年末的广州车展,揭开纯电动车激烈厮杀的一角。 1100多款车型亮相在这届车展,其中新能源车有460多辆,占接近一半比例。这其中,人们的焦点又放在十多款纯电车型上。 造车新势力中,理想的首款…

基于Python+TensorFlow+Django的交通标志识别系统

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 随着交通网络的不断扩展和智能交通系统的发展,交通标志的自动识别变得愈发重要。本项目旨在利用Python编…

micro_ros

原文链接Supported Hardware | micro-ROS Supported Hardware The main targets of micro-ROS are mid-range 32-bits microcontroller families. Usually, the minimum requirements for running micro-ROS in an embedded platform are memory constraints. Since memory u…

阿里云ECS服务器如何搭建并连接FTP,完整步骤

怎么用终端连接服务器就不多说了,直接开始搭建FTP。 我是用root账号执行的命令,如果不使用root账号,注意在命令前面加sudo。 一、安装FTP 我这里安装的是vsftpd。 1、检查是否已安装vsftpd: vsftpd -v如果出现了版本信息&…

Atlassian Confluence 路径遍历和命令执行漏洞 (CVE-2019-3396)

漏洞描述 Confluence 是由澳大利亚软件公司 Atlassian 开发的基于 Web 的企业 wiki。 Atlassian Confluence 6.14.2 版本之前存在一个未经授权的目录遍历漏洞,攻击者可以使用 Velocity 模板注入读取任意文件或执行任意命令。 漏洞环境及漏洞利用 启动docker环境…

【git】pip install git+https://github.com/xxx/xxx替换成本地下载编译安装解决网络超时问题

目录 🌑🌑 背景 🌒 🌒作用 🌔🌔 问题 🌔🌔解决方案 🌙方法一 🌙方法二 🌝🌝我的解决方案 整理不易,欢迎一键三连…

【硬核HeyGen平替】在window平台上使用MyHeyGen

最近在研究HeyGen的平替开源项目,然后发现了MyHeyGen这个项目,但是文档上面并没有说明如果在window平台上使用,考虑到非window平台安装显卡驱动什么的比较繁琐,所以尝试硬着头皮干... 前提 开源项目中所需的环境准备要先准备好 1…

轻松记录收支明细,一键打印,财务无忧!

作为现代人,管理好个人财务是非常重要的。但是,如何记录收支明细并打印出来呢?今天,我们向您推荐一款财务软件,帮助您轻松解决这个问题。 首先第一步,我们要打开【晨曦记账本】,并登录账号。 第…

神经网络训练技巧

1. 逐渐增加训练数据规模,比如先在小数据集上训练,之后再增大数据集继续训练。

安卓隐私指示器学习笔记

最近了解到Google 在Android12上新增了权限指示器,可以在信号栏的右侧显示当前访问录音机和Camera的应用,点击后可以跳转到相应应用的权限界面,消费者可以控制权限的开启和关闭。国内手机厂商最近几年都在增加隐私看板供能,消费者…

电脑出现api-ms-win-crt-runtime-l1-1-0.dll丢失的情况有什么解决办法,dll文件丢失的方法

在使用电脑过程中,有时可能会遇到缺失api-ms-win-crt-runtime-l1-1-0.dll文件的问题,这可能导致某些应用程序无法正常运行。本文将介绍三种解决这个问题的方法,并比较它们的优缺点。 一.解决api-ms-win-crt-runtime-l1-1-0.dll丢失的问题 方…

Excel文件比较不再繁琐,xlCompare助您快速找出差异

概要 在现代职场中,Excel 已成为工作中不可或缺的利器。 在日常操作中,我们会遇到需要对两个或多个 Excel 文件进行比较的情况,此时,一款高效的 Excel 文件比较工具就显得尤为重要。 本文将为您介绍一款功能强大、优势明显的 Exc…

基于docker实现JMeter分布式压测

为什么需要分布式? 在工作中经常需要对一些关键接口做高QPS的压测,JMeter是由Java 语言开发,没创建一个线程(虚拟用户),JVM默认会为每个线程分配1M的堆栈内存空间。受限于单台试压机的配置很难实现太高的并…

在Spring Boot中使用Thymeleaf开发Web页面

引言: 为啥写这篇文章呢?我明明就没怎么用过这个Thymeleaf进行web开发,用JSP也行,三剑客也行,或者Vue,React,PHP等等,不好吗? 那我为啥写这篇博客呢?这个写了…