QA测试开发工程师面试题满分问答3: python的深拷贝和浅拷贝问题

在 Python 中,深拷贝(deep copy)和浅拷贝(shallow copy)是用于创建对象副本的两种不同方式。

  • 浅拷贝是创建一个新的对象,该对象与原始对象的内容相同(包括内部嵌套对象的引用),但是它们指向相同的内存地址。换句话说,浅拷贝创建了一个对象的表面副本,而不是递归复制所有嵌套对象。当原始对象包含可变对象(如列表、字典)时,对副本进行修改可能会影响原始对象。
  • 深拷贝是创建一个全新的对象,该对象与原始对象内容相同,包括所有嵌套对象。深拷贝递归地复制所有嵌套对象,而不仅仅是创建一个表面副本。因此,对深拷贝对象的修改不会影响原始对象。

下面是深拷贝和浅拷贝的用途:

  1. 浅拷贝适用于需要创建一个对象的快速副本,但不需要对副本进行深层次的修改。它可以节省内存和复制时间,特别是当对象包含大量数据或嵌套对象时。
  2. 深拷贝适用于需要创建一个完全独立的对象,以便对副本进行修改而不会影响原始对象。它用于确保对象及其所有嵌套对象在修改时的独立性。

在 Python 中,可以使用 copy 模块来执行深拷贝和浅拷贝操作。以下是示例代码:

import copy

# 浅拷贝示例
original_list = [1, 2, [3, 4]]
shallow_copy = copy.copy(original_list)

# 修改浅拷贝对象的嵌套列表
shallow_copy[2][0] = 5

print(original_list)  # 输出: [1, 2, [5, 4]]
print(shallow_copy)  # 输出: [1, 2, [5, 4]]

# 深拷贝示例
deep_copy = copy.deepcopy(original_list)

# 修改深拷贝对象的嵌套列表
deep_copy[2][1] = 6

print(original_list)  # 输出: [1, 2, [5, 4]]
print(deep_copy)  # 输出: [1, 2, [5, 6]]

在上述示例中,我们首先对一个包含嵌套列表的原始列表进行浅拷贝和深拷贝操作。然后,修改拷贝后的对象的嵌套列表的值。可以看到,浅拷贝对象的嵌套列表修改也影响了原始列表,而深拷贝对象的修改不会影响原始列表。

可能遇到的问题

在进行深拷贝和浅拷贝时,可能会遇到以下问题:

  1. 嵌套对象的共享引用:浅拷贝只复制了对象的引用,而不是创建嵌套对象的副本。这意味着如果对浅拷贝对象中的嵌套对象进行修改,原始对象也会受到影响。这可能导致意外的副作用。

  2. 无限递归:如果存在循环引用或互相引用的对象,进行深拷贝时可能会导致无限递归。这会导致程序进入无限循环并最终引发 "RecursionError" 异常。

  3. 可变对象的修改:无论是深拷贝还是浅拷贝,如果复制的对象包含可变对象(如列表或字典),对副本进行修改可能会影响原始对象。这是因为副本和原始对象引用同一个可变对象。

  4. 性能和内存消耗:深拷贝涉及递归地复制所有嵌套对象,这可能对性能和内存消耗产生一定影响,特别是在处理大型对象或嵌套层次较深的对象时。

一个重要问题:嵌套列表内的引用是相同的

当进行浅拷贝时,新创建的列表中的元素是原始列表中元素的引用,而不是元素的副本。这意味着如果在浅拷贝列表中的嵌套列表上进行修改,原始列表中相应的嵌套列表也会受到影响。

通过一个示例来说明这个问题:

import copy

original_list = [1, [2, 3], 4]
shallow_copy = copy.copy(original_list)

# 修改浅拷贝列表中的嵌套列表
shallow_copy[1].append(5)

print(original_list)  # 输出: [1, [2, 3, 5], 4]
print(shallow_copy)  # 输出: [1, [2, 3, 5], 4]

在上述示例中,我们对一个包含嵌套列表的原始列表进行浅拷贝。然后,我们修改浅拷贝列表中的嵌套列表,结果原始列表中的嵌套列表也被修改了。

这是因为浅拷贝只复制了嵌套列表的引用,而不是创建嵌套列表的副本。因此,对浅拷贝列表中的嵌套列表进行修改实际上是对原始列表中相应的嵌套列表进行修改。

要解决这个问题,你可以使用深拷贝来创建所有嵌套列表的副本,而不是共享引用。这样,对深拷贝列表中的嵌套列表进行修改不会影响原始列表。

import copy

original_list = [1, [2, 3], 4]
deep_copy = copy.deepcopy(original_list)

# 修改深拷贝列表中的嵌套列表
deep_copy[1].append(5)

