一文彻底理解python浅拷贝和深拷贝

目录

  • 一、必备知识
  • 二、基本概念
  • 三、列表,元组,集合,字符串,字典浅拷贝
    • 3.1 列表
    • 3.2 元组
    • 3.3 集合
    • 3.4 字符串
    • 3.5 字典
    • 3.6 特别注意
    • 可视化展示
    • 浅拷贝总结
  • 四、列表,元组,集合,字符串,字典深拷贝
    • 可视化展示
    • 结论

一、必备知识

  • 万物皆对象:在学习python的深浅拷贝之前我们必须要知道一个事情,就是python对象的引用,在python里面,万物皆对象,万物皆对象,万物皆对象,不管什么数据类型都是对象。我们定义一个变量并给这个变量赋值的时候赋的并不是这个对象值,而是这个对象引用,并不是一直值,如a = 1,这个时候并不是把1这个值赋给了a,而是把1这个对象的引用赋值给了a
  • 可变序列和不可变序列:可变序列就是可以直接对这个序列直接在原地址上进行数据修改,如果是不可变序列进行数据修改则会创建一个新的对象,让我这个变量重新指向新的对象。关于这部分不不懂的小伙伴可以参考下这篇博文:Python的可变类型与不可变类型,如果看完还是有不明白的地方可以评论区留言。

二、基本概念

  • 浅拷贝:浅拷贝会创建一个新的对象,但这个新对象的内可能是院对象的引用或者复制(视具体数据类型而言)。具体来说,如果原对象的元素是可变的(比如列表,字典,集合),浅拷贝会复制这些元素的引用,而不是元素本身。这意味着新对象和原对象会共享这些可变元素。如果对这些共享的元素进行修改,会影响到原对象。如果原对象的元素是不可变的(比如元组或字符串),浅拷贝则会复制这些元素的值,因为它们是不可变的,不会影响到原对象。浅拷贝通常有三种方式:自身构造器切片copy.copy()函数,不同数据类型(列表,元组,字典,集合 ,字符串)的浅拷贝会有差异,下面会逐一介绍。

  • 深拷贝:重新分配一块新的内存,创建一个新的对象,并将原对象中的元素以递归的方式通过创建新的子对象拷贝到新的对象中。新的对象和原对象之间没有任何关系。深拷贝使用copy.deepcopy()函数实现

  • python自带数据类型: 列表,元组,字典,集合,字符串

  • 必备工具网站:pythontutor

三、列表,元组,集合,字符串,字典浅拷贝

3.1 列表

  • 自身构造器:
>>> list1 = [1,2,3,4]
>>> list2 = list(list1)
>>> list2
[1, 2, 3, 4]
>>> id(list1)
140495553055488
>>> id(list2)
140495553080256
>>> list1==list2
True
  • 切片
>>> list1 = [1,2,3,4]
>>> list2 = list1[:]
>>> list2
[1, 2, 3, 4]
>>> list1 is list2
False
>>> list1 == list2
True
  • copy()函数
>>> import copy
>>> list1 = [1,2,3,4]
>>> list2 = copy.copy(list1)
>>> list1
[1, 2, 3, 4]
>>> list2
[1, 2, 3, 4]
>>> list1 is list2
False
>>> list1 == list2
True

注:python中的可变序列有自己的copy()方法,即对于列表和字典这种的对象可以使用list.copy()或者dict.copy()跟copy.copy()函数是等价的。

  • 总结:python列表可以使用三种方式进行浅拷贝:自身构造器,切片,copy()函数。浅拷贝之后两个变量的地址不一样,但是数值是一样的,

3.2 元组

  • 自身构造器
>>> a = (1,2,3,4)
>>> b = tuple(a)
>>> a
(1, 2, 3, 4)
>>> b
(1, 2, 3, 4)
>>> a is b
True
>>> a == b
True
  • 切片
>>> a = (1,2,3,4)
>>> b = a[:]
>>> a is b
True
>>> a == b
True
>>> a
(1, 2, 3, 4)
>>> b
(1, 2, 3, 4)
  • copy函数
>>> import copy
>>> a = (1,2,3,4)
>>> b = copy.copy(a)
>>> a
(1, 2, 3, 4)
>>> b
(1, 2, 3, 4)
>>> a is b
True
>>> a == b
True

3.3 集合

  • 自身构造器
>>> a = {1,2,3,4}
>>> b = set(a)
>>> a
{1, 2, 3, 4}
>>> b
{1, 2, 3, 4}
>>> a is b
False
>>> a == b
True
  • copy函数()
