python深浅拷贝

2023-10-29

转自:https://zhuanlan.zhihu.com/p/258097244

只为记录,侵删

在讲深浅拷贝之前,想先讲一下 is 和 == 的区别。

在进行对象是否相等比较的时候我们可以用 is 和 ==

  • is: 比较两个对象的引用是否相同,即 它们的id 是否一样
  • == : 比较两个对象的值是否相同。

id() ,是Python的一个内置函数,返回对象的唯一标识,用于获取对象的内存地址。

如下

a = 1
b = 1

print(id(a)) # 2057422768
print(id(b)) # 2057422768
print(a is b) # True

首先,会为整数1分配一个内存空间。 变量a 和 b 都指向了这个内存空间(内存地址相等),所以他们的id相等。

a is b 为 True

但是,真的所有整数数字都这样吗? 答案是:不是! 只有在 -25 ~ 256范围中的整数才不会重新分配内存空间。

如下所示:

因为257 超出了范围,所以id不相同,所以 a is b 返回的值为False。

>>> a = 257
>>> b = 257
>>> print(id(a))
20004752
>>> print(id(b))
20001312
>>> print(a is b)
False
>>> print(a == b)
True

这样做是考虑到性能,Python对-5 到 256 的整数维护了一个数组,相当于一个缓存, 当数值在这个范围内,直接就从数组中返回相对应的引用地址了。如果不在这个范围内,会重新开辟一个新的内存空间。

is 和 == 哪个效率高?

相比之下, is 比较的效率更高,因为它只需要判断两个对象的id是否相同即可。

== 则需要重载__eq__ 这个函数,遍历变量中的所有元素内容,逐次比较是否相同。因此效率较低

浅拷贝 深拷贝

简单的了解了 is== , 下面我们一起来看看Python中的深浅拷贝。

先说结论吧:

  • 浅拷贝: 拷贝的是对象的引用,如果原对象改变,相应的拷贝对象也会发生改变

  • 深拷贝: 拷贝对象中的每个元素,拷贝对象和原有对象不在有关系,两个是独立的对象

浅拷贝

a = [1, 2, 3]
b = list(a)  # 可以通过list 对列表进行浅拷贝
c = a.copy() # 也可以通过copy函数进行拷贝

# 浅拷贝后,a/b/c的id 各不相同,说明指向了不同的内存地址-- 即 生成了新的对象
print(id(a)) # 16301992
print(b, "id:", id(b)) # id:16562024
print(c, "id:", id(c)) # id:16561960

print(a == b) # True  值相同 返回True
print(a is b) # False  id不同所以 is比较返回False

# 给列表a 添加元素4
a.append(4)
print(a) # [1, 2, 3, 4]
print(b, c) # [1, 2, 3] [1, 2, 3]  b和c 不受影响

以上可以看出,浅拷贝会分配一个新的内存空间,创建一个新的对象。但是如果被拷贝对象中有可变对象会怎么样呢? 看下面的代码

a = [, 2, [3, 4]]
b = a.copy()

print(id(a)) # 23967528
print(id(b)) # 21738984
# 改变a中的可变对象
a[-1].append(5)
print(a)

# 在给a新增元素6
a.append(6)

# [1, 2, [3, 4, 5], 6]
print(a)

# [1, 2, [3, 4, 5]]
print(b)

可以看出,在列表a中新增的元素6,并没有影响b。但是在a的嵌套列表中新增的元素5,却影响了元素b。

原因在于: 对于a和b都指向了同一个列表[3, 4]。 所以当a中在列表新增元素5的时候,改变了那个列表的值,b也指向了那个列表,所以也会发生改变。

再看看下面的代码

a = [1, 2, (3, 4)]
b = a.copy()

print(id(a)) # 59162536
print(id(b)) # 60143400
# 改变a中的可变对象
a[-1] += (5, )

# [1, 2, (3, 4, 5)]
print(a)

# [1, 2, (3, 4)]
print(b)

对于元组(3, 4),因为元组不可变,所以在元组中新增了元素5,实际上是生成了新的元组对象。而b列表中的元组引用并没有发生改变。

通过上面的两个例子可以看出浅拷贝可能会带来的弊端,在使用中需要大家进行相应的判断。或者去完整的拷贝某个对象,即 深拷贝。

深拷贝

所谓深拷贝呢,就是重新分配一个内存空间(新对象),将原对象中的所有元素通过递归的方式进行拷贝到新对象中。

在Python中 通过 copy.deepcopy() 来实现深拷贝。

import copy
a = [1, 2, (3, 4)]
# 深拷贝
b = copy.deepcopy(a)

# 因为生成了新的对象所以,返回False
print(a is b)


a[-1] += (5,)
a.append(6)

print(a) # [1, 2, (3, 4, 5), 6]
print(b) # [1, 2, (3, 4)] 深拷贝后的对象,根本不受原对象的任何影响
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python深浅拷贝 的相关文章

