图解Python深拷贝和浅拷贝

news2025/1/12 1:00:15

Python中,对象的赋值,拷贝(深/浅拷贝)之间是有差异的,如果使用的时候不注意,就可能产生意外的结果。

下面本文就通过简单的例子介绍一下这些概念之间的差别。

对象赋值

直接看一段代码:

will = ["Will", 28, ["Python", "C#", "JavaScript"]]
wilber = will
print id(will)
print will
print [id(ele) for ele in will]
print id(wilber)
print wilber
print [id(ele) for ele in wilber]

will[0] = "Wilber"
will[2].append("CSS")
print id(will)
print will
print [id(ele) for ele in will]
print id(wilber)
print wilber
print [id(ele) for ele in wilber]

代码的输出为:

下面来分析一下这段代码:

  • 首先,创建了一个名为will的变量,这个变量指向一个list对象,从第一张图中可以看到所有对象的地址(每次运行,结果可能不同)
  • 然后,通过will变量对wilber变量进行赋值,那么wilber变量将指向will变量对应的对象(内存地址),也就是说"wilber is will","wilber[i] is will[i]"

    • 可以理解为,Python中,对象的赋值都是进行对象引用(内存地址)传递
  • 第三张图中,由于will和wilber指向同一个对象,所以对will的任何修改都会体现在wilber上

    • 这里需要注意的一点是,str是不可变类型,所以当修改的时候会替换旧的对象,产生一个新的地址39758496

浅拷贝

下面就来看看浅拷贝的结果:

import copy

will = ["Will", 28, ["Python", "C#", "JavaScript"]]
wilber = copy.copy(will)

print id(will)
print will
print [id(ele) for ele in will]
print id(wilber)
print wilber
print [id(ele) for ele in wilber]

will[0] = "Wilber"
will[2].append("CSS")
print id(will)
print will
print [id(ele) for ele in will]
print id(wilber)
print wilber
print [id(ele) for ele in wilber]

代码结果为:

分析一下这段代码:

  • 首先,依然使用一个will变量,指向一个list类型的对象
  • 然后,通过copy模块里面的浅拷贝函数copy(),对will指向的对象进行浅拷贝,然后浅拷贝生成的新对象赋值给wilber变量

    • 浅拷贝会创建一个新的对象,这个例子中"wilber is not will"
    • 但是,对于对象中的元素,浅拷贝就只会使用原始元素的引用(内存地址),也就是说"wilber[i] is will[i]"
  • 当对will进行修改的时候

    • 由于list的第一个元素是不可变类型,所以will对应的list的第一个元素会使用一个新的对象39758496
    • 但是list的第三个元素是一个可不类型,修改操作不会产生新的对象,所以will的修改结果会相应的反应到wilber上

总结一下,当我们使用下面的操作的时候,会产生浅拷贝的效果:

  • 使用切片[:]操作
  • 使用工厂函数(如list/dir/set)
  • 使用copy模块中的copy()函数

深拷贝

最后来看看深拷贝:

import copy

will = ["Will", 28, ["Python", "C#", "JavaScript"]]
wilber = copy.deepcopy(will)

print id(will)
print will
print [id(ele) for ele in will]
print id(wilber)
print wilber
print [id(ele) for ele in wilber]

will[0] = "Wilber"
will[2].append("CSS")
print id(will)
print will
print [id(ele) for ele in will]
print id(wilber)
print wilber
print [id(ele) for ele in wilber]

代码的结果为:

分析一下这段代码:

  • 首先,同样使用一个will变量,指向一个list类型的对象
  • 然后,通过copy模块里面的深拷贝函数deepcopy(),对will指向的对象进行深拷贝,然后深拷贝生成的新对象赋值给wilber变量

    • 跟浅拷贝类似,深拷贝也会创建一个新的对象,这个例子中"wilber is not will"
    • 但是,对于对象中的元素,深拷贝都会重新生成一份(有特殊情况,下面会说明),而不是简单的使用原始元素的引用(内存地址)

      • 例子中will的第三个元素指向39737304,而wilber的第三个元素是一个全新的对象39773088,也就是说,"wilber[2] is not will[2]"
  • 当对will进行修改的时候

    • 由于list的第一个元素是不可变类型,所以will对应的list的第一个元素会使用一个新的对象39758496
    • 但是list的第三个元素是一个可不类型,修改操作不会产生新的对象,但是由于"wilber[2] is not will[2]",所以will的修改不会影响wilber