>>> import copy
>>> a = {1,2,3,4}
>>> b = copy.copy(a)
>>> a
{1, 2, 3, 4}
>>> b
{1, 2, 3, 4}
>>> a is b
False
>>> a ==b
True

3.4 字符串

  • 自身构造器
>>> a = "1234"
>>> b = str(a)
>>> a
'1234'
>>> b
'1234'
>>> a is b
True
>>> a == b
True
  • 切片
>>> a = "1234"
>>> b = a[:]
>>> a
'1234'
>>> b
'1234'
>>> a is b
True
>>> a == b
True
  • copy()
>>> import copy
>>> a = "1234"
>>> b = copy.copy(a)
>>> a
'1234'
>>> b
'1234'
>>> a is b
True
>>> a ==b
True

3.5 字典

  • 自身构造器
>>> dict1 = {"a":1, 1:2}
>>> dict2 = dict(dict1)
>>> dict1
{'a': 1, 1: 2}
>>> dict2
{'a': 1, 1: 2}
>>> dict1 is dict2
False
>>> dict1 == dict2
True
  • copy函数
>>> import copy
>>> dict1 = {"a":1, 1:2}
>>> dict2 = copy.copy(dict1)
>>> dict1
{'a': 1, 1: 2}
>>> dict2
{'a': 1, 1: 2}
>>> dict1 is dict2
False
>>> dict1 == dict2
True

3.6 特别注意

>>> list1 = [[1, 2], (30, 40)]
>>> list2 = list(list1)
>>> list1.append(100)
>>> list1
[[1, 2], (30, 40), 100]
>>> list2
[[1, 2], (30, 40)]
>>> list1[0].append(3)
>>> list1
[[1, 2, 3], (30, 40), 100]
>>> list2
[[1, 2, 3], (30, 40)]
>>> list1[1] += (50,60)
>>> list1
[[1, 2, 3], (30, 40, 50, 60), 100]
>>> list2
[[1, 2, 3], (30, 40)]
  • 如果是可变类型,浅拷贝之后一个变量改变不会影响到另一个,但是如果是不可变类型,一个改变了会影响到另一个同时改变。

可视化展示

  • 可变类型
list1 = [1,2,[3,4,[5,6]]]
list2 = list(list1)

dict1 = {"a":111, "b":{"c":222, "d":{"e":333}}}
dict2 = dict(dict1)

set1 = {1,2,3,4}
set2 = set(set1)

内存指向:
在这里插入图片描述

  • 可变和不可变
list1 = [1,2,[3,4, [5,6]]]
list2 = list1
list3 = list(list1)
print(id(list1))
print(id(list2))
print(id(list3))


tuple1 = (1,2,(3,4,(5,6)))
tuple2 = tuple(tuple1)
tuple3 = tuple1 + (7,8)
tuple4 = tuple1
tuple5 = tuple1[1:3]
print(id(tuple1))
print(id(tuple2))
print(id(tuple3))


str1 = "12'34'56''"
str2 = str1[1:5]
str3 = str1
str4 = str1[:]
print(id(str1))
print(id(str2))
print(id(str3))
print(id(str4))

a = 135346347458484
b = int(a)
b = 123

输出:

140007835258880
140007835258880
140007835581440
140007674106368
140007674106368
140007674089280
140007835585072
140007660015344
140007835585072
140007835585072

内存指向
在这里插入图片描述

浅拷贝总结

  • 可变数据类型的浅拷贝就是为新的变量重新分配一块内存空间,和原来变量的内存不一样,但是变量的值是一样的
  • 不可变数据类型不会发生浅拷贝,只是开辟了内存存储原对象的引用,而不是存储原对象的子对象的引用。
  • 要与赋值操作区分,赋值只是把原对象的引用赋值给了新的变量,相当于这两个变量指向同一个对象
  • 浅拷贝只改改变最外面一层的元素不会影响到原始数据(也就是最外层的数据是复制),改变内层元素则会影响原始数据(内层数据是引用)。
  • 可变类型会重新开辟一段内存,最外层元素互不影响,内层元素会指向原始的数据。不可变类型的数据发生完全浅拷贝(这里为了方便介绍理解成浅拷贝,实际上不可变类型不是浅拷贝,数据全部复制)时,新的变量和原始的变量的地址是一模一样的,如果是发生部分数据的复制或者增加数据的时候,则会新开辟一段空间。
  • 我们重点关注可变类型,因为不可变类型即使发生了浅拷贝或者赋值对我们后续使用没有任何影响,因为不可变类型数据不能被修改,一旦修改就重新开辟了一个新的内存来存储。

