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

    1. 浅拷贝:只拷贝第一层,更深层的还指向原有的内存地址。

    2. 深拷贝: 递归拷贝多层。

    1. 先看一例子:

    import copy
    
    a = [1, 3, 4]
    
    f = a
    print(id(a))
    print(id(f))

    G:envsflaskenvScriptspython.exe G:/workspace/albumy-master/11.py
    1841649924552
    1841649924552

    将变量a 赋值给变脸f,其实是将变量f 指向变量a对应值得内存地址。

     

    浅拷贝:

    import copy
    
    a = [1, 3, 4]
    b = [2, 5]
    c = [a, b]
    d = copy.copy(c)
    print('c的内存地址', id(c))
    print('d的内存地址', id(d))
    print('c的第一个元素内存地址', id(c[0]))
    print('d的第一个元素内存地址', id(d[0]))

    G:envsflaskenvScriptspython.exe G:/workspace/albumy-master/11.py
    c的内存地址 1507477928264
    d的内存地址 1507478038024
    c的第一个元素内存地址 1507477928392
    d的第一个元素内存地址 1507477928392

    d元素是经过浅拷贝c元素得来的,因此d元素的内存地址与c元素的内存地址不相同,就是拷贝了一份c的元素在内存中重新开辟一段空间存储,但是浅拷贝不拷贝内层的引用。因此

    c元素的第一个元素值得内存地址与d元素的一个元素值得内存地址相同。

    深拷贝:

    import copy
    
    a = [1, 3, 4]
    b = [2, 5]
    c = [a, b]
    e = copy.deepcopy(c)
    print('c的内存地址', id(c))
    print('e的内存地址', id(e))
    print('c的第一个元素内存地址', id(c[0]))
    print('e的第一个元素内存地址', id(e[0]))

    G:envsflaskenvScriptspython.exe G:/workspace/albumy-master/11.py
    c的内存地址 2093738014856
    e的内存地址 2093738015048
    c的第一个元素内存地址 2093738014984
    e的第一个元素内存地址 2093738014024

    可以看出,深拷贝内层元素的值也被重新拷贝一份,而不是执行原来的引用。

    对于元组的拷贝

    import copy
    
    
    a = (1, 3, 4)
    b = copy.copy(a)
    print(id(a))
    print(id(b))

    G:envsflaskenvScriptspython.exe G:/workspace/albumy-master/11.py
    1950885994784
    1950885994784

    因为元祖是不可变类型,那么久意味着数据一定不能修改,因此使用浅拷贝时,它会自动判断,如果是元祖,就直接指向,不会重新拷贝一份。

    如果是深拷贝呢

    import copy
    
    
    a = (1, 3, 4)
    b = copy.deepcopy(a)
    print(id(a))
    print(id(b))

    G:envsflaskenvScriptspython.exe G:/workspace/albumy-master/11.py
    2048102687008
    2048102687008

    还是直接指向。

    再看例子

    import copy
    
    
    a = [1, 3, 4]
    b = [2, 5]
    c = (a, b)
    d = copy.copy(c)
    print(id(c))
    print(id(d))
    print(id(c[0]))
    print(id(d[0]))

    G:envsflaskenvScriptspython.exe G:/workspace/albumy-master/11.py
    1698151178632
    1698151178632
    1698152560328
    1698152560328

    结论,对于元祖的浅拷贝,即使元祖中存在可变元素 如列表,也都是指向。

    那么深拷贝呢

    import copy
    
    
    a = [1, 3, 4]
    b = [2, 5]
    c = (a, b)
    d = copy.deepcopy(c)
    print(id(c))
    print(id(d))
    print(id(c[0]))
    print(id(d[0]))

    G:envsflaskenvScriptspython.exe G:/workspace/albumy-master/11.py
    2626026493576
    2626026495560
    2626026321992
    2626026322056

    结论; 对于深拷贝,若元祖中存在可变元素,那么深拷贝就会重新拷贝一份。

    那么总结一个元祖的拷贝:

    如果用浅拷贝 深拷贝对一个全部都是不可变类型的数据进行拷贝,那么他们的结果相同,都是指向引用。

    如果拷贝的是一个不可变类型的数据,但是内层存在可变类型时,浅拷贝是指向引用,深拷贝是重新拷贝一份。

    其他的操作也是拷贝(列表的切片,是浅拷贝)

     字典的拷贝

    先说一下字段的存储原理,创建一个字典时,字典的key在字典中存储,但是对应的值存储的是值对应的引用。

    所以说,对于字典的浅拷贝,拷贝出来的字典的值,也是执行引用。

    import copy
    
    
    a = {'k1': 'v1', 'k2': 'v2', 'k3': [1, 3, 5]}
    b = copy.copy(a)
    print(id(a))
    print(id(b))
    a['k3'].append(9)
    print(a)
    print(b)

    G:envsflaskenvScriptspython.exe G:/workspace/albumy-master/11.py
    2245390036616
    2245396227592
    {'k2': 'v2', 'k3': [1, 3, 5, 9], 'k1': 'v1'}
    {'k2': 'v2', 'k3': [1, 3, 5, 9], 'k1': 'v1'}

    深拷贝

    import copy
    
    
    a = {'k1': 'v1', 'k2': 'v2', 'k3': [1, 3, 5]}
    b = copy.deepcopy(a)
    print(id(a))
    print(id(b))
    a['k3'].append(9)
    print(a)
    print(b)

    G:envsflaskenvScriptspython.exe G:/workspace/albumy-master/11.py
    2422065983112
    2422068394568
    {'k1': 'v1', 'k2': 'v2', 'k3': [1, 3, 5, 9]}
    {'k1': 'v1', 'k2': 'v2', 'k3': [1, 3, 5]}

  • 相关阅读:
    BZOJ3589: 动态树
    BZOJ3631: [JLOI2014]松鼠的新家
    BZOJ3307: 雨天的尾巴
    BZOJ1895: Pku3580 supermemo
    BZOJ3786: 星系探索
    BZOJ2819: Nim
    解题:POI 2009 Lyz
    解题:POI 2016 Nim z utrudnieniem
    解题:POI 2004 Bridge
    解题:POI 2018 Prawnicy
  • 原文地址:https://www.cnblogs.com/yuqiangli0616/p/10291252.html
Copyright © 2011-2022 走看看