我设置了dict2 = dict1。当我编辑dict2时,原来的dict1也改变了。为什么?

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

当前回答

在Python 2.7和3中创建字典副本的最佳和最简单的方法是…

创建一个简单(单层)字典的副本:

1. 使用dict()方法,而不是生成指向现有dict的引用。

my_dict1 = dict()
my_dict1["message"] = "Hello Python"
print(my_dict1)  # {'message':'Hello Python'}

my_dict2 = dict(my_dict1)
print(my_dict2)  # {'message':'Hello Python'}

# Made changes in my_dict1 
my_dict1["name"] = "Emrit"
print(my_dict1)  # {'message':'Hello Python', 'name' : 'Emrit'}
print(my_dict2)  # {'message':'Hello Python'}

2. 使用python字典内置的update()方法。

my_dict2 = dict()
my_dict2.update(my_dict1)
print(my_dict2)  # {'message':'Hello Python'}

# Made changes in my_dict1 
my_dict1["name"] = "Emrit"
print(my_dict1)  # {'message':'Hello Python', 'name' : 'Emrit'}
print(my_dict2)  # {'message':'Hello Python'}

创建一个嵌套的或复杂的字典的副本:

使用内置的复制模块,它提供了通用的浅拷贝和深拷贝操作。此模块在Python 2.7和3中都有

import copy

my_dict2 = copy.deepcopy(my_dict1)

其他回答

深度和简单的记忆方法:

当你执行dict2 = dict1时,dict2指向dict1。dict1和dict2都指向内存中的相同位置。这只是在python中使用可变对象时的正常情况。当你在python中使用可变对象时,你必须小心,因为它很难调试。

你不应该使用dict2 = dict1,而是应该使用python的copy模块中的copy(浅拷贝)和deepcopy方法来分离dict2和dict1。

正确的做法是:

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict1.copy()
>>> dict2
{'key1': 'value1', 'key2': 'value2'}
>>> dict2["key2"] = "WHY?"
>>> dict2
{'key1': 'value1', 'key2': 'WHY?'}
>>> dict1
{'key1': 'value1', 'key2': 'value2'}
>>> id(dict1)
140641178056312
>>> id(dict2)
140641176198960
>>> 

正如您可以看到的,dict1和dict2的id是不同的,这意味着它们都指向/引用内存中的不同位置。

此解决方案适用于具有不可变值的字典,但不适用于具有可变值的字典。

Eg:

>>> import copy
>>> dict1 = {"key1" : "value1", "key2": {"mutable": True}}
>>> dict2 = dict1.copy()
>>> dict2
{'key1': 'value1', 'key2': {'mutable': True}}
>>> dict2["key2"]["mutable"] = False
>>> dict2
{'key1': 'value1', 'key2': {'mutable': False}}
>>> dict1
{'key1': 'value1', 'key2': {'mutable': False}}
>>> id(dict1)
140641197660704
>>> id(dict2)
140641196407832
>>> id(dict1["key2"])
140641176198960
>>> id(dict2["key2"])
140641176198960

你可以看到,尽管我们对dict1应用了copy,但在dict2和dict1上,mutable的值都被更改为false,尽管我们只在dict2上更改了它。这是因为我们改变了dict1中可变dict部分的值。当我们在dict上应用复制时,它只会做一个浅复制,这意味着它将所有不可变的值复制到一个新的dict中,而不复制可变的值,但它会引用它们。

最终的解决方案是对dict1进行深度复制,以完全创建一个包含复制的所有值(包括可变值)的新dict。

>>>import copy
>>> dict1 = {"key1" : "value1", "key2": {"mutable": True}}
>>> dict2 = copy.deepcopy(dict1)
>>> dict2
{'key1': 'value1', 'key2': {'mutable': True}}
>>> id(dict1)
140641196228824
>>> id(dict2)
140641197662072
>>> id(dict1["key2"])
140641178056312
>>> id(dict2["key2"])
140641197662000
>>> dict2["key2"]["mutable"] = False
>>> dict2
{'key1': 'value1', 'key2': {'mutable': False}}
>>> dict1
{'key1': 'value1', 'key2': {'mutable': True}}

正如您所看到的,id是不同的,这意味着dict2完全是一个新的dict,其中包含dict1中的所有值。

当你想改变任何可变值而不影响原始字典时,需要使用Deepcopy。如果不是,你可以使用浅拷贝。Deepcopy很慢,因为它递归地复制原始字典中的任何嵌套值,还需要额外的内存。

你也可以用字典理解来创建一个新字典。这避免了导入副本。

dout = dict((k,v) for k,v in mydict.items())

当然,在python >= 2.7中,你可以这样做:

dout = {k:v for k,v in mydict.items()}

但对于向后比较。,上面的方法更好。

除了其他提供的解决方案,您还可以使用**将字典集成到一个空字典中,例如:

Shallow_copy_of_other_dict = {**other_dict}。

现在您将拥有other_dict的“浅”副本。

应用于你的例子:

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

指针:浅拷贝和深拷贝的区别

如果你的字典是映射类型,你不能.copy()它,但你可以

dict2 = dict1 | {}

它有点模糊,与copy.copy(dict1)相比,我不能说它的性能如何,但它非常简洁。

下面的代码是在dicts上的,它遵循json语法,比deepcopy快3倍以上

def CopyDict(dSrc):
    try:
        return json.loads(json.dumps(dSrc))
    except Exception as e:
        Logger.warning("Can't copy dict the preferred way:"+str(dSrc))
        return deepcopy(dSrc)