python 浅拷贝和深拷贝浅析

编码过程中发现,列表a和b,初始化a,b拷贝a,b中元素值改过之后,a中元素也会跟着修改,一直以为是自己代码逻辑出了错误,最后发现这里的坑是python中浅拷贝和深拷贝的机制


在python中,对象的属性值有:对象id(内存地址),对象类型,对象值

id:唯一标识一个对象:if a is b的判断方式
Type:标识对象的类型
Value:对象的值:if a ==b的判断方式

一、赋值

python中,赋值a=b,实际上是b拷贝了a的引用,这里“=”只是把a对象的引用传递给b对象而已,原始列表改变,b也会改变,因为a和b都是对原始列表的引用

如下:b = a ,对象a赋值给b,这里面a和b指向的就是同一个对象,a和b只不过是这个对象的两个引用而已,共享一个对象

a = ['str',1,2,3,4,5]
b = a
a[0] = 'sss'
a[1] = 10
print id(a[0]),id(b[0])
print id(a[1]),id(b[1])
print a,b
111594624 111594624
110736892 110736892
['sss', 10, 2, 3, 4, 5] ['sss', 10, 2, 3, 4, 5]

二、浅拷贝(shallow copy)

浅拷贝:import copy

如下可以看到与上述赋值是不同的,浅拷贝产生新的对象,但是子对象不拷贝;

a中对象值修改之后,id是变化的,修改值之后不会影响原来的值,但是如果对象中有子对象(如下a[6]是个list),并且是可变对象,id是不变的,修改子对象会同步修改原来的值,即共享子对象

import copy
a = ['str',1,2,3,4,5,[6,7]]
b = copy.copy(a)
print id(a[0]),id(b[0])
print id(a[1]),id(b[1])
print id(a[6][0]),id(b[6][0])
print a,b
print '   '
a[0] = 'sss'
print id(a[0]),id(b[0])
print id(a[1]),id(b[1])
print id(a[6][0]),id(b[6][0])
print a,b
print '   '
a[1] = 10
print id(a[0]),id(b[0])
print id(a[1]),id(b[1])
print id(a[6][0]),id(b[6][0])
print a,b
print '   '
a[6][0] = 666
print id(a[0]),id(b[0])
print id(a[1]),id(b[1])
print id(a[6][0]),id(b[6][0])
print a,b
print '   '
112149136 112149136
112572008 112572008
112571948 112571948
['str', 1, 2, 3, 4, 5, [6, 7]] ['str', 1, 2, 3, 4, 5, [6, 7]]
   
113793120 112149136
112572008 112572008
112571948 112571948
['sss', 1, 2, 3, 4, 5, [6, 7]] ['str', 1, 2, 3, 4, 5, [6, 7]]
   
113793120 112149136
112571900 112572008
112571948 112571948
['sss', 10, 2, 3, 4, 5, [6, 7]] ['str', 1, 2, 3, 4, 5, [6, 7]]
   
113793120 112149136
112571900 112572008
113722716 113722716
['sss', 10, 2, 3, 4, 5, [666, 7]] ['str', 1, 2, 3, 4, 5, [666, 7]]
   

注:类似于[0,0,0]*4这样的二维数组,也是浅拷贝的一种,多维数组初始化推荐如下循环方法

list=[[0 for t in range(2)]for i in range(3)]
print list
list[0][1] = 2
print list
[[0, 0], [0, 0], [0, 0]]
[[0, 2], [0, 0], [0, 0]]

三、深拷贝

深拷贝:import copy

拷贝产生新的对象,包含子对象的拷贝,是个完全新的对象

a中对象值修改之后,id是变化的,修改值之后不会影响原来的值,即便对象中有子对象(如下a[6]是个list),并且是可变对象,id是不变的,修改子对象也不会影响原来的值!

import copy
a = ['str',1,2,3,4,5,[6,7]]
b = copy.deepcopy(a)
print id(a[0]),id(b[0])
print id(a[1]),id(b[1])
print id(a[6]),id(b[6])
print id(a[6][0]),id(b[6][0])
print a,b
print '   '
a[0] = 'sss'
print id(a[0]),id(b[0])
print id(a[1]),id(b[1])
print id(a[6]),id(b[6])
print id(a[6][0]),id(b[6][0])
print a,b
print '   '
a[1] = 10
print id(a[0]),id(b[0])
print id(a[1]),id(b[1])
print id(a[6]),id(b[6])
print id(a[6][0]),id(b[6][0])
print a,b
print '   '
a[6][0] = 666
print id(a[0]),id(b[0])
print id(a[1]),id(b[1])
print id(a[6]),id(b[6])
print id(a[6][0]),id(b[6][0])
print a,b
print '   '
38093456 38093456
38516328 38516328
111663624 111724384
38516268 38516268
['str', 1, 2, 3, 4, 5, [6, 7]] ['str', 1, 2, 3, 4, 5, [6, 7]]
   
112106096 38093456
38516328 38516328
111663624 111724384
38516268 38516268
['sss', 1, 2, 3, 4, 5, [6, 7]] ['str', 1, 2, 3, 4, 5, [6, 7]]
   
112106096 38093456
38516220 38516328
111663624 111724384
38516268 38516268
['sss', 10, 2, 3, 4, 5, [6, 7]] ['str', 1, 2, 3, 4, 5, [6, 7]]
   
112106096 38093456
38516220 38516328
111663624 111724384
112018780 38516268
['sss', 10, 2, 3, 4, 5, [666, 7]] ['str', 1, 2, 3, 4, 5, [6, 7]]
   

猜你喜欢

转载自blog.csdn.net/weixin_43533825/article/details/83544162