Python 高阶内容:深拷贝与浅拷贝揭秘复制的“玄学”

news2024/9/21 10:44:38

Python 高阶内容:深拷贝与浅拷贝揭秘复制的“玄学”

文章目录

  • Python 高阶内容:深拷贝与浅拷贝揭秘复制的“玄学”
      • 一 copy 数据
        • 示例一
        • 示例二
      • 二 深拷贝与浅拷贝
      • 三 copy 对比
        • 基本概念对比
        • 实现方式对比
      • 四 完整代码示例
      • 五 源码地址

在 Python 中,复制操作并不是简单地将对象内容重新创建,而是存在着深拷贝(Deep Copy)和浅拷贝(Shallow Copy)两种方式。浅拷贝只是复制对象本身,不包括内部嵌套的子对象;如果内部对象被修改,原始对象也会受到影响。而深拷贝则是递归地复制对象及其所有子对象,生成一个完全独立的副本,确保原对象和副本之间互不影响。浅拷贝通常通过对象的 .copy() 方法或切片操作实现,适用于对象中不包含可变子对象或希望共享子对象的情况。而深拷贝则需要使用 copy 模块中的 deepcopy() 函数,适用于需要完全独立的副本,避免任何联动修改的场景。

掌握这两种拷贝方式的区别与应用,可以帮助开发者在不同场景下更好地管理数据和内存。本文通过实例详解了深拷贝与浅拷贝的不同特点及适用场景,帮助你轻松理解这一看似“玄学”的知识点。

一 copy 数据

复制本质是复制地址和复制值。

示例一
l = [1, 2, 3]
_l = l.copy()
_l[0] = -1
print(_l)
print(l)

运行的之后

[-1, 2, 3]
[1, 2, 3]
示例二
l = [[1], [2], 3]
_l = l.copy()
_l[0][0] = -1
print(_l)
print(l)

运行的之后

[[-1], [2], 3]
[[-1], [2], 3]

运行后,发现,源列表居然变了,再来看一个实例。

audio = File("mp3")
file = File("txt")
l = [audio, file]
_l = l.copy()
_l[0].name = "mp4"
print(audio.name)  
# 运行之后 "mp4"

运行之后源列表是 mp3 的,怎么被复制后的列表改变成了 mp4 。

二 深拷贝与浅拷贝

Python 中复制,有两种方式,一种是深拷贝,一种是浅拷贝。

深拷贝是 Deep Copy,浅拷贝是 Shallow Copy,Deep copy 就是我们通常意义上的复制,把东西全部再造了一遍,彻底成为了两个独立的个体。 而Shallow Copy, 其实也有一点影子拷贝的意思,我复制出来的是你的一个影子,一个投影成像。 所以真实的实体是没有被复制的,我只复制了这个实体的一个投影而已。这里有点绕。划重点 Python 对数值字符的复制是直接复制的值,浅复制的优势就是。复制是需要内存和时间的,因为浅复制没有真正复制,所以并不需要耗多少内存和时间。

那如何拷贝出互不影响的实例列表呢?对存放实例的列表做 Deep Copy 深拷贝。

    from copy import deepcopy
    l = [[1], [2], 3]
    _l = deepcopy(l)
    _l[0][0] = -1
    print(_l)
    print(l)

三 copy 对比

基本概念对比
比较项浅拷贝(Shallow Copy)深拷贝(Deep Copy)
定义仅复制对象本身,内部的子对象仍然引用原始对象的子对象递归地复制对象及其所有子对象,生成全新的副本
对象关系新对象与原对象共享可变的子对象新对象与原对象完全独立,修改互不影响
适用场景对象中不包含可变的子对象,或希望共享子对象的情况需要完全独立的副本,避免任何联动修改的情况
实现方式对比
比较项浅拷贝实现方法深拷贝实现方法
内置方法使用对象的 .copy() 方法
copy 模块copy.copy(obj)copy.deepcopy(obj)
列表特有切片操作:new_list = original_list[:]
示例代码shallow_copied_list = copy.copy(original_list)
shallow_copied_list = original_list[:]
deep_copied_list = copy.deepcopy(original_list)

四 完整代码示例

# This is a sample Python script.

# Press ⌃R to execute it or replace it with your code.
# Press Double ⇧ to search everywhere for classes, files, tool windows, actions, and settings.


