嵌套字典 copy() 还是 deepcopy()? [复制]

Posted

技术标签:

【中文标题】嵌套字典 copy() 还是 deepcopy()? [复制]【英文标题】:Nested dictionaries copy() or deepcopy()? [duplicate] 【发布时间】:2017-01-21 08:18:19 【问题描述】:

我尝试在代码的开头存储一个字典模板,大多数函数都会使用该模板:

字典:键 = 客户端名称,值 = 字典 2 字典 2:键 = 用户名,值 = 无

我填满了我们所有的客户和他们的用户。然后代码的每一部分都可以复制这个字典并产生它自己的输出。目标是每个输出都将具有相同的“基本”字典结构,就像可以修改 None 的模板一样。

对于使用此词典的每个进程,我使用以下内容:

process1dict = clientdict 
# processing 1
output1dict = ... #modified version of original clientdict, the None values have been replaced by dictionaries/lists

process2dict = clientdict
# processing 2
output2dict = ... #same here but could be different

我遇到的问题是每次将客户端复制到进程中时都会更改! 我注意到由于我最初的cliendict 中的None 值,它在每个进程之后都会发生变化(当然取决于每个进程的输出)。

编辑:我找到了复制库,但 copy() 似乎对我的情况没有帮助。我将尝试 deepcopy() 但为什么 copy() 不起作用?为什么deepcopy()会?

【问题讨论】:

是的,你需要做deepcopy -> 没有它clientdictDNT只是指向同一个底层字典,所以当你修改clientdict时会被修改你也可以dict(clientdict)或@987654331 @ 您应该阅读这篇文章:Facts and myths about Python names and values,作者是 SO 老将 Ned Batchelder。 如果您不使用 deepcopy(),您的新词典成员将指向嵌入在基本词典中的词典。 deepcopy() 复制被复制字典中的内容。 感谢您的文章和回答。如果我理解正确,因为我使用的是可变对象的嵌套字典,如果我执行“copy()”并且在我的进程中使用了一些“更改”函数,例如“.append()”,它将直接将更改链接到值本身(特别是这里的“无”值)。如果我想像字典模板一样使用它(就像我在这里做的那样),我认为使用“deepcopy()”会更好。我明天试试看! 【参考方案1】:

当您使用字典或列表等可变集合并执行分配时,默认情况下您不会创建该对象的副本 - 即,将某些 dict b 分配给另一个 dict a 创建从 b 到原始对象 a 的引用,这样当你改变 b 时,你也间接地改变了 a

查看这个基本示例:

>>> orig = "a": 1, "b": 2
>>> new = orig
>>> new["a"] = 9
>>> orig
'a': 9, 'b': 2
>>> new
'a': 9, 'b': 2
>>> new is orig
True

要解决此问题并保持neworig 字典分隔不相互引用的对象,请在将其分配给new 时将deepcopy 分配给orig

>>> import copy
>>> orig = "a": 1, "b": 2
>>> new = copy.deepcopy(orig)
>>> new["a"] = 9
>>> orig
'a': 1, 'b': 2
>>> new
'a': 9, 'b': 2
>>> new is orig
False

另外,这里是上面链接的 Python 文档的 tl;dr:

Python 中的赋值语句不会复制对象,它们会在目标和对象之间创建绑定。对于可变集合或包含可变项的集合,有时需要一个副本,以便可以更改一个副本而不更改另一个副本。

【讨论】:

在许多情况下,深度复制不是必需的,而且实际上可能是有害的。如果您有一个属于两个客户端的对象User("Somebody"),您可能不想将它们拆分为两个等效的对象并分别对其进行变异。如果您不想要或不需要copy.deepcopy,您可以改用dict.copyorig = "a": 1, "b": 2; new = orig.copy() 在这种特殊情况下,我没有属于两个客户端的用户名对象。我现在遇到的问题是,这个“clientdict”字典被用作模板,而“None”值被用作空白字符来填充进程中字典的其余部分。当我第一次尝试在写问题的最后一分钟使用“copy()”时,我发现它不起作用,我想我现在明白了为什么感谢你们的 cmets!谢谢大家 #upvote。这很深刻;)而且很有帮助 你救了我的夜芽!谢谢 =)

以上是关于嵌套字典 copy() 还是 deepcopy()? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

Python 函数参数引用(传值/传址)/copy/deepcopy

day3 字典,集合,文件

Python 中copy和deepcopy的区别

copy与deepcopy

python3下关于copy和deepcopy中的区别

Python-copy()与deepcopy()区别