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

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

当前回答

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)

其他回答

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

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

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

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

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

在python 3.5+上,有一种更简单的方法来实现浅拷贝,即使用** unpackaging操作符。由Pep 448定义。

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

**将字典解包到一个新字典中,然后分配给dict2。

我们还可以确认每个字典都有一个不同的id。

>>>id(dict1)
 178192816

>>>id(dict2)
 178192600

如果需要深度复制,那么copy.deepcopy()仍然是可行的方法。

另一种更简洁的方法是使用json。参见下面的代码

>>> a = [{"name":"Onkar","Address": {"state":"MH","country":"India","innerAddress":{"city":"Pune"}}}]
>>> b = json.dumps(a)
>>> b = json.loads(b)
>>> id(a)
2334461105416
>>> id(b)
2334461105224
>>> a[0]["Address"]["innerAddress"]["city"]="Nagpur"
>>> a
[{'name': 'Onkar', 'Address': {'state': 'MH', 'country': 'India', 'innerAddress': {'city': 'Nagpur'}}}]
>>> b
[{'name': 'Onkar', 'Address': {'state': 'MH', 'country': 'India', 'innerAddress': {'city': 'Pune'}}}]
>>> id(a[0]["Address"]["innerAddress"])
2334460618376
>>> id(b[0]["Address"]["innerAddress"])
2334424569880

要创建另一个字典,请在同一个字典对象上执行json.dumps()和json.loads()。你将有单独的字典对象。

使用for循环进行复制:

orig = {"X2": 674.5, "X3": 245.0}

copy = {}
for key in orig:
    copy[key] = orig[key]

print(orig) # {'X2': 674.5, 'X3': 245.0}
print(copy) # {'X2': 674.5, 'X3': 245.0}
copy["X2"] = 808
print(orig) # {'X2': 674.5, 'X3': 245.0}
print(copy) # {'X2': 808, 'X3': 245.0}

你可以直接使用:

dict2 = eval(repr(dict1))

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

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