四、列表,元组,集合,字符串,字典深拷贝

可视化展示

  • 代码
import copy
list1 = [1,2,[3,4, [5,6]]]
list2 = copy.deepcopy(list1)
print(id(list1))
print(id(list2))


tuple1 = (1,2,(3,4,(5,6)))
tuple2 = copy.deepcopy(tuple1)
print(id(tuple1))
print(id(tuple2))

tuple3 = (1,2,[3,4], {"a":1})
tuple4 = tuple(tuple3)
tuple4[2].append(5)
tuple4[3]["a"] = 2

输出:

140347510384064
140347510378496
140347334201984
140347334201984
  • 可视化
    在这里插入图片描述

结论

  • 可变类型深拷贝之后新旧变量地址不一样,不可变类型不变

  • 元组类型比较特殊, 元组内部如果嵌套了 可变类型(list, dict)浅拷贝之后, 内部的值修改, 会影响拷贝之后的结果

  • 补充:函数传参的时候不可变类型是值传递,可变类型是传引用

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python+Robotframework实现http接口自动化测试详解

前言 下周即将展开一个http接口测试的需求,刚刚完成的java类接口测试工作中,由于之前犯懒,没有提前搭建好自动化回归测试框架,以至于后期rd每修改一个bug,经常导致之前没有问题的case又产生了bug,所以需要…

LED数码管的静态显示与动态显示(Keil+Proteus)

前言 就是今天看了一下书上的单片机实验,发现很多的器件在Proteus中都不知道怎么去查找,然后想做一下这个实验,尝试能不能实现,LED数码管的两个还可以实现,但是用LED点阵显示器的时候他那个网络标号不知道是什么情况&…

openGauss学习笔记-111 openGauss 数据库管理-管理用户及权限-用户权限设置

文章目录 openGauss学习笔记-111 openGauss 数据库管理-管理用户及权限-用户权限设置111.1 给用户直接授予某对象的权限111.2 给用户指定角色111.3 回收用户权限 openGauss学习笔记-111 openGauss 数据库管理-管理用户及权限-用户权限设置 111.1 给用户直接授予某对象的权限 …

【uniapp】uniapp实现input输入显示数字键盘:

文章目录 一、官网文档:二、文档:三、效果:【1】number:iPhone原生数字键盘不显示小数点【2】digit:【3】digit和inputmode: 一、官网文档: input | uni-app官网 二、文档: 三、效果…

正点原子嵌入式linux驱动开发——Linux 多点电容触摸屏

随着智能手机的发展,电容触摸屏也得到了飞速的发展。相比电阻触摸屏,电容触摸屏有很多的优势,比如支持多点触控、不需要按压,只需要轻轻触摸就有反应。ALIENTEK的三款RGB LCD屏幕都支持多点电容触摸,本章就以ATK7016这…

git命令清单

一、设置和配置 1.初始化一个新的仓库&#xff1a; git init2.克隆&#xff08;Clone&#xff09;一个远程仓库到本地&#xff1a; git clone <repository_url>3.配置用户信息&#xff1a; git config --global user.name "Your Name" git config --global…

matlibplot绘图设置标签角度

如下图所示&#xff0c;当我们绘图的时候有时候会遇到标注太长显示不全&#xff0c;这时候需要修改标注的角度来实现&#xff1a; **plt.xticks(rotation70)**设置x轴旋转70度 import matplotlib.pyplot as plt import numpy as np CHN[13.6081.06**i for i in range(1,31)] U…

C语言数组首地址学习1

C语言数组名也是数组首地址&#xff1b;数组首地址&#xff0c;也就是数组首元素地址&#xff1b; 数组首地址也可以用第0个元素加&表示&#xff0c;数值a的首地址是&a[0]&#xff1b; #include <stdio.h> int main(){int nums[5];int i;//从控制台读取用户输…

第20期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练 Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大型语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以…

安防视频监控平台EasyCVR前端解码与后端解码的区别介绍

视频监控平台/视频存储/视频分析平台EasyCVR基于云边端一体化管理&#xff0c;支持多类型设备、多协议方式接入&#xff0c;具体包括&#xff1a;国标GB28181协议、RTMP、RTSP/Onvif、海康Ehome&#xff0c;以及海康SDK、大华SDK、华为SDK、宇视SDK、乐橙SDK、萤石SDK等&#x…

