在python中进行字典的赋值的时候发现了一个问题:
有一个列表b=[{'a':1,'b':2}],列表b中现在只有一个字典{‘a':1,'b':2}。
现在要在b中添加另一个字典,这个字典的key和b中现有字典的key一样,但是value是它的两倍。
于是我写了下面这段代码:
b=[{'a':1,'b':2}]
c=b[0]
for x,y in c.items():
c[x]=y*2
b.append(c)
print(b)
本来期待它能够输出[{'a': 1, 'b': 2}, {'a': 2, 'b': 4}],可是运行后b的值是这样的:[{'a': 2, 'b': 4}, {'a': 2, 'b': 4}],
b中原来的字典也改变了。如果要让b中原来的字典不改变就需要用到深拷贝(在这个例子中浅拷贝也可以)。
现在来了解一下直接赋值、浅拷贝和深拷贝:
1.直接赋值
上面代码中c=b[0]其实是给b[0]对象取了一个别名,也就是说c和b[0]指向同一个对象,所以c修改后b[0]也被修改了。
(和c++中的引用很像)
代码和运行结果:
b=[{'a':1,'b':2}]
c=b[0]
for x,y in c.items():
c[x]=y*2
b.append(c)
print(b)
#输出结果是[{'a': 2, 'b': 4}, {'a': 2, 'b': 4}]
2.浅拷贝
调用b[0]对象的copy()函数就可以获得一个b[0]的浅拷贝对象。
比如:c=b[0].copy()
这样一来,如果b[0]中value是简单值而不是容器的话,那么对c的修改不会改变b[0]。
因为对于简单值,浅拷贝复制的是值本身,所以并不会改变原来的对象。
代码和运行结果:
b=[{'a':1,'b':2}]
c=b[0].copy()
for x,y in c.items():
c[x]=y*2
b.append(c)
print(b)
#[{'a': 1, 'b': 2}, {'a': 2, 'b': 4}]
但是如果b[0]对象中value的值是一个容器(比如一个列表),那么对c的修改就会改变b[0]的值。
因为对于容器,拷贝的是别名,所以他们是指向同一个容器的,那么改变c自然后改变b[0]
代码:
b={'a':1,'b':[1,2]}
c=b.copy()
c['a']=2
c['b'].remove(1)
print(b)
#输出{'a': 1, 'b': [2]}
3.深拷贝
如:c=copy.deepcopy(b[0]) #需要导入copy
这样拷贝后c和b[0]就完全是两个不同的对象,他们之间没有任何关系,即使b[0]中的value是一个容器,修改c也不会对b[0]产生任何影响。
代码:
import copy
b={'a':1,'b':[1,2]}
c=copy.deepcopy(b)
c['a']=2
c['b'].remove(1)
print(b)
#输出{'a': 1, 'b': [1, 2]}