python字典和列表赋值的坑

在 二 18 十二月 2018 发布于 TECH SKILLS 分类 • 1 min read

今天在实际脚本中遇到了一个python的变量赋值的坑,将字典从一个变量a赋值给另外一个变量b之后,修改了原始变量a的值,本意是保持b变量为原始值不动,结果修改a之后发现b的值也随着改变了,经过一番查询以及自己的测试之后,确认原来python中的list和dict数据类型采用的是浅拷贝。

列表的具体测试如下:

>>> a = ['1']
>>> b = a
>>> a.append('2')
>>> a
['1', '2']
>>> b
['1', '2']

可以看到当改变a的值时,b的值也跟着一起改变了。 再看字典的例子:

>>> ar = {'x':'1','y':'2'}
>>> br = ar
>>> br
{'y': '2', 'x': '1'}
>>> ar['x'] = '3'
>>> br
{'y': '2', 'x': '3'}
>>> ar
{'y': '2', 'x': '3'}

其实还可以有更简单的验证方式,即查看变量的id值:

>>> id(a)
139930012177976
>>> id(b)
139930012177976
>>> id(ar)
139930012303440
>>> id(br)
139930012303440

可以看到他们虽然变量名不一样,但实际指向的内存地址是同一个(称之为浅拷贝),所以修改任意一个的值,意味着变量值都改变了。

如果想要实现深拷贝,即开头提到的原本需求,实现深拷贝,则需要用到deepcopy功能,具体使用如下:

>>> from copy import deepcopy
>>> a = ['1']
>>> b = deepcopy(a)
>>> a.append('2')
>>> a
['1', '2']
>>> b
['1']
>>> id(a)
139930012252784
>>> id(b)
139930012253000

从上面的测试可以看到,a和b分别指向了两个不同的内存地址,这样修改a的值并不会影响b的值了。