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

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

当前回答

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

dict2 = dict1 | {}

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

其他回答

Dict1是一个引用底层字典对象的符号。将dict1赋值给dict2只是赋值相同的引用。通过dict2符号更改键的值将更改底层对象,这也会影响dict1。这很令人困惑。

推断不可变值比推断引用要容易得多,所以尽可能地复制:

person = {'name': 'Mary', 'age': 25}
one_year_later = {**person, 'age': 26}  # does not mutate person dict

这在语法上是相同的:

one_year_later = dict(person, age=26)

虽然dict.copy()和dict(dict1)会生成一个副本,但它们只是浅副本。如果你想要一个深度拷贝,copy.deepcopy(dict1)是必需的。一个例子:

>>> source = {'a': 1, 'b': {'m': 4, 'n': 5, 'o': 6}, 'c': 3}
>>> copy1 = source.copy()
>>> copy2 = dict(source)
>>> import copy
>>> copy3 = copy.deepcopy(source)
>>> 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复制模块docs:

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

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

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

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

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

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

对于嵌套的字典,不要使用dict(srcData)或srcData.copy()或{**srcData},因为如果你改变了秒级或更多,它也会修改源字典

srcData = {
  'first': {
    'second': 'second Value'
  }
}
newData = dict(srcData) # srcData.copy() or {**srcData}
newData['first']['second'] = 'new Second Value'

print(srcData)
print(newData)

# it will print
# srcData: {'first': {'second': 'new Second Value'}}
# newData:{'first': {'second': 'new Second Value'}}

# but it should be
# srcData: {'first': {'second': 'second Value'}}
# newData:{'first': {'second': 'new Second Value'}}

deepcopy的另一个选择是使用json技巧,如Javascript json .parse(json .stringify(obj))

import json

srcData = {'first': {'second': 'second Value'}}
newData = json.loads(json.dumps(srcData))
newData['first']['second'] = 'new Second Value'

print(srcData)
print(newData)

# srcData: {'first': {'second': 'second Value'}}
# newData: {'first': {'second': 'new Second Value'}}