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

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

当前回答

python中的每个变量(比如dict1或str或__builtins__)都是指向机器内部某个隐藏的柏拉图式“对象”的指针。

如果您设置dict1 = dict2,您只需将dict1指向与dict2相同的对象(或内存位置,或任何您喜欢的类比)。现在,dict1引用的对象就是dict2引用的对象。

你可以检查:dict1是dict2应该是True。另外,id(dict1)应该与id(dict2)相同。

你需要dict1 = copy(dict2),或者dict1 = deepcopy(dict2)。

复制和深度复制的区别是什么?Deepcopy将确保dict2的元素(你是否将它指向一个列表?)也是副本。

我不怎么使用深度复制——编写需要它的代码通常是一种糟糕的实践(在我看来)。

其他回答

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

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

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

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

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

Python从不隐式复制对象。当您设置dict2 = dict1时,您将使它们引用相同的dict对象,因此当您更改它时,对它的所有引用都将引用处于当前状态的对象。

如果您想复制字典(这是罕见的),您必须显式地使用

dict2 = dict(dict1)

or

dict2 = dict1.copy()

你可以直接使用:

dict2 = eval(repr(dict1))

其中对象dict2是dict1的独立副本,因此可以修改dict2而不影响dict1。

这适用于任何类型的对象。

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

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'}
>>>

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

Python中的赋值语句不复制对象,而是在目标和对象之间创建绑定。

因此,dict2 = dict1,结果在dict2和dict1引用的对象之间产生另一个绑定。

如果你想复制字典,你可以使用copy模块。 复制模块有两个接口:

copy.copy(x)
Return a shallow copy of x.

copy.deepcopy(x)
Return a deep copy of x.

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

浅拷贝构造一个新的复合对象,然后(在可能的范围内)将对原始对象的引用插入其中。

深度复制构造一个新的复合对象,然后递归地将原始对象中的对象的副本插入其中。

例如,在python 2.7.9中:

>>> import copy
>>> a = [1,2,3,4,['a', 'b']]
>>> b = a
>>> c = copy.copy(a)
>>> d = copy.deepcopy(a)
>>> a.append(5)
>>> a[4].append('c')

结果是:

>>> a
[1, 2, 3, 4, ['a', 'b', 'c'], 5]
>>> b
[1, 2, 3, 4, ['a', 'b', 'c'], 5]
>>> c
[1, 2, 3, 4, ['a', 'b', 'c']]
>>> d
[1, 2, 3, 4, ['a', 'b']]