zoukankan      html  css  js  c++  java
  • 深拷贝与浅拷贝

    #原创,转载请先留言联系

    在阅读此文前,建议先看一下我的另一篇博文:https://www.cnblogs.com/chichung/p/9607226.html

    浅拷贝

    import copy
    copy.copy(obj)

    深拷贝

    import copy
    copy.deepcopy(obj)
    • 深拷贝与浅拷贝的区别

    1.浅拷贝

    import copy
    
    a = [1,2]
    b = [3,4]
    c = [a,b]
    d = copy.copy(c)
    print('c的内存地址',id(c))
    print('d的内存地址',id(d))
    
    print('
    c[0]的内存地址',id(c[0]))
    print('d[0]的内存地址',id(d[0]))
    print('a的内存地址',id(a))
    
    输出:
    c的内存地址 139752474494984
    d的内存地址 139752475133128
    
    c[0]的内存地址 139752474562824
    d[0]的内存地址 139752474562824
    a的内存地址 139752474562824

    由输出结果可知。d列表浅拷贝了c列表,所以d列表重新分配了一个内存空间。但是,由于是浅拷贝,d列表的内部,a列表与b列表并没有进行拷贝,也就没有分配新的内存空间,还是原来的内存空间地址。所以说,浅拷贝是对象的最外层的拷贝

    2.深拷贝

    import copy
    
    a = [1,2]
    b = [3,4]
    c = [a,b]
    d = copy.deepcopy(c)
    print('c的内存地址',id(c))
    print('d的内存地址',id(d))
    
    print('
    c[0]的内存地址',id(c[0]))
    print('d[0]的内存地址',id(d[0]))
    print('a的内存地址',id(a))
    
    输出:
    c的内存地址 139657913055240
    d的内存地址 139657913118792
    
    c[0]的内存地址 139657913118984
    d[0]的内存地址 139657913118920
    a的内存地址 139657913118984

    由输出结果可知。d列表深拷贝了c列表,所以d列表重新分配了一个内存空间。但是,由于是深拷贝,d列表的内部,a列表与b列表也进行了拷贝,也重新分配了内存空间。所以说,深拷贝是拷贝是对象的所有层的拷贝。

    上面针对的是可变类型数据的深浅拷贝,不可变类型的深浅拷贝又是不一样的。

    附:

    不可变类型(不可变类型不能对其内容直接修改,修改的话其实是将新的数据储存到新的内存中):数字、字符串、元组、不可变集合

    可变类型(可变类型可以对其内容直接修改,修改的话也是将新的数据储存到原来的内存中):列表、字典、可变集合

    • 不可变类型的深浅拷贝(元组,字符串,数字)
    import copy
    
    a = (1,2)
    b = copy.copy(a)
    c = copy.deepcopy(a)
    
    print('a的内存空间为',id(a))
    print('浅拷贝b的内存空间为',id(b))
    print('深拷贝c的内存空间为',id(c))
    
    输出:
    a的内存空间为 140239461449608
    浅拷贝b的内存空间为 140239461449608
    深拷贝c的内存空间为 140239461449608

    由输出结果可知。a的元组,b对a进行了浅拷贝,但是内存空间还是没有改变!c对a进行了深拷贝,内存空间还是没有变!可知,对于不可变类型,浅拷贝与深拷贝都是相同的 ,都不会单独开辟内存空间,而是引用原来的内存空间。

    • 可变类型与不可变类型嵌套的深浅拷贝
    import copy
    
    b = [1,2]
    a= (b, )
    copy_a = copy.copy(a)
    deepcopy_a = copy.deepcopy(a)
    
    print('a的内存空间为',id(a))
    print('浅拷贝后copy_a的内存空间为',id(copy_a))
    print('深拷贝后deepcopy_a的内存空间为',id(deepcopy_a))
    
    print('
    a[0]的内存空间为',id(a[0]))
    print('浅拷贝后copy_a[0]的内存空间为',id(copy_a[0]))
    print('深拷贝后deepcopy_a[0]的内存空间为',id(deepcopy_a[0]))
    
    输出:
    a的内存空间为 140588590524736
    浅拷贝后copy_a的内存空间为 140588590524736
    深拷贝后deepcopy_a的内存空间为 140588560914976
    
    a[0]的内存空间为 140588560399496
    浅拷贝后copy_a[0]的内存空间为 140588560399496
    深拷贝后deepcopy_a[0]的内存空间为 140588560398408

    要拷贝的是a,a是元组里面嵌套一个字典,a=([1,2],)

    当进行浅拷贝时,只拷贝最外层,因为最外层是元组,是不可变类型,所以只是引用原来的内存空间,内存与a相同。

    当进行深拷贝是,先拷贝最外层,因为最外层是元组,是不可变类型,只是引用原来的内存空间。但是当他开始拷贝第二层时,发现是个可变类型,然后就分配一个新的空间,因此,深拷贝后deepcopy_a[0]的内存空间a[0]的内存空间不一样。但是问题来了,为什么拷贝后deepcopy_a的内存空间a的内存空间不一样?图解!

    明白了吧?如果是嵌套可变类型和不可变类型的,实质上深拷贝还是把全部层都拷贝了一遍,全部层都分配了新的内存空间。

    还有嵌套全是不可变类型的,那深浅拷贝都是引用原来的内存地址,并不会拷贝。

    还有嵌套全是可变类型的,那浅拷贝就会给最外层分配新的内存地址,其它层内存地址不变。深拷贝就会给拷贝所有层,给所有层分配新的内存地址。

    相信你搞得懂上面的示例,这两个肯定都懂的。这里就不演示了。

    • 列表切片、字典中的copy都采用的是浅拷贝

    1.列表切片

    import copy
    
    a = [[1,2],[3,4]]
    b = a[:]
    
    print('a的内存空间',id(a))
    print('b的内存空间',id(b))
    
    print('
    a[0]的内存空间',id(a[0]))
    print('b[0]的内存空间',id(b[0]))
    
    输出:
    a的内存空间 140020984498184  # 最外层拷贝了,因为内存空间重新分配了
    b的内存空间 140020984565832
    
    a[0]的内存空间 140020984566024  # 里面的层没有拷贝,还是原来的内存空间
    b[0]的内存空间 140020984566024
    import copy
    
    a = {'name':['chichung','cong'],'age':22}
    b = a.copy()
    
    print('字典a的内存地址:',id(a))
    print('字典b的内存地址:',id(b))
    
    print('
    字典a里name的内存地址:',id(a['name']))
    print('字典b里name的内存地址:',id(b['name']))
    
    输出:
    字典a的内存地址: 139921205047240  # 最外层拷贝了,因为内存空间重新分配了
    字典b的内存地址: 139921205006472
    
    字典a里name的内存地址: 139921174875464  # 里面的层没有拷贝,还是原来的内存空间
    字典b里name的内存地址: 139921174875464

    因此,列表切片、字典中的copy都采用的是浅拷贝。

    最后的tips:python中内存数据的拷贝默认是浅拷贝。

  • 相关阅读:
    开发报表的先进工具
    强大的报表前端展现功能
    管理驾驶舱监控大屏展现
    换乘算法【转】
    提交中文数据乱码问题总结
    重定向
    容易遗漏的
    jsp基础语法【转】
    说说Java NIO【转】
    Java读取大文件的操作【转】
  • 原文地址:https://www.cnblogs.com/chichung/p/9609786.html
Copyright © 2011-2022 走看看