随机推荐

  • angular.js官方文档的一些说明

    由于angular phonecat那个项目更新了 中文翻译资料很多还是之前版本的 用起来会有问题 自己也碰到一些坑 在此说明下 windows 1 node js官网下载node的安装包 http nodejs org dist v0 1
  • PWN学习---1、基本漏洞-缓冲区溢出

    环境 Ubuntu12 04 32位 一 存在漏洞代码 vuln c include
  • p值小于0.05拒绝还是接受_计算p-值和第二类错误

    专栏里有一篇 两类错误弃真与取假 对显著性水平 P value 第二类错误 功效进行了解释 这里换种行文说 并给出具体计算例子 用来增加对这几个概念的认识和理解 首先我们要清楚我们手上只有一份容量为 的样本 实践中希望通过该份样本进行统计推
  • 老司机教你如何用Unity和Cardboard把3D游戏做成VR游戏

    原网址 随着Oculus宣布1月6日开启预售 2016年很可能成为VR游戏元年 但很多的调研显示 手游设备才是市场增长的关键 SuperData发布的报告显示 2016年全球VR游戏市场规模预计在51亿美元左右 消费者设备安装量在3890万
  • 你一定要知道的那些以太坊术语解释

    block 区块 包含交易 0或多个 父区块 parent hash及其他数据的数据包 在区块链中 除创世区块的每个区块都要包含其父区块的hash 整个区块链包含一个网络的所有交易历史 注意 有些基于区块链的加密货币自称 账本 而非 区块链
  • HashMap底层原理分析

    HashMap的实现原理在Jdk1 7之前底层实现是基于数组 链表的形式 即通过HashMap的key值进行Hash 然后对容量 默认16 负载因子 默认是0 75 进行取余获取到其桶的位置 比如某一个key的hash值是18 容量为为16
  • C语言if语句,for循环相关年月日应用

    文章目录 一 if双分支语句变成单分支语句 1 if单分支语句 2 if双分支语句 3 if双分支语句改成单分支语句 二 采用冒泡排序法对n个数据排序 编写n个元素数组 用冒泡排序法进行排序 三 输入一个年份 判断是不是闰年 1 满足两个条
  • 俞敏洪演讲:创业不需要有钱 只需想着挣钱

    各位朋友大家下午好 上午我坐下面我发现我跟郭凡生郭总很大不同 他认为他自己很聪明 而我恰恰认为自己不聪明 我呢认为自己也不一定笨 他认为他很有吸引力 确实是对三四十岁的中年人来说 郭总很有创业热情 因为这个年龄的人 能够用那样的语气语调 两
  • RabbitMQ(八)【高级 - 过期时间 TTL】

    八 RabbitMQ高级 过期时间 TTL 上一篇文章 SpringBoot案例 概述 过期时间 TTL 表示可以对消息设置预期的时间 在这个时间内都可以被消费者接收获取 过了之后消息将自动被删除 RabbitMQ可以对 消息和队列 设置
  • 技术博客?

    我认为技术博客是一个非常好的工具 能够帮助我们更好地学习和理解各种技术 同时还能够帮助我们建立自己的品牌和声誉 在我的博客中 我会分享各种最新的技术 开发工具 以及一些我在实际项目中的经验和教训 我的博客主题主要分为以下几个方面 1 前端开
  • 如何高效解决问题?

    前言 我相信很多人在生活中和工作中都会遇到大大小小的问题 每个人解决问题的效率和思维都是有差别的 那么怎么样才能高效解决问题呢 其实问题的产生 从现象到逻辑 考验着我们的知识储备 磨砺着能力的段位 训练着思维的灵活度 从现象到方法论 5W1
  • Elasticsearch学习系列之term和match查询 Elasticsearch查询模式

    Elasticsearch查询模式 一种是像传递URL参数一样去传递查询语句 被称为简单查询 GET library books search 查询index为library type为books的全部内容 GET library book
  • Bean的自动装配 Spring使用注解开发

    Bean的自动装配 自动装配是Spring满足bean依赖的一种方式 Spring会在上下文自动寻找 并自动给bean装配 1 在xml中显示的配置 2 在java中显示的配置 3 隐式 的自动装配bean 重要 测试 autowire b
  • GPT-3 模型

    GPT 3 Generative Pre training Transformer 3 是由 OpenAI 开发的一种大型语言生成模型 它可以用来进行文本生成 翻译 问答等任务 GPT 3 使用了 Transformer 架构 并在大量的网
  • day14-多线程01

    1 实现多线程 1 1简单了解多线程 理解 是指从软件或者硬件上实现多个线程并发执行的技术 具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程 提升性能 1 2并发和并行 理解 并行 在同一时刻 有多个指令在多个CPU上同时执行
  • [4G/5G/6G专题基础-160]: BLER与MCS的关系、MCS表格的选择

    目录 第1章 什么是MCS 1 1 基本概念 1 2 三张不同的MCS表 1 3 MCS表的选择 1 4 MCS index的选择 第2章 什么是BLER 2 1 什么是比特误码率BER 2 2 什么是BLER 第3章 BLER与MCS的关
  • 机器学习——建筑能源得分预测

    前言 编码之前是了解我们试图解决的问题和可用的数据 在这个项目中 我们将使用公共可用的纽约市的建筑能源数据 目标是使用能源数据建立一个模型 来预测建筑物的Enerqy Star Score 能源之星分数 并解释结果以找出影响评分的因素 数据
  • 运维必学

    欢迎关注 全栈工程师修炼指南 专注 企业运维实践 网络安全 系统运维 应用开发 物联网实战 全栈文章 等知识分享 设为 星标 每天带你 基础入门 到 进阶实践 再到 放弃学习 作者主页 https www weiyigeek top 博客
  • 猫狗大战 python_猫狗大战

    这个项目我们要做一个识别猫狗的模型 这和上次的数字识别一样 也是运用深度学习 不过这次模型较为复杂 我们会用到迁移学习 站在巨人的肩膀上 借用大佬们已经训练好的模型来搭建我们自己的模型并让它做我们想做的事 安装要求Python3 Numpy
  • python深浅拷贝

    转自 https zhuanlan zhihu com p 258097244 只为记录 侵删 在讲深浅拷贝之前 想先讲一下 is 和 的区别 在进行对象是否相等比较的时候我们可以用 is 和 is 比较两个对象的引用是否相同 即 它们的i