基于英伟达NVIDIA Jetson Xavier nx的Ubuntu系统安装nginx,mysql, java8

记录一下基于英伟达NVIDIA Jetson Xavier nx的Ubuntu系统安装nginx&#xff0c;mysql&#xff0c; java8(非docker方式) nx系统主要用于开发ai边缘人工智能视觉计算&#xff0c;人脸识别&#xff0c;车辆识别等&#xff0c;同样的也可以部署一些常见的程序应用 nx系统界面 …

SQL注入——二次注入漏洞

文章目录 SQL注入——二次注入漏洞1. 二次注入原理2. 二次注入需要具备的两个条件3. 二次注入实例4. 总结 SQL注入——二次注入漏洞 1. 二次注入原理 在第一次插入恶意数据的时候&#xff0c;只是对其中的特殊字符进行了转义&#xff0c;在写入数据库的时候还是原来的字符&am…

分类预测 | Matlab实现KOA-CNN-GRU-selfAttention多特征分类预测(自注意力机制)

分类预测 | Matlab实现KOA-CNN-GRU-selfAttention多特征分类预测&#xff08;自注意力机制&#xff09; 目录 分类预测 | Matlab实现KOA-CNN-GRU-selfAttention多特征分类预测&#xff08;自注意力机制&#xff09;分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matla…

一文吃透低代码开发与传统IT开发的区别

目录 一、含义不同 二、开发门槛不同 三、两者之间的区别 1、从技术特征来看 2、从目标开发者来看 四、低代码平台使用感受&#xff1f; &#xff08;1&#xff09;自定义模块&#xff0c;满足不同的业务需求 &#xff08;2&#xff09;工作流引擎&#xff0c;简化复杂流程的管…

c++-set和map

文章目录 前言一、set容器1、set容器介绍2、set的使用2.1 set的构造函数和迭代器2.2 set的容量2.3 set修改操作 3、multiset容器3.1 multiset容器介绍3.2 multiset容器使用 二、map容器1、map容器介绍2、map容器使用2.1 map的构造函数与迭代器2.2 map中元素的修改2.3 map的容量…

ChatGPT 3.5只有200亿规模的参数?最新微软的论文暴漏OpenAI的ChatGPT的参数规模远低于1750亿!

本文来自DataLearnerAI官方网站&#xff1a;ChatGPT 3.5只有200亿规模的参数&#xff1f;最新微软的论文暴漏OpenAI的ChatGPT的参数规模远低于1750亿&#xff01; | 数据学习者官方网站(Datalearner)https://www.datalearner.com/blog/1051698672594665 2022年11月底发布的Cha…

数据库的事务四大特性(ACID)、详解隔离性以及隔离级别、锁

文章目录 &#x1f389;数据库的事务四大特性&#xff08;ACID&#xff09;以及隔离性一、事务的四大特性✨1、原子性&#xff08;Atomicity&#xff09;&#x1f38a;2、一致性&#xff08;Consistency&#xff09;&#x1f38a;3、隔离性&#xff08;Isolation&#xff09;&a…

TensorFlow案例学习:简单的音频识别

前言 以下内容均来源于官方教程&#xff1a;简单的音频识别&#xff1a;识别关键字 音频识别 下载数据集 下载地址&#xff1a;http://storage.googleapis.com/download.tensorflow.org/data/mini_speech_commands.zip 可以直接浏览器访问下载。 下载完成后将其解压到项目…

博彦科技:以金融为起点,凭借创新技术平台真打实干

【科技明说 &#xff5c; 重磅专题】 成立于1995年的博彦科技&#xff0c;已有28年左右的发展历程。 我没有想到&#xff0c;博彦科技也对AIGC领域情有独钟。博彦科技自研的数字人产品SaaS平台&#xff0c;可以接入包括百度文心一言、阿里通义千问等AI大模型产品。可见&#…

uniapp开发微信小程序uview里的u-upload组件上传图片点击没反应,开发者工具点击正常,正式上手机上点击没反应

项目场景&#xff1a; 用uniapp开发的微信小程序&#xff0c;uview插件ui&#xff0c;u-upload上传文件&#xff0c;上传头像等方法&#xff0c;早就审核发布过的突然反应上传图片&#xff0c;文件啥的点击没反应 问题描述 原因分析&#xff1a; 根据查资料得知可能是因为小程…