• 深拷贝与浅拷贝


    1. 浅拷贝

    copy函数是浅拷贝,只对可变类型的第一层对象进行拷贝,对拷贝的对象开辟新的内存空间进行存储,不会拷贝对象内部的子对象。

    不可变类型的浅拷贝示例代码:

    import copy  # 使用浅拷贝需要导入copy模块
    
    # 不可变类型有: 数字、字符串、元组
    
    a1 = 123123
    b1 = copy.copy(a1)  # 使用copy模块里的copy()函数就是浅拷贝了
    # 查看内存地址
    print(id(a1))
    print(id(b1))
    
    print("-" * 10)
    a2 = "abc"
    b2 = copy.copy(a2)
    # 查看内存地址
    print(id(a2))
    print(id(b2))
    
    print("-" * 10)
    a3 = (1, 2, ["hello", "world"])
    b3 = copy.copy(a3)
    # 查看内存地址
    print(id(a3))
    print(id(b3))
    

    运行结果:

    140459558944048
    140459558944048
    ----------
    140459558648776
    140459558648776
    ----------
    140459558073328
    140459558073328
    

    不可变类型的浅拷贝说明:

    • 通过上面的执行结果可以得知,不可变类型进行浅拷贝不会给拷贝的对象开辟新的内存空间,而只是拷贝了这个对象的引用。

    可变类型的浅拷贝示例代码:

    import copy # 使用浅拷贝需要导入copy模块
    
    # 可变类型有: 列表、字典、集合
    
    a1 = [1, 2]
    b1 = copy.copy(a1) # 使用copy模块里的copy()函数就是浅拷贝了
    # 查看内存地址
    print(id(a1))
    print(id(b1))
    print("-" * 10)
    a2 = {"name": "张三", "age": 20}
    b2 = copy.copy(a2)
    # 查看内存地址
    print(id(a2))
    print(id(b2))
    print("-" * 10)
    a3 = {1, 2, "王五"}
    b3 = copy.copy(a3)
    # 查看内存地址
    print(id(a3))
    print(id(b3))
    
    print("-" * 10)
    a4 = [1, 2, [4, 5]]
    # 注意:浅拷贝只会拷贝父对象,不会对子对象进行拷贝
    b4 = copy.copy(a4) # 使用copy模块里的copy()函数就是浅拷贝了
    # 查看内存地址
    print(id(a4))
    print(id(b4))
    print("-" * 10)
    # 查看内存地址
    print(id(a4[2]))
    print(id(b4[2]))
    
    # 修改数据
    a4[2][0] = 6
    
    # 子对象的数据会受影响
    print(a4)
    print(b4)
    

    运行结果:

    139882899585608
    139882899585800
    ----------
    139882919626432
    139882919626504
    ----------
    139882919321672
    139882899616264
    ----------
    139882899587016
    139882899586952
    ----------
    139882899693640
    139882899693640
    [1, 2, [6, 5]]
    [1, 2, [6, 5]]
    

    可变类型的浅拷贝说明:

    • 通过上面的执行结果可以得知,可变类型进行浅拷贝只对可变类型的第一层对象进行拷贝,对拷贝的对象会开辟新的内存空间进行存储,子对象不进行拷贝。

    2. 深拷贝

    deepcopy函数是深拷贝, 只要发现对象有可变类型就会对该对象到最后一个可变类型的每一层对象就行拷贝, 对每一层拷贝的对象都会开辟新的内存空间进行存储。

    不可变类型的深拷贝示例代码:

    import copy  # 使用深拷贝需要导入copy模块
    
    # 不可变类型有: 数字、字符串、元组
    
    a1 = 1
    b1 = copy.deepcopy(a1)  # 使用copy模块里的deepcopy()函数就是深拷贝了
    # 查看内存地址
    print(id(a1))
    print(id(b1))
    print("-" * 10)
    a2 = "张三"
    b2 = copy.deepcopy(a2)
    # 查看内存地址
    print(id(a2))
    print(id(b2))
    print("-" * 10)
    a3 = (1, 2)
    b3 = copy.deepcopy(a3)
    # 查看内存地址
    print(id(a3))
    print(id(b3))
    print("-" * 10)
    
    # 注意: 元组里面要是有可变类型对象,发现对象有可变类型就会该对象到最后一个可变类型的每一层对象进行拷贝
    a4 = (1, ["李四"])
    b4 = copy.deepcopy(a4)
    # 查看内存地址
    print(id(a4))
    print(id(b4))
    # 元组里面的可变类型子对象也会进行拷贝
    print(id(a4[1]))
    print(id(b4[1]))
    

    运行结果:

    9289120
    9289120
    ----------
    140115621848320
    140115621848320
    ----------
    140115621859592
    140115621859592
    ----------
    140115602480584
    140115621834568
    140115602328136
    140115602436168
    

    不可变类型的深拷贝说明:

    • 通过上面的执行结果可以得知:
      • 不可变类型进行深拷贝如果子对象没有可变类型则不会进行拷贝,而只是拷贝了这个对象的引用,否则会对该对象到最后一个可变类型的每一层对象就行拷贝, 对每一层拷贝的对象都会开辟新的内存空间进行存储

    可变类型的深拷贝示例代码:

    import copy  # 使用深拷贝需要导入copy模块
    
    # 可变类型有: 列表、字典、集合
    
    a1 = [1, 2]
    b1 = copy.deepcopy(a1)  # 使用copy模块里的deepcopy()函数就是深拷贝了
    # 查看内存地址
    print(id(a1))
    print(id(b1))
    print("-" * 10)
    a2 = {"name": "张三"}
    b2 = copy.deepcopy(a2)
    # 查看内存地址
    print(id(a2))
    print(id(b2))
    print("-" * 10)
    a3 = {1, 2}
    b3 = copy.deepcopy(a3)
    # 查看内存地址
    print(id(a3))
    print(id(b3))
    print("-" * 10)
    
    a4 = [1, 2, ["李四", "王五"]]
    b4 = copy.deepcopy(a4)  # 使用copy模块里的deepcopy()函数就是深拷贝了
    # 查看内存地址
    print(id(a4))
    print(id(b4))
    
    # 查看内存地址
    print(id(a4[2]))
    print(id(b4[2]))
    a4[2][0] = "王五"
    # 因为列表的内存地址不同,所以数据不会收到影响
    print(a4)
    print(b4)
    

    运行结果:

    140348291721736
    140348291721928
    ----------
    140348311762624
    140348311221592
    ----------
    140348311457864
    140348291752456
    ----------
    140348291723080
    140348291723144
    140348291723208
    140348291723016
    [1, 2, ['王五', '王五']]
    [1, 2, ['李四', '王五']]
    

    可变类型的深拷贝说明:

    • 通过上面的执行结果可以得知, 可变类型进行深拷贝会对该对象到最后一个可变类型的每一层对象就行拷贝, 对每一层拷贝的对象都会开辟新的内存空间进行存储。

    3. 浅拷贝和深拷贝的区别

    • 浅拷贝最多拷贝对象的一层
    • 深拷贝可能拷贝对象的多层

    4. 总结

    • 浅拷贝使用copy.copy函数
    • 深拷贝使用copy.deepcopy函数
    • 不管是给对象进行深拷贝还是浅拷贝,只要拷贝成功就会开辟新的内存空间存储拷贝的对象。
    • 浅拷贝和深拷贝的区别是:
      • 浅拷贝最多拷贝对象的一层,深拷贝可能拷贝对象的多层。
  • 相关阅读:
    jvmgc调优2
    5G 组网模式
    IIS报错用户 'IIS APPPOOL\\XXX' 登录失败
    ASP.NET Core.netcore使用swagger后打开页面空白
    IIS报错无法打开登录所请求的数据库 \"MyDB\"。登录失败。\r\n用户 'NT AUTHORITY\\SYSTEM' 登录失败。
    ASP.NET Corewebapi返回固定格式的json数据
    ASP.NET Core在.netcore项目中使用Newtonsoft
    JS数组
    Leetcode 2032. 至少在两个数组中出现的值(可以,一次过)
    Qt文件编码格式识别
  • 原文地址:https://www.cnblogs.com/zhangwei112/p/13586815.html
Copyright © 2020-2023  润新知