def print_hi(name):
    # Use a breakpoint in the code line below to debug your script.
    print(f'Hi, {name}')  # Press ⌘F8 to toggle the breakpoint.
    # 我的确复制了呀, 复制数值
    # 复制本质是复制地址和复制值
    l = [1, 2, 3]
    _l = l.copy()
    _l[0] = -1
    print(_l)
    print(l)
    # 看看这个示例
    l = [[1], [2], 3]
    _l = l.copy()
    _l[0][0] = -1
    print(_l)
    print(l)
    # 运行后,发现,源列表居然变了,再来看一个实例
    audio = File("mp3")
    file = File("txt")
    l = [audio, file]
    _l = l.copy()
    _l[0].name = "mp4"
    print(audio.name)  # "mp4"
    # 源列表是 mp3 的,怎么被复制后的列表改变成了 mp4
    # Python 中复制,有两种方式,一种是深拷贝,一种是浅拷贝。
    # 深拷贝与浅拷贝
    # 深拷贝是 Deep Copy,浅拷贝是 Shallow Copy
    # Deep copy 就是我们通常意义上的复制,把东西全部再造了一遍,彻底成为了两个独立的个体。 而
    # Shallow Copy, 其实也有一点影子拷贝的意思,我复制出来的是你的一个影子,一个投影成像。 所以真实的实体是没有被复制的,我只复制了这个实体的一个投影而已。
    # Python 对数值字符的复制,直接是复制的值
    # 对存放实例的列表做 Deep Copy 深拷贝
    from copy import deepcopy
    l = [[1], [2], 3]
    _l = deepcopy(l)
    _l[0][0] = -1
    print(_l)
    print(l)


class File:
    def __init__(self, name):
        self.name = name


# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    print_hi('复制的"玄学"')

# See PyCharm help at https://www.jetbrains.com/help/pycharm/

复制粘贴并覆盖到你的 main.py 中运行,运行结果如下。

Hi, 复制的"玄学"
[-1, 2, 3]
[1, 2, 3]
[[-1], [2], 3]
[[-1], [2], 3]
mp4
[[-1], [2], 3]
[[1], [2], 3]

五 源码地址

代码地址:

国内看 Gitee 之 复制的"玄学".py

国外看 GitHub 之 复制的"玄学".py

引用 莫烦 Python

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

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

相关文章

VScode开发GD32移植(标准库通用),保姆级!!!!!!!

VScode开发GD32移植(标准库通用),保姆级!!!!!!! 文章目录 VScode开发GD32移植(标准库通用),保姆级!!!!!&#…

[产品管理-30]:NPDP新产品开发 - 29 - 产品生命周期管理 - 可持续产品创新

目录 一、可持续开发与可持续创新 可持续开发 可持续创新 可持续开发与可持续创新的关系 二、循环经济 1、循环经济的定义 2、循环经济的起源与发展 3、循环经济的原则 4、循环经济的实践案例 5、循环经济的意义与展望 三、三重底线 1. 财务底线 - 企业。赚钱 2. …

11. DPO 微调示例:根据人类偏好优化LLM大语言模型

在部署大模型之后,我们必然要和微调打交道。现在大模型的微调有非常多的方法,过去的文章中提到的微调方法通常依赖于问题和答案对,标注成本较高。 2023 年所提出的 Direct Preference Optimization(DPO)为我们提供了一…

卡牌抽卡机小程序:市场发展下的创新

今年以来,卡牌成为了行业中的黑马,在国内迅速流行,成为消费者的心头好。小小的卡牌创下了百亿的市场规模,发展前景巨大! 不过,随着卡牌市场的不断增长,市场发展也需要进行创新。线上抽卡机小程…

Yocto - 使用Yocto开发嵌入式Linux系统_02 认识 Yocto 项目

Meeting the Yocto Project 本章向你介绍 Yocto 项目。这里讨论的项目主要概念将贯穿全书。此外,我们还将简要讨论 Yocto 项目的历史、OpenEmbedded、Poky、BitBake、元数据和版本模式。系好安全带,欢迎加入我们的行列! This chapter introdu…

信息安全数学基础(19)同余式的基本概念及一次同余式

一、同余式概念 同余式是数论中的一个基本概念,用于描述两个数在除以某个数时所得的余数相同的情况。具体地,设m是一个正整数,a和b是两个整数,如果a和b除以m的余数相同,则称a和b模m同余,记作a≡b(mod m)。反…

C语言 | Leetcode C语言题解之第421题数组中两个数的最大异或值

