zoukankan      html  css  js  c++  java
  • python进阶----深拷贝&浅拷贝

    复制需要区分,,复制的是源文件的数据,还是指向源文件数据的地址

    1.引用   b=a时,理解为b指向了a指向的数据,相当于引用复制

    a=[1,2]
    b=a
    #验证复制的是数据还是地址
    #1.查看ab的地址
    id(a)  #2677646858824
    id(b) #2677646858824
    #2. a增加1个元素,查看b是否增加
    a.append(3)
    a #[1,2,3]
    b #[1,2,3]

     2. 浅拷贝--copy.copy()

    import copy
    a=[1,2]
    b=[3,4]
    c=[a,b]
    d=copy.copy(c)
    
    #验证问题1:d是否执行c地址
    #验证方法1
    id(d) #2677647114120
    id(c) #2677644514824
    #验证方法2
    c.append(6)
    c  #[[1, 2], [3, 4], 6]
    d  #[[1, 2], [3, 4]]
    结论:d没有指向c的地址
    
    验证问题2:d执行a,b的地址,还是只是复制了a,b的值
    #验证方法1
    id(d[0]) #2677647113672
    id(c[0]) #2677647113672
    #验证方法2
    a.append(5)
    c  #[[1, 2, 5], [3, 4]]
    d  #[[1, 2, 5], [3, 4]]
    结论:,d中的a与c中的a,地址相同,说明d中的a,与c中的a均指向a的地址的
    

      浅拷贝仅仅把最外面1层进行了copy,并没有把里面多层嵌套进行递归拷贝,里面的还是指向原来的地址

    3.深拷贝 copy.deepcopy()

    import copy
    a=[1,2]
    b=[3,4]
    c=[a,b]
    d=copy.deepcopy(c)
    
    #验证问题1:d是否执行c地址
    #验证方法1
    id(d) #2677647114120
    id(c) #2677644514824
    #验证方法2
    c.append(6)
    c  #[[1, 2], [3, 4], 6]
    d  #[[1, 2], [3, 4]]
    结论:d没有指向c的地址
    
    验证问题2:d执行a,b的地址,还是只是复制了a,b的值
    #验证方法1
    id(c[0]) #2677647113672
    id(d[0]) #2677645539912
    #验证方法2
    a.append(5)
    c  #[[1, 2, 5], [3, 4]]
    d  #[[1, 2], [3, 4]]
    结论:,d中的a与c中的a,地址不同,说明d中的a是复制了a的值,并没有指向a的地址
    

      深拷贝递归拷贝, 多层时,每层都拷贝对象的值

    4.深拷贝和浅拷贝的应用  

    a=[1,2]
    def aa(num):
        num.append(3)
        
    a #[1, 2]
    aa(a)
    a #[1, 2, 3]
    
    #结论:函数传递的实参,一定传递的是引用地址,所以函数会改变原数据
    
    #如果想不改变源数据需要复制,最好用深复制
    aa(copy.deepcopy(a))
    a  #[1, 2]
    

    5.注意事项

    a=(1,2)
    b=[1,2]
    a1=copy.copy(a)
    b1=copy.copy(b)
    id(a)   #2677645526152
    id(a1)  #2677645526152
    id(b)    #2677645754888
    id(b1)   #2677647113800
    #结论:元组即使是1层,copy不拷贝,相当实用"="
    
    #验证:元组中嵌套列表是都拷贝
    a=[1,2]
    b=(3,4,a)
    b1=copy.copy(b)
    id(b)   #2677645507248
    id(b1) #2677645507248
    #结论是不拷贝

    列表是可变的,,所以可以copy,元祖是不可变的,copy后改变不了,所以copy前后的2个set均不能被修改,但占用了2个空间,,没有意义但是浪费空间,所以不能copy

    a=(1,2)
    a1=copy.deepcopy(a)
    id(a)   #2677645531976
    id(a1) #2677645531976
    
    a=[1,2]
    b=(3,4,a)
    b1=copy.deepcopy(b)
    id(b)   #2677645547848
    id(b1) #2677645507896
    

     结论:如果copy的是对象多层嵌套中的对象都不可变,则深拷贝和浅拷贝都失效,仅仅指向引用,如果最外层不可变,内层嵌套中包含可变对象,浅拷贝不拷贝,指向引用,深拷贝进行copy 

    总结论:

    浅拷贝

    如果最外层是list可变的,浅拷贝只拷贝最外层,内部的指向引用,如果最外层是set不可变的,不论里面嵌套的可不可变,浅拷贝都不进行copy,只是指向引用

    深拷贝

    如果最外层是list可变的,深拷贝递归拷贝,如果最外层是set不可变的,里面嵌套的包含可变的,深拷贝进行copy,如果里面嵌套的也无可变的,深copy也不copy

    其他

    如果使用列表的切片,相当于copy.copy() 浅拷贝

    如果使用字典中的copy()方法,相当于copy.copy() 浅拷贝

  • 相关阅读:
    数据类面试题
    java二进制文件复制
    String源码
    集合类题目
    OBJ-C
    java文件(文件夹)操作
    java中输入方式Scanner和BufferedReader
    二次分发举例
    Eclipse常用快捷键
    c#获取新浪微博登录cookie
  • 原文地址:https://www.cnblogs.com/alasijia/p/12207004.html
Copyright © 2011-2022 走看看