python之赋值、浅拷贝和深拷贝

2023-11-13

概念

python中的对象包含三个属性,id、type和value,id代表着对象唯一的标识符,是独一无二的,cpython中代表了存放对象的内存地址;type代表着对象的类型,比如说数字1的type就是int,字符串‘abc’的type就是str,这里还可以进一步去区分type()函数与isinstance()函数的区别,简单来说type函数不考虑继承,不会认为子类的对象属于父类,而isinstance函数考虑继承;value就是代表我们赋给对象的值。

深拷贝和浅拷贝来自于python的copy模块,可以通过import copy来导入该模块。
浅拷贝的语法为copy.copy(),深拷贝的语法为copy.deepcopy()。

变量及存储方式

值语义与引用语义

在高级语言中,变量的存储方式有两个,值语义和引用语义。

  • 对于值语义,大部分语言中都是一样的,把变量的值直接存放在变量的存储区里,这样一来,每个变量所需存储区的大小是不一样的,存放数字和存放字符串所需空间大小就不同,这就需要在给变量赋值时根据值的类型声明变量的类型,静态语言比如c,c++都有值语义。
  • 对于引用语义,变量中存储的只是值的引用,比如我们将整数1赋值给变量a,a中存储的是其值的引用(即地址),值1有另外的存储位置,这样做的好处是我们在给变量赋值时不需要提前声明,因为变量存储的是值对象的引用,那所有变量在内存中的大小都是一样的,就是一个地址。也被称为对象语义和指针语义。

python对象的存储方式

在python中,万物皆对象,采用的就是引用语义,赋给变量的值作为对象拥有自己的存储空间,赋值给变量,变量中存储的只是值对象的内存地址,而不是变量本身。

python中的对象可以简单的分为可变对象和不可变对象,基本数据类型比如int,float,bool是不可变的(python2中还有long),结构数据类型中,tuple,str是不可变对象,list,dict,set是可变对象,之所以是可变的,是因为变量中存储的是值对象的地址,值的地址里面存放的是元素值的地址,可以一直这样链式传递下去,所以我们对其进行内置操作(比如append,pop,remove等)都不会改变变量中存储的地址,也就表现为对象是可变的,比如说,a=[1, 2, 3],a存储的是对象[1, 2, 3]的地址,[1, 2, 3]中存储的是元素1,2,3的地址,因此要注意的是仅限于python的内置操作,别的操作比如赋值操作会改变变量的引用,即使与原来的数据一样。

 a = [1, 2, 3]
    print(id(a))
    a = [1, 2, 3]
    print(id(a))
    a.append(4)
    print(id(a), a)
    a.pop(0)
    print(id(a), a)
    b = [7, 8, 9]
    print(id(b))
    
    输出结果:
    6054472
    6054536
    6054536 [1, 2, 3, 4]
    6054536 [2, 3, 4]
    6054472

上述结果体现了python内置操作不会改变对象的引用,赋值操作会改变对象的引用,但是如果是c = a,那就没问题了,因为a本来就是存储着值对象的地址,赋值操作后,传递给c的实际上也是值对象的地址,所以id并不会变,有意思的是最后的b的id竟然与第一个a的id一样,这说明了当变量重新指向新的内存地址后,之前指向的内存就会被回收,建立新的变量时,又从程序自己的内存空间空间开始位置查找可分配的内存。

下面再看一个有意思的操作:

    a = [1, 2, 3]
    print(id(a))
    a[0] = 4
    print(id(a))
    a[2] = [1, 2, 3]
    print(id(a))
    
    输出结果:
    5071432
    5071432
    5071432

对列表中的元素进行赋值操作,并没有改变变量中存储的地址,但是按照前面的说法,赋值操作会改变变量指向的地址,这不是前后矛盾吗?

实际上并不矛盾,个人的理解是这样的:

