我不理解这些情况:
content = {'a': {'v': 1}, 'b': {'v': 2}}
d1 = {'k1': {}}
d2 = {'k2': {}}
d1['k1'].update(content)
print(d1)
content['a']['v'] = 3
content['b']['v'] = 4
d2['k2'].update(content)
print(d2)
print(d1)
>>> {'k1': {'a': {'v': 1}, 'b': {'v': 2}}}
>>> {'k2': {'a': {'v': 3}, 'b': {'v': 4}}}
>>> {'k1': {'a': {'v': 3}, 'b': {'v': 4}}}
在上述情况下,更新变量 content 后,d1的内容会发生变化。
content = {'a': 1, 'b': 2}
d1 = {'k1': {}}
d2 = {'k2': {}}
d1['k1'].update(content)
print(d1)
content['a'] = 3
content['b'] = 4
d2['k2'].update(content)
print(d2)
print(d1)
>>> {'k1': {'a': 1, 'b': 2}}
>>> {'k2': {'a': 3, 'b': 4}}
>>> {'k1': {'a': 1, 'b': 2}}
然而,在这种情况下,即使变量 content 已更改,d1也不更改。我不明白为什么......任何想法?
答案 0 :(得分:7)
请参阅shallow vs deep副本。
此处的副本是浅层副本,因此第一级条目是副本,但嵌套结构是引用。
- 浅拷贝构造一个新的复合对象,然后(尽可能)将对它的引用插入到对象中 发现在原文中。
- 深层复制构造一个新的复合对象,然后递归地将复制品插入其中的对象中 原始
答案 1 :(得分:2)
两个代码段之间的主要区别在于content['a']['v'] = 3
与content['a'] = 3
完全不同。在第一种情况下,您通过更改其v
键来修改内部字典。在后一种情况下,您替换字典中的值而不修改。
当所有内容都是字典时,它会让人感到困惑,所以让我们用一个类的变量和实例替换字典:
class Person:
def __init__(self, name):
self.name = name
# these two variables are represent your `content` dict
a = Person('Andy') # this variable represents `{'v': 1}`
b = Person('Belle') # this variable represents `{'v': 2}`
# the equivalent of `d1['k1'].update(content)` is a simple assignment
k1_a = a
# and the equivalent of `content['a']['v'] = 3` is changing a's name
a.name = 'Aaron'
# because k1_a and a are the same Person instance, this is reflected in k1_a:
print(k1_a.name) # output: Aaron
这里要注意的关键点是
k1_a = a
没有制作此人的副本;类似于d1['k1'].update(content)
没有复制{'v': 1}
字典的方式。a.name = 'Aaron'
修改人物;类似于content['a']['v'] = 3
修改内部字典的方式。相当于你的第二个片段如下:
a = 'Andy'
b = 'Belle'
k1_a = a
a = 'Aaron'
print(k1_a) # output: Andy
这一次,没有任何对象被修改。我们正在做的就是覆盖a
变量的值,确切地说content['a'] = 3
覆盖了你的dict中a
键的值。
如果您不希望内部词组中的更改反映在其他词组中,则必须使用copy.deepcopy
复制它们:
import copy
content = {'a': {'v': 1}, 'b': {'v': 2}}
d1 = {'k1': {}}
d2 = {'k2': {}}
d1['k1'].update(copy.deepcopy(content))
print(d1)
content['a']['v'] = 3
content['b']['v'] = 4
d2['k2'].update(copy.deepcopy(content))
print(d2)
print(d1)
# output:
# {'k1': {'a': {'v': 1}, 'b': {'v': 2}}}
# {'k2': {'a': {'v': 3}, 'b': {'v': 4}}}
# {'k1': {'a': {'v': 1}, 'b': {'v': 2}}}
答案 2 :(得分:0)
如果我们用简单的作业替换update()
:
# d1['k1'].update(content)
d1['k1'] = content
我们得到:
{'k1': {'a': 1, 'b': 2}}
{'k2': {'a': 3, 'b': 4}}
{'k1': {'a': 3, 'b': 4}}
(这与您的示例中的update
不同。)这是因为update
接受可迭代(例如字典)并复制内的键值对 。这相当于:
d1['k1'] = {k: v for k, v in content.items()}
当然,int
值是不可变的,因此它们的重新分配不会影响原始值。