题目: 题解: const int HIGH_BIT 30;struct Trie {// 左子树指向表示 0 的子节点struct Trie* left;// 右子树指向表示 1 的子节点struct Trie* right; };struct Trie* createTrie() {struct Trie* ret malloc(sizeof(struct Trie));ret->left re…

SpringBoot 数据库表结构文档生成

官方地址&#xff1a;https://github.com/pingfangushi/screw screw 螺丝钉&#xff0c;支持以下数据库 MySQL MariaDB TIDB Oracle SqlServer PostgreSQL Cache DB&#xff08;2016&#xff09; 生产文档支持 html word markdown 开始 添加依赖 <!-- 螺丝钉 --><…

CompletableFuture-详解使用及源码解析

背景 上一篇文章我们看了FutureTask&#xff0c;分析了他的问题&#xff0c;异步编程并不方便。 问题1&#xff1a; FutureTask获取执行结果前&#xff0c;主线程需要通过get()方法一直阻塞等待子线程执行完成call方法&#xff0c;才可以拿到返回结果问题2&#xff1a;如果不…

电竞显示器哪个牌子好

电竞显示器哪个好&#xff1f;你想成为电竞选手吗&#xff1f;显示器很关键&#xff0c;下面我就列举7款市面流行的电竞显示器给大家看看&#xff0c;总有一款适合你。 1.电竞显示器哪个好 - 蚂蚁电竞 ANT255VF电竞显示器 一、产品概述 蚂蚁电竞 ANT255VF电竞显示器是一款专为…

2024/9/21 leetcode 21.合并两个有序链表 2.两数相加

目录 21.合并两个有序链表 题目描述 题目链接 解题思路与代码 2.两数相加 题目描述 题目链接 解题思路与代码 --------------------------------------------------------------------------- 21.合并两个有序链表 题目描述 将两个升序链表合并为一个新的 升序 链表并返…

ChatCADChatCAD+:Towards a Universal and Reliable Interactive CAD using LLMs

ChatCAD&#xff08;论文链接&#xff1a;[2302.07257] ChatCAD: Interactive Computer-Aided Diagnosis on Medical Image using Large Language Models (arxiv.org)&#xff09; 网络流程图&#xff1a; 辅助阅读&#xff1a; 基于大型语言模型的医学图像交互式计算机辅助诊…

【运维自动化-作业平台】如何使用全局变量之字符串类型?

使用变量是脚本很常见的处理场景&#xff0c;作业平台中主要有全局变量和魔法变量两类&#xff0c;全局变量又区分了字符串、命名空间、主机列表、密文、数组5种类型。字符串类型变量 最简单、使用频率最高的全局变量类型&#xff0c;可以跨主机、跨步骤使用。目前在作业平台中…

uniApp微信小程序扫描普通二维码跳转到小程序指定页面操作方法

这篇文章主要给大家介绍了关于微信小程序扫描普通二维码跳转到小程序指定页面操作的相关资料,需要的朋友可以参考下 1、首先我们需要在微信公众平台的开发管理——>开发设置&#xff0c;找到&#xff08;扫普通链接二维码打开小程序&#xff09;&#xff0c;点击添加,根据提…

vue3-05-Element-plus中表单校验:校验对象中的对象的属性,校验对象中的数组中的对象的属性,校验嵌套对象

目录 一、校验对象中的普通属性二、校验对象中对象的属性三、校验对象中的数组中的对象的属性 这两天写vue3项目&#xff0c;用了element-plus库&#xff0c;到了表单规则验证的环节&#xff0c;我发现我只会校验对象中的普通属性&#xff0c;如果校验嵌套对象&#xff0c;我就…

ML 系列:多元线性回归 (MLR)(04)

图 1.多元线性回归与简单线性回归 一、说明 线性回归从一维推广到多维&#xff0c;这与单变量线性回归有很多不同&#xff0c;情况更加复杂&#xff0c;而在梯度优化也需要改成向量梯度&#xff0c;同时&#xff0c;数据预处理也成了必要步骤。 二、综述 多元线性回归是简单线性…

C++:分苹果【排列组合】

描述 把M个同样的苹果放到N个同样的盘子里&#xff0c;允许有的盘子空着不放&#xff0c;问共有多少种不同的分法&#xff1f;&#xff08;用K表示&#xff09;&#xff0c;5&#xff0c;1&#xff0c;1和1&#xff0c;5&#xff0c;1是同一种分法。 输入描述 两个整数M和N&…

C语言 | Leetcode C语言题解之第420题强密码检验器

题目&#xff1a; 题解&#xff1a; #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b))int strongPasswordChecker(char * password) {int n strlen(password);bool has_lower false, has_upper false, has_digit false;for …

YOLOv9改进系列,YOLOv9主干网络替换为RepViT (CVPR 2024,清华提出,独家首发),助力涨点

摘要 轻量级视觉变换器(ViTs)在资源受限的移动设备上表现出优越的性能和较低的延迟,相比之下轻量级卷积神经网络(CNNs)稍显逊色。研究人员发现了许多轻量级 ViTs 和轻量级 CNNs 之间的结构联系。然而,它们在块结构、宏观和微观设计上的显著架构差异尚未得到充分研究。在…

【重磅发布】大模型在金融领域的价值、治理和生态进阶之路白皮书

引言 金融行业天然具备数据和信息密集型的特点,在数字化成熟度方面处于领先地位。此外,金融行业的数字化投入持续稳步增长,汇集了大量具备数字化技能的人才。这些优势使得金融行业在AI技术的应用和创新方面具备独特的条件,能够在推动技术革新和提升行业效率方面起到示范作…