• python中深拷贝和浅拷贝的区别



    若将需要注释若干行,则将这些行选中,然后按住 ctrl + / 键就可以了,再按一次,即可取消多行注释
    若要批量缩进,那么将需要缩进的行都选中,按 tab 键就可以
    若要取消批量缩进,则选中对应行,按 shift + tab

    值的引用

    # 1、值的引用
    num1 = [1, 2, 3]
    num2 = num1  # num1和num2指向同一个内存空间
    num1.append(4)
    print(num2)  # [1,2,3,4]
    
    • 1
    • 2
    • 3
    • 4
    • 5

    浅拷贝

    # 2、浅拷贝
    n1 = [1, 2, 3]
    n2 = n1.copy()  # n1.copy和n1[:]切片均能实现拷贝
    print(id(n1), id(n2))  # n1和n2的内存地址不同
    n1.append(4)  # n1和n2内存地址不相同,互不影响,修改n1不会影响n2
    print(n2)  # [1,2,3]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    可变数据类型与不可变数据类型

    • 可变数据类型(可以增删改):列表
    • 不可变数据类型:字符串、元组、所有的数值型、命名元组

    不可变数据类型

    整型是不可变数据类型,不可变数据类型是变量指向内存空间的值不会发生改变

    a=5
    print(id(a))
    a=10
    print(id(a)) #两者内存地址不一样
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    从内存空间的角度可以理解为:
    内存空间中有2块位置分别存放了值5和值10,
    第一次定义变量a时,a指向值5的内存地址,第二次定义变量a时,由于整型是不可变数据类型,值无法改变,因此a重新指向值10的内存地址

    可变数据类型

    列表是可变数据类型
    可变数据类型:变量指向的内存空间中以存放的值是可发生更改的

    li=[1,2,3]
    print(id(li))
    li.append(4)
    print(li)
    print(id(li)) #内存地址是一致的
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    上述例子可以理解为:
    在一块内存空间中存放了列表[1,2,3],变量li指向该内存空间,
    当需要添加删除元素时,是直接对该内存空间中的值更改,这就叫做可变数据类型

    深拷贝

    如果列表嵌套的时候,或者列表中包含可变数据类型,拷贝时一定选择深拷贝!!!

    n1=[1,2,[1,2]]
    n2=n1.copy() #浅拷贝
    print(id(n1),id(n2)) #n1和n2的内存地址不相同
    print(id(n1[-1]),id(n2[-1])) #n1[-1]和n2[-1]内存地址相同
    n1[-1].append(4)
    print(n2) #[1, 2, [1, 2, 4]]
    #如果列表嵌套的时候,或者列表中包含可变数据类型,拷贝时一定选择深拷贝
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述copy()实现了浅拷贝。在列表嵌套时或者列表中包含可变数据类型时,只是对嵌套的子对象复制了引用,并没有对这些子对象建立一个新对象(上述例子中n1[-1]和n2[-1]内存地址相同)。所以改变n1[-1],n2[-1]也发生相应改变。

    修改了n1,但是n2也发生了变化。通过使用深拷贝,才能使得n1和n2完全独立
    那么深拷贝该如何实现呢?

    import  copy
    n1=[1,2,[1,2]]
    n2=copy.deepcopy(n1)
    print(id(n1),id(n2)) #n1和n2的内存地址不相同
    print(id(n1[-1]),id(n2[-1])) #n1[-1]和n2[-1]内存地址不相同
    n1[-1].append(4) #[1, 2, [1, 2, 4]]
    print(n2) #[1, 2, [1, 2]]
    #如果列表嵌套的时候,或者列表中包含可变数据类型,拷贝时一定选择深拷贝
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述通过深拷贝,实现了n1和n2完全独立。

    深拷贝浅拷贝总结

    赋值: 创建了对象的一个新的引用,修改其中任意一个变量都会影响到另一个(因为都指向同一块内存地址)
    浅拷贝:另外一个变量的内存地址的拷贝,这两个变量指向同一个内存地址的变量值(li.copy copy.copy)

    • 公用一个值
    • 这两个变量的内存地址一样
    • 对其中一个变量的值改变,另外一个变量的值也会改变

    深拷贝: 一个变量对另外一个变量的值拷贝(copy.deepcopy())

    • 两个变量的内存地址不同
    • 两个变量各有自己的值,且互不影响
    • 对其中任意一个变量的值的改变不会影响另外一个

    更形象点说:
    深拷贝和浅拷贝最根本的区别在于是否真正获得一个对象的复制实体,而不是引用
    假设B复制了A,修改A的时候,看B是否发生变化
    如果B也发生了变化,说明是浅拷贝,拿人手短。(修改堆内存中的同一个值)
    如果B没有发生变化,说明是深拷贝,自食其力。(修改堆内存中的不同的值)

    在这里插入图片描述

    看到别的文章对于深拷贝浅拷贝解释的很不错:
    https://blog.csdn.net/Elon15/article/details/125256787?spm=1001.2014.3001.5506
    https://www.jianshu.com/p/9ed9b5ce7bb0

  • 相关阅读:
    10种电影类型
    AI计算机视觉进阶项目(一)——带口罩识别检测(4)
    大促过后,销量与流量兼具,是否真的高枕无忧?
    【1day】金和协同管理平台c6系统任意文件读取漏洞学习
    虚心型性格分析,虚心型人格的职业规划
    uniapp -- 扫码记录(针对app场景)
    TCP协议
    “深入理解Nginx的负载均衡与动静分离“
    PCA算法(python版本)
    如何修复丢失的vcruntime140_1.dll文件
  • 原文地址:https://blog.csdn.net/qq_43604376/article/details/127931019