拷贝的特殊情况

其实,对于拷贝有一些特殊情况:

  • 对于非容器类型(如数字、字符串、和其他'原子'类型的对象)没有拷贝这一说

    • 也就是说,对于这些类型,"obj is copy.copy(obj)" 、"obj is copy.deepcopy(obj)"
  • 如果元祖变量只包含原子类型对象,则不能深拷贝,看下面的例子

    

总结

本文介绍了对象的赋值和拷贝,以及它们之间的差异:

  • Python中对象的赋值都是进行对象引用(内存地址)传递
  • 使用copy.copy(),可以进行对象的浅拷贝,它复制了对象,但对于对象中的元素,依然使用原始的引用.
  • 如果需要复制一个容器对象,以及它里面的所有元素(包含元素的子元素),可以使用copy.deepcopy()进行深拷贝
  • 对于非容器类型(如数字、字符串、和其他'原子'类型的对象)没有被拷贝一说
  • 如果元祖变量只包含原子类型对象,则不能深拷贝,看下面的例子

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

蓝桥杯:数字三角形

目录 题目描述 输入描述 输出描述 输入输出样例 输入 输出 思路: AC代码(Java): 题目描述 上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个…

数据结构基础--排序

一、直接插入排序 思路: 直接插入排序是一种简单的插入排序法 其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一 个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。 直接插入排序的特性总…

二分查找算法

目录 一 算法简介 1)算法解释 2)前提 3)思想 4)分类 5)算法模板 mid的计算的实现方法 二分法模板 求某个数的平方根: 二 算法实践 1)问题引入 2)问题解答 1)解法一:左闭…

[附源码]Node.js计算机毕业设计关山社区居民信息管理系统Express

项目运行 环境配置: Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术: Express框架 Node.js Vue 等等组成,B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境:最好是Nodejs最新版,我…

Nacos认证绕过漏洞(CVE-2021-29441)

Nacos认证绕过漏洞(CVE-2021-29441) 指纹识别 titlenacos漏洞范围 nacos1.2.0版本-nacos1.4.0版本 漏洞复现 靶机ip:192.168.1.4 默认的nacos登录界面 http://192.168.1.14:8848/nacos/#/login利用如下请求包查看只有一个nacos用户 GET /nacos/v…

ZBC陆续在主要CEX开启Staking,锁定市场大部分流通量成大利好

从2022年Q3开始,Zebec生态开始不断的迎来新的利好,比如以 10 亿美元的完全稀释估值筹集了 850 万美元,使其历史融资额超过4000万美元,引发ZBC通证的一波上涨。而在此后,Zebec 生态开启了从Solana生态的迁移&#xff0c…

Eclipse+Java+Swing+mysql实现学生宿舍管理系统

EclipseJavaSwingmysql实现学生宿舍管理系统一、系统介绍1.环境配置二、系统展示1.登录页2.学生主页面3.学生端-登记页面4.学生端-学生信息修改5.学生端-寝室信息查询6.学生端-学生信息查询7.学生端-退出登录8.管理员-主页面9.管理员-宿舍信息修改10.管理员-宿舍信息删除11.管理…

JQuery | 系统性学习 | 无知的我费曼笔记

无知的我已经复盘完成JQuery 。。。 文章目录JQuery概述入口函数特性-隐式迭代Dom和JQuery区别互相转化JQuery选择器基本和层级选择器筛选选择器后缀筛选方法筛选应用排他思想应用链式编程JQuery操作样式修改样式CSS修改类名JQuery效果基础效果显示效果隐藏效果切换效果滑动效果…

Springboot 使用redis检测浏览量,评论量,点赞量的变化并完成与mysql的交互(有具体实现,有具体需求)

目录 依赖 准备实体类与业务类 开始正题 实现一览 流程一览 具体实现 1 初始化 2 写浏览量增加的方法 3 在切面处检测浏览器变化 4 新增文章时将新的数据写入redis 5 删除文章时将数据从Redis中删除 6 书写将数据写入mysql数据库的方法 7 销毁的时候将数据写入my…

