Python深拷贝与浅拷贝说明与举例

Posted 詩和遠方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python深拷贝与浅拷贝说明与举例相关的知识,希望对你有一定的参考价值。

知识准备

  • 可变类型(mutable):list、set、dict可变类型,支持原地址直接改变元素(item)的值
  • 不可变类型(immutable):int、float、str、tuple等均为不可变类型,不支持原地址改变元素的值

相关例子见另一篇博文深刻理解python变量

浅拷贝说明与举例

无拷贝

a = [1,2,(3,4)]
b = a
b[0] = 4
print('id(a) =',id(a))
print('id(b) =',id(b))
print('a =',a)
print('b =',b)
结果:
	id(a) = 2848475391240
	id(b) = 2848475391240
	a = [4, 2, (3, 4)]
	b = [4, 2, (3, 4)]

直接赋值,相当于取了别名,其地址是一样的,所以对b元素的修改,也影响了a。

浅拷贝(Shallow Copy)

使用构造函数list,切片或copy.copy()函数可浅拷贝列表

a = [1,2,[3,4]]
b = list(a) # 拷贝列表a值,而不是引用
b[0] = 4
print('id(a) =',id(a))
print('id(b) =',id(b))
print('a =',a)
print('b =',b)
结果:
	id(a) = 2848460025992
	id(b) = 2848475458632
	a = [1, 2, [3, 4]]
	b = [4, 2, [3, 4]]

发现a和b的地址不同,对b的改变不会影响a,但这仅对不可变元素成立,因为对不可变元素的修改,会生成新的对象,从而指向新的地址,而原来a列表中的元素还是指向老地址。
由于b[2]是一个List,为可变类型,若对b[2]元素的进行修改,a也会一起变:

b[2][0] = 100
print('id(a) =',id(a))
print('id(b) =',id(b))
print('a =',a)
print('b =',b)
结果:
	id(a) = 2848481489096
	id(b) = 2848477955016
	a = [1, 2, [100, 4]]
	b = [4, 2, [100, 4]]

a[2][0]和b[2][0]的值都变为100。
所以浅拷贝只是拷贝了第一层地址,如果列表中含可变类型元素,则对副本的修改也可能会影响原来的值。

深拷贝(Deep Copy)

为了解决以上问题,python有一个copy模块可以实现深拷贝,deepcopy为深拷贝,copy为浅拷贝。

import copy
a = [1,2,[3,4]]
b = copy.deepcopy(a)
b[2][0] = 100
print('id(a) =',id(a))
print('id(b) =',id(b))
print('a =',a)
print('b =',b)
结果:
	id(a) = 2848487131400
	id(b) = 2848487129480
	a = [1, 2, [3, 4]]
	b = [1, 2, [100, 4]]

b[2][0]的值不再影响a[2][0]。
深拷贝不仅复制列表第一层的地址,若列表中含有可变类型元素,则其对应元素也一起复制,依此类推,有多少层可变类型引用,就复制多少层。

可变与不可变元素深拷贝的区别

同样是深拷贝,当所拷贝对象可变或不可变属性不一样时,情况是不一样的:

import copy
a = [1,(2,3),[4,5]]
b = copy.deepcopy(a)
print('a = ',id(a))
for x in a: print(' ',id(x))
print('b = ',id(b))
for x in b: print(' ',id(x))
结果:
	a =  2848483339784
	  140711207018896
	  2848488706632
	  2848487130696
	b =  2848487129608
	  140711207018896
	  2848488706632
	  2848482189128 (地址不同)

以上1和(2,3)均为不可变类型,所以即便是深拷贝,在拷贝后的列表b中,其地址还是一致的,但[4,5]是可变类型,拷贝后地址也变了。

画图助理解

最后画一张简单的图帮助理解(add为address缩写):

开发者涨薪指南 48位大咖的思考法则、工作方式、逻辑体系

以上是关于Python深拷贝与浅拷贝说明与举例的主要内容,如果未能解决你的问题,请参考以下文章

[随笔重写] Python3 的深拷贝与浅拷贝

Python中list的复制及深拷贝与浅拷贝探究

python中的深拷贝与浅拷贝

python深拷贝与浅拷贝

深拷贝与浅拷贝的区别,实现深拷贝的几种方法

Python中的深拷贝与浅拷贝