一、问题引出浅拷贝
首先看下面代码的执行情况:
a = [1, 2, 3]print('a = %s' % a) # a = [1, 2, 3]b = aprint('b = %s' % b) # b = [1, 2, 3]a.append(4) # 对a进行修改print('a = %s' % a) # a = [1, 2, 3, 4]print('b = %s' % b) # b = [1, 2, 3, 4]b.append(5) # 对b进行修改print('a = %s' % a) # a = [1, 2, 3, 4, 5]print('b = %s' % b) # b = [1, 2, 3, 4, 5]
上面的代码比较简单,定义了一个变量a,它是一个数值[1, 2, 3]的列表,通过一个简单的赋值语句 b = a 定义变量b,它同样也是数值[1, 2, 3]的列表。
问题是:如果此时修改变量a,对b会有影响吗?同样如果修改变量b,对a又会有影响吗?
从代码运行结果可以看出,无论是修改b还是修改a(注意这种修改的方式,是用append,直接修改原列表,而不是重新赋值),都另一方都是有影响的。
当然这个原因其实很好理解,变量a指向的是列表[1, 2, 3]的地址值,当用 = 进行赋值运算时,b的值也相应的指向的列表[1, 2, 3]的地址值。在python中,可以通过id(变量)的方法来查看地址值,我们来查看下a,b变量的地址值,看是不是相等:
# 注意,不同机器上,这个值不同,但只要a,b两个变量的地址值是一样的就能说明问题了print(id(a)) # 4439402312print(id(b)) # 4439402312
所以原理如下图所示:
因此,只要是在地址值:4439402312上的列表进行修改的话,a,b都会发生变化。(注意我这里说的修改,是在地址值为:4439402312上的列表进行的修改,而不说对变量a进行修改,因为对变量a的修改方式有两种,本文结尾会解释为什么不说对变量a进行修改) 。所以我们便引出了以下概念:
对于这种是将引用进行拷贝赋值给另一个变量的方式(即拷贝的是地址值),我们称之为浅拷贝。
二、如何进行深拷贝
python中实现深拷贝的方式很简单,只需要引入copy模块,调用里面的deepcopy()的方法即可,示例代码如下:
import copya = [1, 2, 3]b = copy.deepcopy(a)print('a = %s' % a) # a = [1, 2, 3]print('b = %s' % b) # b = [1, 2, 3]b.append(4)print('a = %s' % a) # a = [1, 2, 3]print('b = %s' % b) # b = [1, 2, 3, 4]
从代码执行情况来看,我们已经实现了深拷贝。这时我们再来看下两个变量的地址值:
print(id(a)) # 4321416008print(id(b)) # 4321416200
果然就不一样了。我们再通过一个图来看下深拷贝的原理:
三、copy模块方法简介
从深拷贝的实现过程,我们知道copy模块,也使用了里面的deepcopy()方法。下面我们来介绍下copy模块中的copy()与deepcopy()方法。
首先介绍我们已经使用过的deepcopy()方法,官方文档介绍如下:
新闻热点
疑难解答