一文搞懂百万富翁问题

百万富翁问题1. 解决方案2. 协议描述3. 协议说明4. 协议举例两个百万富翁Alice和Bob想知道他们两个谁更富有,但他们都不想让对方及其他第三方知道自己财富的任何信息,这是由中国计算机科学家、2000年图灵奖获得者姚启智教授于1982年在论文《Protocols fo…

新手小白做跨境电商有哪些注意的地方?

近两年,受疫情刺激,线上电商出现前所未有的高速增长,中国品牌纷纷出海,跨境电商腾飞。此外,国内电商市场发展趋于平淡,市场需求不断萎缩,也让越来越多的大卖家和平台盯上了这块大蛋糕。不仅中小…

300左右半入耳蓝牙耳机推荐:南卡、漫步者、JBL蓝牙耳机谁值得入手?

现在的年轻人,出门都会随身携带的一副蓝牙耳机,所以很多品牌商加入其中,导致大多数人选购难度变大,很多人总是不知道哪个不知道品牌蓝牙耳机最好,半入耳式蓝牙耳机相比入耳式蓝牙耳机有着天然的舒适性,因而…

如何利用MOS管设计一个LED亮度可调电路

首先大家可以看下下面的MOS管亮度可调的演示视频 如何利用MOS管设计一个LED亮度可调电路这个电路大致电路图如下 MOS管的栅极放了一个电容,当按按键1的时候,电源通过R1给电容充电,,MOS管栅极的电压慢慢增大,流过MOS管的…

计算机毕业设计HTML+CSS+JavaScript——基于HTML花店购物网站项目的设计与实现

常见网页设计作业题材有 个人、 美食、 公司、 学校、 旅游、 电商、 宠物、 电器、 茶叶、 家居、 酒店、 舞蹈、 动漫、 服装、 体育、 化妆品、 物流、 环保、 书籍、 婚纱、 游戏、 节日、 戒烟、 电影、 摄影、 文化、 家乡、 鲜花、 礼品、 汽车、 其他等网页设计题目, A…

Essential singularity

In complex analysis, an essential singularity of a function is a “severe” singularity near which the function exhibits odd behavior. The category essential singularity is a “left-over” or default group of isolated singularities that are especially unm…

跳转指令 —— B、BL

跳转指令可以跳转到标号的下一条指令,本质就是修改了PC寄存器的值。(标号并非指令,只是用来定位,相当于记录了当前位置的下一条指令的地址) 这里的MAIN就是一个标号 MAIN: MOV R1, #1 这里的FUNC就是一个标…

实验3 路由器基本配置及路由配置

实验3 路由器基本配置及路由配置一、实验目的二、实验要求三、实验步骤,数据记录及处理四.实验总结一、实验目的 1、路由器几种模式。 2、基本的配置命令。 3、路由器各接口的配置方法。 4、会查看检测接口状态。 二、实验要求 写出自己学习使用了哪些…

Redis框架(十五):大众点评项目 共同关注方案实现?双指针筛选DB数据:Redis取交集

大众点评项目 好友关注 共同关注需求:好友关注 共同关注业务逻辑展示点击关注功能实现判断当前用户是否关注了此博主共同好友列表查询业务逻辑实现双指针筛选DB数据Redis取交集总结SpringCloud章节复习已经过去,新的章节Redis开始了,这个章节…

字节一面:select......for update会锁表还是锁行?

select查询语句是不会加锁的,但是select .......for update除了有查询的作用外,还会加锁呢,而且它是悲观锁。 那么它加的是行锁还是表锁,这就要看是不是用了索引/主键。 没用索引/主键的话就是表锁,否则就是是行锁。…

sklearn基础篇(十)-- 非负矩阵分解与t-SNE

1 非负矩阵分解(NFM) NMF(Non-negative matrix factorization),即对于任意给定的一个非负矩阵V\pmb{V}VVV,其能够寻找到一个非负矩阵W\pmb{W}WWW和一个非负矩阵H\pmb{H}HHH,满足条件VW∗H\pmb{VW*H}VW∗HVW∗HVW∗H,从而将一个非负的矩阵分解…