协慌网

登录 贡献 社区

如何复制字典并仅编辑副本

有人可以向我解释一下吗?这对我来说毫无意义。

我将字典复制到另一个字典中,然后编辑第二个字典,并且两者都已更改。为什么会这样呢?

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict1
>>> dict2
{'key2': 'value2', 'key1': 'value1'}
>>> dict2["key2"] = "WHY?!"
>>> dict1
{'key2': 'WHY?!', 'key1': 'value1'}

答案

Python 绝不会隐式复制对象。设置dict2 = dict1dict2 = dict1它们引用同一精确的 dict 对象,因此,在对它进行突变时,对其的所有引用都将始终引用该对象的当前状态。

如果要复制字典(这种情况很少见),则必须使用

dict2 = dict(dict1)

要么

dict2 = dict1.copy()

当你将dict2 = dict1 ,你是不是做的副本dict1 ,它导致dict2是为另一个名称而已dict1

要复制字典等可变类型,请使用copy模块的copy / deepcopy

import copy

dict2 = copy.deepcopy(dict1)

虽然dict.copy()dict(dict1)生成一个副本,但它们只是浅表副本。如果要拷贝,则需要copy.deepcopy(dict1) 。一个例子:

>>> source = {'a': 1, 'b': {'m': 4, 'n': 5, 'o': 6}, 'c': 3}
>>> copy1 = x.copy()
>>> copy2 = dict(x)
>>> import copy
>>> copy3 = copy.deepcopy(x)
>>> source['a'] = 10  # a change to first-level properties won't affect copies
>>> source
{'a': 10, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> copy1
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> copy2
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> copy3
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> source['b']['m'] = 40  # a change to deep properties WILL affect shallow copies 'b.m' property
>>> source
{'a': 10, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> copy1
{'a': 1, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> copy2
{'a': 1, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> copy3  # Deep copy's 'b.m' property is unaffected
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}

关于浅拷贝和深拷贝,来自Python copy模块 docs

浅表复制和深度复制之间的区别仅与复合对象(包含其他对象的对象,如列表或类实例)有关:

  • 浅表副本构造一个新的复合对象,然后(在可能的范围内)将对原始对象中引用的对象的引用插入其中。
  • 深层副本会构造一个新的复合对象,然后递归地将原始对象中发现的对象的副本插入其中。