• Python深浅拷贝


    前言

    Python的数据类型:

    • 不可变数据类型:数值类型(int、float)、字符串、元组
    • 可变数据类型:列表、字典、集合

    深浅copy的模块(copy):

    • copy.copy() 浅拷贝
    • copy.deepcopy() 深拷贝

    不可变数据类型的深浅拷贝

    浅拷贝

    #!/usr/bin/env python
    # -*-coding:utf-8-*-
    
    """
    @author:fyh
    @time:2019/6/5
    """
    import copy
    
    a = 123
    b = copy.copy(a)
    print(b)
    print(id(a))
    print(id(b))
    
    # 输出结果
    # 123
    # 1891531600
    # 1891531600
    
    s1 = "abc"
    s2 = copy.copy(s1)
    print(s2)
    print(id(s1))
    print(id(s2))
    
    # 输出结果
    # abc
    # 2586689354584
    # 2586689354584
    

    通过上面的示例可以看出:不可变类型进行浅拷贝不会给拷贝的对象开辟新的内存空间,而只是拷贝了这个对象的引用。

    深拷贝

    #!/usr/bin/env python
    # -*-coding:utf-8-*-
    
    """
    @author:fyh
    @time:2019/6/5
    """
    import copy
    
    a = 123
    b = copy.deepcopy(a)
    print(b)
    print(id(a))
    print(id(b))
    
    # 输出结果
    # 123
    # 1891531600
    # 1891531600
    
    s1 = "abc"
    s2 = copy.deepcopy(s1)
    print(s2)
    print(id(s1))
    print(id(s2))
    
    # 输出结果
    # abc
    # 2586689354584
    # 2586689354584
    

    通过上面的示例可以看出:不可变类型进行深拷贝不会给拷贝的对象开辟新的内存空间,也是拷贝了这个对象的引用。

    原理如下图:

    可变类型的深浅拷贝

    浅拷贝

    #!/usr/bin/env python3
    
    """
    @author:fyh
    """
    import copy
    
    
    my_list1 = ['苹果', '鸭梨']
    my_list2 = copy.copy(my_list1)
    print("my_list1:", id(my_list1), "my_list2:", id(my_list2))
    my_list1[0] = '香蕉'
    print(my_list1, my_list2)
    
    # 结果
    # my_list1: 140246877880712 my_list2: 140246877802120
    # ['香蕉', '鸭梨'] ['苹果', '鸭梨']
    
    # 结论:对可变类型可以进行浅拷贝,会对对象开辟新的内存空间
    
    my_list3 = ['苹果', '鸭梨', ['橘子', '橙子']]
    my_list4 = copy.copy(my_list3)
    print("my_list3:", id(my_list3), "my_list4:", id(my_list4))
    # 结果 my_list3: 140703644308360 my_list4: 140703644310728
    
    print("my_list3[2]:", id(my_list3[2]), "my_list4[2]:", id(my_list4[2]))
    # 结果:my_list3[2]: 140309865347272 my_list4[2]: 140309865347272
    
    my_list3[2][0] = '凤凰'
    print("my_list3", my_list3, "my_list4", my_list4)
    # 结果:my_list3 ['苹果', '鸭梨', ['凤凰', '橙子']] my_list4 ['苹果', '鸭梨', ['凤凰', '橙子']]
    
    my_list3[0] = "aa"
    
    print("my_list3", my_list3, "my_list4", my_list4)
    # 结果:my_list3 ['aa', '鸭梨', ['凤凰', '橙子']] my_list4 ['苹果', '鸭梨', ['凤凰', '橙子']]
    
    # 结论:浅拷贝只会对对象的第一层对象进行拷贝
    

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

    原理如下:

    未修改前:

    修改后的:

    深拷贝

    #!/usr/bin/env python3
    
    """
    @author:fyh
    """
    import copy
    
    list1 = [1, 2]
    list2 = copy.deepcopy(list1)
    print("list1", id(list1), "list2", id(list2))
    # 结果:list1 140200541024008 list2 140200540991112
    
    list1[0] = 3
    print(list1, list2)
    # 结果:[3, 2]     [1, 2]
    
    list3 = [3, 4, [5, 6]]
    list4 = copy.deepcopy(list3)
    print("list3", id(list3), "list4", id(list4))
    # 结果:list3 140370543248904 list4 140370543250184
    print("list3[2]", id(list3[2]), "list4[2]", id(list4[2]))
    # print("list3", id(list3), "list4", id(list4))
    list3[2][0] = 7
    print(list3, list4)
    # 结果:[3, 4, [7, 6]]    [3, 4, [5, 6]]
    

    结论:可变类型进行深拷贝会对该对象到最后一个可变类型的每一层对象就行拷贝, 对每一层拷贝的对象都会开辟新的内存空间进行存储。

    原理如下图:

    总结

    • 浅拷贝使用copy.copy函数
    • 深拷贝使用copy.deepcopy函数
    • 不管是给对象进行深拷贝还是浅拷贝,只要拷贝成功就会开辟新的内存空间存储拷贝的对象。
    • 浅拷贝和深拷贝的区别是:
      • 浅拷贝最多拷贝对象的一层,深拷贝可能拷贝对象的多层
  • 相关阅读:
    Proj THUDBFuzz Paper Reading: The Art, Science, and Engineering of Fuzzing: A Survey
    Proj THUDBFuzz Paper Reading: A systematic review of fuzzing based on machine learning techniques
    9.3 付费代理的使用
    11.1 Charles 的使用
    第十一章 APP 的爬取
    10.2 Cookies 池的搭建
    10.1 模拟登录并爬取 GitHub
    11.5 Appium 爬取微信朋友圈
    11.4 Appium 的基本使用
    11.3 mitmdump 爬取 “得到” App 电子书信息
  • 原文地址:https://www.cnblogs.com/fengyuhao/p/11697534.html
Copyright © 2020-2023  润新知