前面我们也提到了,对于list这种复杂的数据结构,变量只是值对象的引用,存储值对象的地址,值对象中存储着各个元素的地址,因此,我们对元素进行赋值操作只是修改值对象中存储的单个的元素地址,并不涉及变量对值对象引用这一层面,所以变的只是元素的地址,变量的id不会变。

    a = [1, 2, 3]
    print(id(a), id(a[0]), id(
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python之赋值、浅拷贝和深拷贝 的相关文章

随机推荐

  • 用jemalloc代替glibc默认ptmalloc进一步提升服务器性能和负载

    启动redis时 无意中看到redis的启动信息有一个jemalloc的版本信息 处于好奇了解了一下 它是一个进一步提升服务器负载和性能的神器 一 Ptmalloc Linux 系统在装载 elf 格式的程序文件时 会调用 loader 把
  • win7下连接共享打印机的方法(终于解决了)

    1 首先一定要确保Spooler服务启动 2 随便找个添加打印机的地方 我是在控制面板找的 3 点击 添加打印机 后选择 添加网络打印机 进来一般来说搜不到你想要连接的打印机 这时候点击 我想要连接的打印机不再列表中 点击 通过共享选择一个
  • OnTriggerEnter 当进入触发器

    当Collider 碰撞体 进入trigger 触发器 时调用OnTriggerEnter 这个消息被发送到触发器碰撞体和刚体 或者碰撞体假设没有刚体 注意如果碰撞体附加了一个刚体 也只发送触发器事件 销毁所有进入触发器的物体 void O
  • 10.netty客户端与服务器使用protobuf传输报文

    README 本文总结自B站 尚硅谷 netty 很不错 内容如下 netty的编码器与解码器 netty客户端与服务器通过 protobuf 传输报文的开发方式 文末po出了所有代码 1 netty的编码器与解码器 codec 1 编解码
  • (1)docker的使用 阿里镜像 运行jar包 springboot

    前言 在运行jar包时 我的 中台 建议使用docker进行运行 于是查阅资料 将这个过程进行记录如下 对于入门小白 共勉 安装docker 由于是第一次安装 所以借鉴了大牛的帖子 当然 大牛帖子也有缺点 就是一旦被大家认可 更新不及时 该
  • BGP基础

    简述 在EGP协议中 引入了AS Autonomous System 自治系统 的概念 AS是指由同一个技术管理机构管理 使用统一选路策略的一些路由器的集合 AS的内部使用IGP来计算和发现路由 同一个AS内部的路由器之间是相互信任的 因此
  • win10笔记蓝屏VIDEO_DXGKRNL_ERROR解决思路

    今天笔记本插电正常开机 打开怪物猎人游戏后提示缺少DirectX11 很疑惑 因为以前从来没有报这个错 随后过了不久笔记本就蓝屏 且始终不会自己重新启动 网上查了查都说是显卡硬件的问题 说什么显卡烧坏了 让拿去线下售后店修理 说的都很玄乎
  • 30天入门Python(基础篇)——第2天:Python安装(保姆级)与IDE的认识与选择+详细安装教程

    文章目录 专栏导读 上一节课回顾 1 Python解释器的安装 查看各个版本的Python解释器 ok 双击安装 这里我们选择 自定义 安装 下面的 将Python添加在环境变量 大家一定要打个勾 点击 Next 进行下一步 这里不建议安装
  • 《C++ Primer》学习笔记

    这次一定要完整学完 2022 8 24 像编辑器一样思考和理解C C 的编程风格 C风格 基于对象 面向对象 泛型和基于组件 初学建议 C Primer 和 C 标准程序库 Scott Meyers的 Effective C Anthony
  • Direct local .aar file dependencies are not supported when building an AAR.

    前言 起因 项目中含有视频播放功能 使用的是GSYVideoPlayer 因为公司网络问题经常依赖添加不了 所以将关于它的aar包全部下载下来直接本地依赖 因为多个业务都可能涉及视频播放功能 为了复用 就想着将视频播放的功能提取出来 通过F
  • 计算机vfp系统,计算机等级考试VFP教程:第一章数据库系统

    1 数据处理 数据 是对事实 概念或指令的一种特殊表达形式 可以用人工的方式或自动化的装置进行通信 翻译转换或者进行加工处理 它包括两类 一类是能参与数字运算的数值型数据 一类是不能参与数字运算的非数值型数据 如文字 图画 声音 活动图象等
  • 动态扩容Linux根目录 (解决/dev/mapper/cl_192-root 占用了过高问题)

    相信大家在运维centos服务器的时候经常会遇到根目录空间不足的现象 今天本人就针对此问题给出一个调整root分区大小的方案 操作如下 1 首先 必须确保其他分区有足够的空间用来分给根目录 可以使用以下命令查看 sudo df h 可以看到
  • java addservlet_Java ServletContext.addServlet方法代碼示例

    本文整理匯總了Java中javax servlet ServletContext addServlet方法的典型用法代碼示例 如果您正苦於以下問題 Java ServletContext addServlet方法的具體用法 Java Ser
  • 设计模式之装饰模式

    网上说JDK中的I O设计是最标准的装饰模式 所以今天打算研究一些装饰模式 乍一看怎么感觉和代理模式这么像呢 1 为什么需要装饰模式 在不必改变原类文件和使用继承的情况下 动态地扩展一个对象的功能 它是通过创建一个包装对象 也就是装饰来包裹
  • 关于Keil不识别系统头文件core_cm3.h的问题

    之前遇到一次这个问题 解决了 之后又遇到一次就忘了之前是怎么解决的了 所以记录一下 所有不识别系统头文件的问题都可以用这种方式解决 找到你工程目录下的头文件 我以core cm3 h为例 这个头文件在STM32 LIBRARY CMSIS
  • 这8点能教你如何更好地阅读代码

    我讨厌阅读别人的代码 是所有经验层级上的软件开发人员之间普遍存在的问题 然而 这又是一个必要的技能 特别是对于开发人员进入到现有的代码库中的时候 如果你以正确的角度和正确的工具来处理它 这可能是一个愉快和有启发性的体验 我们讨厌阅读别人的代
  • 类变量类型

    1 局部变量 在方法 构造方法 语句块中定义的变量 其声明和初始化在方法中实现 在方法结束后自动销毁 public class ClassName public void printNumber int a 其他代码 2 成员变量 定义在类
  • 解决jar包启动关闭窗口后停止项目问题

    项目以jar形式部署到服务器 通常会以这样的形式 java jar zpw 2 2 5 RELEASE jar 问题 当我们一关闭当前窗口就会停止运行项目 解决思路 在后台运行 解决方法 nohup java jar zpw 2 2 5 R
  • 计算次对角线元素平均值、折半查找(二分查找)、冒泡排序

    一 计算次对角线元素平均值 首先从键盘输入方阵的行数n 然后输入n行n列的整数保存到数组a中 最后计算方阵中次对角线元素的平均值并输出 输入格式 第一行输入方阵行数n 以下n行每行输入n个整数 以空格间隔 输出格式 输出平均值 保留两位小数
  • python之赋值、浅拷贝和深拷贝

    概念 python中的对象包含三个属性 id type和value id代表着对象唯一的标识符 是独一无二的 cpython中代表了存放对象的内存地址 type代表着对象的类型 比如说数字1的type就是int 字符串 abc 的type就