print(original_list)  # 输出: [1, [2, 3], 4]
print(deep_copy)  # 输出: [1, [2, 3, 5], 4]

在上述示例中,我们使用深拷贝创建了嵌套列表的副本。对深拷贝列表中的嵌套列表进行修改不会影响原始列表。

因此,当涉及到嵌套列表时,特别是在进行拷贝操作时,请考虑使用深拷贝来确保所有嵌套列表的副本都被创建,以避免意外行为

当涉及到嵌套字典时,浅拷贝也会导致类似的问题。通过一个例子来说明:

import copy

original_dict = {'a': 1, 'b': {'x': 2, 'y': 3}}
shallow_copy = copy.copy(original_dict)

# 修改浅拷贝字典中的嵌套字典
shallow_copy['b']['x'] = 4

print(original_dict)  # 输出: {'a': 1, 'b': {'x': 4, 'y': 3}}
print(shallow_copy)  # 输出: {'a': 1, 'b': {'x': 4, 'y': 3}}

在上述示例中,我们对一个包含嵌套字典的原始字典进行浅拷贝。然后,我们修改浅拷贝字典中的嵌套字典的值,结果原始字典中相应的嵌套字典也被修改了。

这是因为浅拷贝只复制了嵌套字典的引用,而不是创建嵌套字典的副本。因此,对浅拷贝字典中的嵌套字典进行修改实际上是对原始字典中相应的嵌套字典进行修改。

同样地,为了解决这个问题,你可以使用深拷贝来创建所有嵌套字典的副本,而不是共享引用。这样,对深拷贝字典中的嵌套字典进行修改不会影响原始字典。

import copy

original_dict = {'a': 1, 'b': {'x': 2, 'y': 3}}
deep_copy = copy.deepcopy(original_dict)

# 修改深拷贝字典中的嵌套字典
deep_copy['b']['x'] = 4

print(original_dict)  # 输出: {'a': 1, 'b': {'x': 2, 'y': 3}}
print(deep_copy)  # 输出: {'a': 1, 'b': {'x': 4, 'y': 3}}

在上述示例中,我们使用深拷贝创建了嵌套字典的副本。对深拷贝字典中的嵌套字典进行修改不会影响原始字典。

因此,无论是嵌套列表还是嵌套字典,在进行拷贝操作时,请考虑使用深拷贝来确保所有嵌套对象的副本都被创建,以避免意外修改原始对象的问题

    三段头部互联网大厂测开经历,辅导过25+同学入职大厂,【简历优化】、【就业指导】、【模拟/辅导面试】一对一指导

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

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

相关文章

SBCFormer:能够在单板计算机上以每秒1帧的速度进行全尺寸ImageNet分类的轻量级网络

摘要 https://arxiv.org/ftp/arxiv/papers/2311/2311.03747.pdf 计算机视觉在解决包括智能农业、渔业和畜牧业管理等不同领域的实际问题中变得越来越普遍。这些应用可能不需要每秒处理许多图像帧,因此从业者倾向于使用单板计算机(SBCs)。尽管…

Pytorch数据结构:Tensor

文章目录 Tensor基础1.1、Tensor的维度(Dimensions)1.1.1、举例说明1.1.2、高维Tensor 1.2、.dim()和.size()方法1.2.1、.dim()方法1.2.2、.size()方法1.2.3、.shape属性1.2.3、示例代码1.2.3.1、一维Tensor1.2.3.2、二维Tensor1.2.3.3、三维Tensor 1.3、…

【Go】十五、接口、多态、断言

文章目录 1、接口的引入2、接口3、接口的注意点4、多态5、断言6、Type Switch 1、接口的引入 以日常生活中打招呼为例,定义接口规范,各国人为打招呼为具体的实现 package main import "fmt"//接口的定义:定义规则、定义规范&…

存内领域前沿,基于忆阻器的存内计算----浅析忆阻存内计算

目录 一.概念浅析 二.忆阻器的分类 三.基于忆阻器的存内计算原理 四.存内计算的实验研究 一.概念浅析 1.存内计算 存内计算(In-Memory Computing,简称 IMC)是一种将数据处理和存储紧密结合在一起的计算方式。它的主要思想是在存储设备中直…

Navicat设置mysql权限

新建用户: 注意:如果不生效执行刷新命令:FLUSH PRIVILEGES; 执行后再重新打开查看; 查询权限命令:1234为新建的用户名,localhost为访问的地址 SHOW GRANTS FOR 1234localhost;如果服务器设置服务器权限后可能会出现权…

某东手势验证

地球上最强版!!!!!!!! 成功率99 基本不失败!!!!!!!!!! 识别速…

ZCMU操作系统课程实验 - 实验1-Linux的使用

