简单理解Python中的深拷贝与浅拷贝
I. 简介
深拷贝会递归的创建一个完全独立的对象副本,包括所有嵌套的对象,而浅拷贝只复制嵌套对象的引用,不复制嵌套对象本身。
简单来说就是两者都对原对象进行了复制,因此使用is运算符来比较新旧对象时,返回的都是False(都开辟了新的内存);两者区别在于对嵌套对象有没有进行递归的复制。浅拷贝没有给嵌套对象复制并分配新内存,用is来比较嵌套对象时返回的是True;而深拷贝对嵌套对象开辟了进行了复制并分配新内存,用is来比较嵌套对象时返回的是False。
一个例子如下,我们分别对链表的头结点执行深拷贝与浅拷贝:
# 原链表 ↓
a1 -> b1 -> c1 -> d1 -> e1
# 浅拷贝 ↓ 对于嵌套对象b1, c1, ..., 直接采用了原有引用
a2 -> b1 -> c1 -> d1 -> e1
# 深拷贝 ↓ 对于嵌套对象,同样开辟了内存空间将其复制
a2 -> b2 -> c2 -> d2 -> e2
从代码实现来讲,深拷贝可以用copy库的deepcopy方法实现;浅拷贝除了用copy库的copy方法,还有许多其他的实现途径,接下来我们将进行介绍。
II. 列表
A. 首先要注意一点,对于常用的等号赋值操作,这一操作并没有进行任何拷贝,只是创建了对现有对象的一个新引用:
arr1 = [1, 2, 3, 4]
arr2 = arr1
print(arr2 is arr1) # True
arr2[0] = 0
print(arr1) # [0, 2, 3, 4]
B. 对列表进行切片属于浅拷贝操作:
arr1 = [1, 2, 3, 4]
arr2 = arr1[:]
print(arr2 is arr1) # False
arr2[0] = 0
print(arr1) # [1, 2, 3, 4]
C. 浅拷贝并不会复制嵌套对象:
arr1 = [1, 2, 3, [4, 5, 6]]
arr2 = arr1[:]
print(arr2 is arr1) # False(最外层被复制)
print(arr2[-1] is arr1[-1]) # True(嵌套对象没有被复制)
arr2[-1][0] = 0
print(arr1) # [1, 2, 3, [0, 5, 6]](被修改)
D. 深拷贝才会复制嵌套对象:
import copy
arr1 = [1, 2, 3, [4, 5, 6]]
arr2 = copy.deepcopy(arr1)
print(arr2 is arr1) # False
print(arr2[-1] is arr1[-1]) # False(嵌套对象也被复制)
arr2[-1][0] = 0
print(arr1) # [1, 2, 3, [4, 5, 6]](未修改)
E. 使用数据类型本身的构造器仍属于浅拷贝:
arr1 = [1, 2, 3, [4, 5, 6]]
arr2 = list(arr1) # 使用构造器创建新对象, 属于浅拷贝
print(arr2 is arr1) # False
print(arr2[-1] is arr1[-1]) # True
arr2[-1][0] = 0
print(arr1) # [1, 2, 3, [0, 5, 6]]
F. 对列表进行修改所返回的新列表也属于浅拷贝(先浅拷贝再修改):
arr1 = [1, 2, 3, [4, 5, 6]]
arr2 = arr1 + [] # 先浅拷贝再修改
print(arr2 is arr1) # False
print(arr2[-1] is arr1[-1]) # True
arr2[-1][0] = 0
print(arr1) # [1, 2, 3, [0, 5, 6]]
III. 字符串
A. Python中的字符串是不可变对象。因此,如果对其进行完整切片[:],可以发现这一过程并没有对字符串本身进行修改。那么Python此时只会直接记录原字符串对象的引用,不进行任何拷贝。从设计动机的角度理解,既然本身不可修改,并且进行的切片操作也没有进行修改,那么复制的意义不大,所以干脆不进行复制:
s1 = "1234"
s2 = s1[:]
print(s2 is s1) # True(引用的内容相同)
B. 以上结论同样适用于对字符串进行"假修改",此时也不会进行任何拷贝:
s1 = "1234"
s2 = s1 + ""
print(s2 is s1) # True(没有进行实质修改)
C. 想要进行拷贝,那就得对字符串进行实质修改。如果切片运算改变了原字符串的内容,由于字符串是不可变的,因此只能开辟一个新的内存,来存储修改后的字符串。此时进行了拷贝过程。注意,由于字符串本身没法嵌套对象,因此这里不区分深拷贝与浅拷贝:
s1 = "1234"
s2 = s1[::-1][::-1] # 进行两次修改,翻转两次
print(s2 is s1) # False
print(s2) # 1234
s3 = s1 + "5"
print(s3 is s1) # False
D. 使用构造方法str,也不会进行任何拷贝,只是创建了另一个指向原字符串对象的引用:
s1 = "1234"
s2 = str(s1)
print(s2 is s1) # True
E. 使用copy或deepcopy都不能对字符串内容进行拷贝,只会新增一个引用:
import copy
s1 = "1234"
s2 = copy.copy(s1)
s3 = copy.deepcopy(s1)
print(s2 is s1) # True
print(s3 is s1) # True
相关文章:
简单理解Python中的深拷贝与浅拷贝
I. 简介 深拷贝会递归的创建一个完全独立的对象副本,包括所有嵌套的对象,而浅拷贝只复制嵌套对象的引用,不复制嵌套对象本身。 简单来说就是两者都对原对象进行了复制,因此使用is运算符来比较新旧对象时,返回的都是F…...
C++之std::pair<uint64_t, size_t>应用实例(一百七十七)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…...
前端打开后端返回的HTML格式的数据
前端打开后端返回的 HTML格式 的数据: 后端返回的数据格式如下示例: 前端通过 js 方式处理(核心代码如下) console.log(回调, path); // path 是后端返回的 HTML 格式数据// 必须要存进localstorage,否则会报错&am…...
How to deal with document-oriented data
Schema designData models for e-commerceNuts and bolts of databases, collection, and documents. Principles of schema design What are your application access pattern?Whats the basic unit of data? the basic unit of data is the BSON documentWhat are the ca…...
Http 状态码汇总
文章目录 Http 状态码汇总1xx(信息性状态码)2xx(成功状态码)3xx(重定向状态码)4xx(客户端错误状态码)5xx(服务器错误状态码) Http 状态码汇总 1xx(…...
mysql自定义实体类框架
根据表结构自动生产实体类和方法,根据反射与io生成,可自定义扩展方法 package com.digital.web.front; /*** pom依赖* <dependency>* <groupId>mysql</groupId>* <artifactId>mysql-connector-java</artifactId>* <version>5.1.27</ve…...
批量将Excel中的第二列内容从拼音转换为汉字
要批量将Excel中的第二列内容从拼音转换为汉字,您可以使用Python的openpyxl库来实现。下面是一个示例代码,演示如何读取Excel文件并将第二列内容进行拼音转汉字: from openpyxl import load_workbook from xpinyin import Pinyin # 打开Exce…...
消息推送:精准推送,提升运营效果,增添平台活力
对于app开发者而言,没有什么途径比消息推送更能直接、即时地触及目标用户群体了。消息推送与我们的日常生活息息相关,各种APP的状态和通知都通过消息推送来告知用户,引起用户的注意,吸引用户点开app。总而言之,推送服务…...
[保研/考研机试] KY43 全排列 北京大学复试上机题 C++实现
题目链接: 全排列https://www.nowcoder.com/share/jump/437195121692001512368 描述 给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列。 我们假设对于小写字母有a < b < ... < y < z,而且给定的字符串中的字…...
Java将时间戳转化为特定时区的日期字符串
先上代码: ZonedDateTime dateTime ZonedDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis()),zone ); //2019-12-01T19:01:4608:00String formattedDate dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd") ); //2019-12-…...
【算法挨揍日记】day03——双指针算法_有效三角形的个数、和为s的两个数字
611. 有效三角形的个数 611. 有效三角形的个数https://leetcode.cn/problems/valid-triangle-number/ 题目描述: 给定一个包含非负整数的数组 nums ,返回其中可以组成三角形三条边的三元组个数。 解题思路: 本题是一个关于三角形是否能成立…...
通过 kk 创建 k8s 集群和 kubesphere
官方文档:多节点安装 确保从正确的区域下载 KubeKey export KKZONEcn下载 KubeKey curl -sfL https://get-kk.kubesphere.io | VERSIONv3.0.7 sh -为 kk 添加可执行权限: chmod x kk创建 config 文件 KubeSphere 版本:v3.3 支持的 Kuber…...
感觉和身边其他人有差距怎么办?
虽然清楚知识需要靠时间沉淀,但在看到自己做不出来的题别人会做,自己写不出的代码别人会写时还是会感到焦虑怎么办? 你是否也因为自身跟周围人的差距而产生过迷茫,这份迷茫如今是被你克服了还是仍旧让你感到困扰? 下…...
【C语言基础】宏定义的用法详解
📢:如果你也对机器人、人工智能感兴趣,看来我们志同道合✨ 📢:不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 📢:文章若有幸对你有帮助,可点赞 👍…...
微服务系列文章之 SpringBoot 最佳实践
Spring Boot 是一种广泛使用且非常流行的企业级高性能框架。 以下是一些最佳实践和一些技巧,我们可以使用它们来改进 Spring Boot 应用程序并使其更加高效。 Spring Boot 的四大核心 1、自动配置 针对很多Spring应用程序和常见的应用功能,Spring Boo…...
C++并发多线程--std::async、std::packaged_task和std::promise的使用
目录 1--std::async的使用 2--std::packaged_task的使用 3--std::promise的使用 1--std::async的使用 std::async用于启动一个异步任务,并返回一个std::future对象;std::future对象里含有异步任务线程入口函数的结果; std::launch::deferr…...
opencv-目标追踪
import argparse import time import cv2 import numpy as np# 配置参数 ap argparse.ArgumentParser() ap.add_argument("-v", "--video", typestr,help"path to input video file") ap.add_argument("-t", "--tracker", …...
【数据结构】 单链表面试题讲解
文章目录 引言反转单链表题目描述示例:题解思路代码实现: 移除链表元素题目描述:示例思路解析: 链表的中间结点题目描述:示例:思路解析代码实现如下: 链表中倒数第k个结点题目描述示例思路解析&…...
C++ string类的模拟实现
模拟实现string类不是为了造一个更好的轮子,而是更加理解string类,从而来掌握string类的使用 string类的接口设计繁多,故而不会全部涵盖到,但是核心的会模拟实现 库中string类是封装在std的命名空间中的,所以在模拟…...
Qt实现简单的漫游器
文章目录 Qt的OpenGL窗口GLSL的实现摄像机类的实现简单的漫游器 Qt的OpenGL窗口 Qt主要是使用QOpenGLWidget来实现opengl的功能。 QOpenGLWidget 提供了三个便捷的虚函数,可以重载,用来重新实现典型的OpenGL任务: paintGL:渲染…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
