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

简单理解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&#xff08…...

mysql自定义实体类框架

根据表结构自动生产实体类和方法,根据反射与io生成,可自定义扩展方法 package com.digital.web.front; /*** pom依赖* <dependency>* <groupId>mysql</groupId>* <artifactId>mysql-connector-java</artifactId>* <version>5.1.27</ve…...

批量将Excel中的第二列内容从拼音转换为汉字

要批量将Excel中的第二列内容从拼音转换为汉字&#xff0c;您可以使用Python的openpyxl库来实现。下面是一个示例代码&#xff0c;演示如何读取Excel文件并将第二列内容进行拼音转汉字&#xff1a; from openpyxl import load_workbook from xpinyin import Pinyin # 打开Exce…...

消息推送:精准推送,提升运营效果,增添平台活力

对于app开发者而言&#xff0c;没有什么途径比消息推送更能直接、即时地触及目标用户群体了。消息推送与我们的日常生活息息相关&#xff0c;各种APP的状态和通知都通过消息推送来告知用户&#xff0c;引起用户的注意&#xff0c;吸引用户点开app。总而言之&#xff0c;推送服务…...

[保研/考研机试] KY43 全排列 北京大学复试上机题 C++实现

题目链接&#xff1a; 全排列https://www.nowcoder.com/share/jump/437195121692001512368 描述 给定一个由不同的小写字母组成的字符串&#xff0c;输出这个字符串的所有全排列。 我们假设对于小写字母有a < b < ... < y < z&#xff0c;而且给定的字符串中的字…...

Java将时间戳转化为特定时区的日期字符串

先上代码&#xff1a; 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/ 题目描述&#xff1a; 给定一个包含非负整数的数组 nums &#xff0c;返回其中可以组成三角形三条边的三元组个数。 解题思路&#xff1a; 本题是一个关于三角形是否能成立…...

通过 kk 创建 k8s 集群和 kubesphere

官方文档&#xff1a;多节点安装 确保从正确的区域下载 KubeKey export KKZONEcn下载 KubeKey curl -sfL https://get-kk.kubesphere.io | VERSIONv3.0.7 sh -为 kk 添加可执行权限&#xff1a; chmod x kk创建 config 文件 KubeSphere 版本&#xff1a;v3.3 支持的 Kuber…...

感觉和身边其他人有差距怎么办?

虽然清楚知识需要靠时间沉淀&#xff0c;但在看到自己做不出来的题别人会做&#xff0c;自己写不出的代码别人会写时还是会感到焦虑怎么办&#xff1f; 你是否也因为自身跟周围人的差距而产生过迷茫&#xff0c;这份迷茫如今是被你克服了还是仍旧让你感到困扰&#xff1f; 下…...

【C语言基础】宏定义的用法详解

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…...

微服务系列文章之 SpringBoot 最佳实践

Spring Boot 是一种广泛使用且非常流行的企业级高性能框架。 以下是一些最佳实践和一些技巧&#xff0c;我们可以使用它们来改进 Spring Boot 应用程序并使其更加高效。 Spring Boot 的四大核心 1、自动配置 针对很多Spring应用程序和常见的应用功能&#xff0c;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用于启动一个异步任务&#xff0c;并返回一个std::future对象&#xff1b;std::future对象里含有异步任务线程入口函数的结果&#xff1b; 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", …...

【数据结构】 单链表面试题讲解

文章目录 引言反转单链表题目描述示例&#xff1a;题解思路代码实现&#xff1a; 移除链表元素题目描述&#xff1a;示例思路解析&#xff1a; 链表的中间结点题目描述&#xff1a;示例&#xff1a;思路解析代码实现如下&#xff1a; 链表中倒数第k个结点题目描述示例思路解析&…...

C++ string类的模拟实现

模拟实现string类不是为了造一个更好的轮子&#xff0c;而是更加理解string类&#xff0c;从而来掌握string类的使用 string类的接口设计繁多&#xff0c;故而不会全部涵盖到&#xff0c;但是核心的会模拟实现 库中string类是封装在std的命名空间中的&#xff0c;所以在模拟…...

Qt实现简单的漫游器

文章目录 Qt的OpenGL窗口GLSL的实现摄像机类的实现简单的漫游器 Qt的OpenGL窗口 Qt主要是使用QOpenGLWidget来实现opengl的功能。  QOpenGLWidget 提供了三个便捷的虚函数&#xff0c;可以重载&#xff0c;用来重新实现典型的OpenGL任务&#xff1a; paintGL&#xff1a;渲染…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

基础测试工具使用经验

背景 vtune&#xff0c;perf, nsight system等基础测试工具&#xff0c;都是用过的&#xff0c;但是没有记录&#xff0c;都逐渐忘了。所以写这篇博客总结记录一下&#xff0c;只要以后发现新的用法&#xff0c;就记得来编辑补充一下 perf 比较基础的用法&#xff1a; 先改这…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

MySQL JOIN 表过多的优化思路

当 MySQL 查询涉及大量表 JOIN 时&#xff0c;性能会显著下降。以下是优化思路和简易实现方法&#xff1a; 一、核心优化思路 减少 JOIN 数量 数据冗余&#xff1a;添加必要的冗余字段&#xff08;如订单表直接存储用户名&#xff09;合并表&#xff1a;将频繁关联的小表合并成…...