嵌套字典 copy() 还是 deepcopy()?

2022-01-20 00:00:00 python 复制 dictionary deep-copy

问题描述

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

I tried to store a dictionary template at the beginning of my code that most of the functions will use:

  • 字典:keys = 客户端名称,values = Dictionary2
  • 字典 2:键 = 用户名,值 = 无

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

I filled it with all our clients and their users. Then each part of the code can copy this dictionary and produces it's owns outputs. The goal is that each output will have the same "base" dictionary structure like a template where None can be modified.

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

For each process using this dictionnary I use the following :

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

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

The problem that I have is that the cliendict changes each time it is copied into a process! I noticed that because of the None value in my initial cliendict it changes after each process (depending on the output of each one of course).

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

I found the copy library but copy() seems to not help my case. I will try out the deepcopy() but why did copy() didn't worked? And why deepcopy() will?


解决方案

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

When you're working with a mutable collection like a dictionary or a list, and you perform an assignment, you are not creating a copy of that object by default – i.e., the assignment of some dict b to another dict a creates a reference from b to the original object a, such that when you mutate b you indirectly also mutate 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 字典将不相互引用的对象分开,请创建一个 deepcopy of orig 将其分配给 :

To fix this and keep the new and orig dictionaries separate objects that do not reference each other, make a deepcopy of orig when assigning it to new:

>>> 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:

Also, here's a tl;dr for the Python documentation linked to above:

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

Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other.

相关文章