python中的shallow copy 和 deep copy
程序员文章站
2022-06-03 14:25:24
...
- 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://*.com/questions/17873384/deep-copy-a-list-in-python