python中的shallow copy 和 deep copy

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lx_ros/article/details/79977699
  • Python中的对象之间赋值时是按引用传递的,如果需要拷贝对象,需要使用标准库中的copy模块。
  • 1.copy.copy 浅拷贝 只拷贝父对象
  • 2.copy.deepcopy 深拷贝 拷贝父对象及其子对象
  • 3.例子解读:

    >>>x=5
    >>>y=x
    >>>id(x)==id(y)
    True
    
    #刚开始y和x是相同的地址,现在对y赋值
    
    >>>y=10
    >>>id(x)==id(y)
    False
    
    #赋值后y将会有新的地址
    
    
    #若是
    
    >>>x=y#结果就又不一样了

    所以,python默认的是拷贝是对变量的引用,要实现真正的拷贝需要调用copy模块

    列表的拷贝

    >>> colours1 = ["red", "blue"]
    >>> colours2 = colours1
    >>> print(colours1)
    ['red', 'blue']
    >>> print(colours2)
    ['red', 'blue']
    >>> print(id(colours1),id(colours2))
    43444416 43444416
    >>> colours2 = ["rouge", "vert"]
    >>> print(colours1)
    ['red', 'blue']
    >>> print(colours2)
    ['rouge', 'vert']
    >>> print(id(colours1),id(colours2))
    43444416 43444200
    >>> 

    整体改变列表的时候,给引用变量生成了新的地址,再来看改变其中一个元素时,

    >>> colours1 = ["red", "blue"]
    >>> colours2 = colours1
    >>> print(id(colours1),id(colours2))
    14603760 14603760
    >>> colours2[1] = "green"
    >>> print(id(colours1),id(colours2))
    14603760 14603760
    >>> print(colours1)
    ['red', 'green']
    >>> print(colours2)
    ['red', 'green']
    >>> 

    改变引用时,原来变量的值也被改变。可以使用切片运算来进行列表的浅拷贝克服这个问题,

    >>> list1 = ['a','b','c','d']
    >>> list2 = list1[:]
    >>> id(list1)==id(list2)
    False
    >>> list2[1] = 'x'
    >>> print(list2)
    ['a', 'x', 'c', 'd']
    >>> print(list1)
    ['a', 'b', 'c', 'd']
    >>> 

    但是使用切片方法,在列表中包含子列表的时候,新的问题就又出现了,

    >>> lst1 = ['a','b',['ab','ba']]
    >>> lst2 = lst1[:]
    >>> id(lst1)==id(lst1)
    False
    >>> lst2[0] = 'c'
    >>> print(lst1)
    ['a', 'b', ['ab', 'ba']]
    >>> print(lst2)
    ['c', 'b', ['ab', 'ba']]
    
    #但是,若对list2中子列表中值进行修改,list1将还是会受到影响
    
    >>>lst2[2][1]='d'
    >>>print(lst2)
    ['c','b',['ab','d']]
    >>>print(lst1)
    ['a','b',['ab','d']]

    浅拷贝只对父列表进行了拷贝,没有对子列表进行拷贝。如图,

    浅拷贝

    为了解决这个问题,实现列表的完全拷贝,考虑使用copy模块的deepcopy函数,

    >>> from copy import deepcopy
    >>> 
    >>> lst1 = ['a','b',['ab','ba']]
    >>> 
    >>> lst2 = deepcopy(lst1)
    >>> 
    >>> lst1
    ['a', 'b', ['ab', 'ba']]
    >>> lst2
    ['a', 'b', ['ab', 'ba']]
    >>> id(lst1)==id(lst2)
    False
    >>>id(lst1[2][0])==id(lst2[2][0])
    False
    >>> lst2[2][1] = "d"
    >>> lst2[0] = "c"
    >>> print(lst1)
    ['a', 'b', ['ab', 'ba']]
    >>> print(lst2)
    ['c', 'b', ['ab', 'd']]
    >>> 

    其存储示意图如下:

    深拷贝

    测验:

    >>> import copy
    >>> a = [1,2,3,4,['a','b']]  #原始对象
    >>> b = a  #赋值,传对象的引用
    >>> c = copy.copy(a)
    >>> d = copy.deepcopy(a)
    >>> e = a[:]
    >>> a.append(5)
    >>> a[4].append('c')
    >>> print 'a=',a
    a= [1, 2, 3, 4, ['a', 'b', 'c'], 5]
    >>> print 'b=',b
    b= [1, 2, 3, 4, ['a', 'b', 'c'], 5] #引用
    >>> print 'c=',c
    c= [1, 2, 3, 4, ['a', 'b', 'c']]  #浅拷贝
    >>> print 'd=',d
    d= [1, 2, 3, 4, ['a', 'b']]      #深拷贝
    >>> print 'e'=,e
    e= [1, 2, 3, 4, ['a', 'b', 'c']]  #浅拷贝

  • refer

[1] https://www.python-course.eu/python3_deep_copy.php

[2] https://stackoverflow.com/questions/17873384/deep-copy-a-list-in-python

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页