python中的shallow copy 和 deep copy

本文深入探讨了Python中对象赋值的引用传递特性,并通过实例详细解释了浅拷贝与深拷贝的区别。同时介绍了如何利用copy模块实现列表的完全拷贝。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值