登录 1. 打开这个东西 2. 在 文件 - > 打开 中打卡机房里VMOS文件里的这个东东 3. 然后依次操作下去好了,有红色的选项,我都是选的"Do nothing"。完成后就会出现这样一个黑框框。 4. 让你登录。输入:root。密码&…

Excel制作甘特图

使用Excel表格制作甘特图,可根据任务开始时间和结束时间自动计算工时,并自动用指定颜色填充横道图。 1.新建Excel文档,先设置项目基本信息,包括表格名称,这里设置为“**项目甘特图”;然后添加任务序号列&a…

前后端实现下拉框带条件查询(Vue+Java)

目录 前言1. 前端2. 后端 前言 对于该基本知识熟门熟路,对此总结一套自身的模版如下 总体逻辑如下:通过前端下拉框或者其他组合框(多选勾选查询),将条件返回给后端处理,后端查询数据库,查询得…

【Servlet】Servlet入门

文章目录 一、介绍二、入门案例导入servlet-api的解决办法 一、介绍 概念:server applet,即:运行在服务器端的小程序 Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则。 将来我们定义…

bugku-web-速度要快

发现phpsessid 从上述提示 提示发送post请求,并且带有参数margin 发送后发现报文头部有一个字段叫flag,但好像每一次flag都不一样 构建Python脚本 request requests.Session()data {margin:find, } for i in range(50):html request.post(urlhttp:/…

JS详解-class-类的核心语法关于ES6与ES5

class基本核心语法: //定义类class Person{//公有属性(推荐此处定义)name// 定义属性并设置默认值price 100//构造函数constructor(name,age){// 构造函数内部的this实例化对象this.name namethis.age age// 动态添加属性(不推荐,查找麻烦)this.rank …

位运算算法(1)

目录 一、算法简述 191. 位1的个数 一、题目描述 二、思路解析 三、代码 338.比特位计数 一、题目描述 二、思路解析 三、代码 461.汉明距离 一、题目描述 二、思路解析 三、代码 声明:本博客涉及到的三道题均为一种做法的总结,建议先了解做…

ansible-tower安装

特别注意:不需要提前安装ansible,因为ansible tower中的setup.sh脚本会下载对应的ansible版本 ansible tower不支持Ubuntu系统,对cenos系统版本也有一定的限制,建议使用centos7.9。 准备一台全新的机器安装,因为ansible tower需要…

RISC-V/ARM mcu OpenOCD 调试架构解析

Risc-v/ARM mcu OpenOCD 调试架构解析 最近有使用到risc-v的单片机,所以了解了下risc-v单片机的编译与调试环境的搭建,面试时问到risc-v的调试可参看以下内容。 risc-v根据官方的推荐,调试器服务是选择OpenOCD,DopenOCD(开放片上…

2024多功能知识付费源码下载

多功能知识付费源码下载实现流量互导多渠道变现 源码介绍 资源变现类产品的许多优势,并剔除了那些无关紧要的元素,使得本产品在运营和变现能力方面实现了质的飞跃。多领域素材资源知识变现营销裂变独立版本。 支持:视频、音频、图文、文档…

【机器学习】揭秘无监督学习:机器如何自我学习发现数据奥秘

无监督学习:全面解析 引言 在机器学习的众多分支中,无监督学习因其在未标记数据上发现隐藏模式的能力而独树一帜。它不依赖于事先标记的输出,而是通过分析数据本身的结构和分布来揭示内在的关系和分类。本文深入探讨无监督学习的核心概念、…

2013年认证杯SPSSPRO杯数学建模C题(第一阶段)公路运输业对于国内生产总值的影响分析全过程文档及程序

2013年认证杯SPSSPRO杯数学建模 C题 公路运输业对于国内生产总值的影响分析 原题再现: 交通运输作为国民经济的载体,沟通生产和消费,在经济发展中扮演着极其重要的角色。纵观几百年来交通运输与经济发展的相互关系,生产水平越高…

学透Spring Boot 003 —— Spring 和 Spring Boot 常用注解(附面试题和思维导图)

这是 学透 Spring Boot 专栏 的第三篇,欢迎关注我,与我一起学习和探讨 Spring Boot 相关知识,学透 Spring Boot。 从面试题说起 今天我们通过一道和Spring Boot有关的常见面试题入手。 面试题:说说 Spring Boot 中有哪些常用注解…

图解PyTorch中的torch.gather函数和 scatter 函数

前言 torch.gather在目前基于 transformer or query based 的目标检测中,在最后获取目标结果时,经常用到。 这里记录下用法,防止之后又忘了。 介绍 torch.gather 官方文档对torch.gather()的定义非常简洁 定义:从原tensor中获…