在动态创建带有引用字典的字典时,为什么引用字典会被修改? (蟒蛇)

时间:2012-08-21 10:44:54

标签: python dictionary

我正在编写一个动态创建字典的Python代码,将其初始化为引用字典,并修改字典中的特定值。但是,我发现不仅我得到了意想不到的结果,而且参考字典也被修改了。 我的代码:

tdict={'a':'1','b':'2','c':'3'}
newdict={}
for i in range(5):
  newdict['name'+str(i)]=tdict
  newdict['name'+str(i)]['a']='value'+str(i)
  print 'tdict:  ',tdict
print 'newdict:  ',newdict

结果:

tdict:   {'a': 'value0', 'c': '3', 'b': '2'}
tdict:   {'a': 'value1', 'c': '3', 'b': '2'}
tdict:   {'a': 'value2', 'c': '3', 'b': '2'}
tdict:   {'a': 'value3', 'c': '3', 'b': '2'}
tdict:   {'a': 'value4', 'c': '3', 'b': '2'}
newdict:   {'name4': {'a': 'value4', 'c': '3', 'b': '2'}, 'name2': {'a': 'value4', 'c': '3', 'b': '2'}, 'name3': {'a': 'value4', 'c': '3', 'b': '2'}, 'name0': {'a': 'value4', 'c': '3', 'b': '2'}, 'name1': {'a': 'value4', 'c': '3', 'b': '2'}}

而我期待我的'新命'就像:

newdict:   {'name4': {'a': 'value4', 'c': '3', 'b': '2'}, 'name2': {'a': 'value2', 'c': '3', 'b': '2'}, 'name3': {'a': 'value3', 'c': '3', 'b': '2'}, 'name0': {'a': 'value0', 'c': '3', 'b': '2'}, 'name1': {'a': 'value1', 'c': '3', 'b': '2'}}

任何人都可以帮我弄清楚为什么会这样吗?另外,为什么当我没有给它分配任何值时,参考字典'tdict'会被改变?

提前致谢

2 个答案:

答案 0 :(得分:2)

您正在tdict词典的每个值中存储newdict的引用:

newdict['name'+str(i)]=tdict

然后您通过执行

修改'a'的密钥tdict
# newdict['name'+str(i)] is a reference to tdict
newdict['name'+str(i)]['a']='value'+str(i)
# this is equivalent to doing
tdict['a']='value'+str(i)

您可能想要的是在新词典词典中存储tdict的副本:

newdict['name'+str(i)]=dict(tdict)

使用现有字典作为构造函数参数创建新字典会创建一个浅表副本,您可以在其中为现有键分配新值。你不能(或你不想要的)是修改这个字典中的可变值。例如:

>>> a={'a': 1, 'b': 2, 'c': [1,2,3]}
>>> b=dict(a)
>>> b['a']=9
>>> a
{'a': 1, 'c': [1, 2, 3], 'b': 2}
>>> b
{'a': 9, 'c': [1, 2, 3], 'b': 2}
>>> b['c'].append(99)
>>> a
{'a': 1, 'c': [1, 2, 3, 99], 'b': 2}
>>> b
{'a': 9, 'c': [1, 2, 3, 99], 'b': 2}

如果要修改字典中的可变值,则需要创建深层副本:

>>> import copy
>>> a={'a': 1, 'b': 2, 'c': [1,2,3]}
>>> b=copy.deepcopy(a)
>>> b['a']=9
>>> b['c'].append(99)
>>> a
{'a': 1, 'c': [1, 2, 3], 'b': 2}
>>> b
{'a': 9, 'c': [1, 2, 3, 99], 'b': 2}

答案 1 :(得分:0)

只是因为你正在引用tdict而不是副本。要复制,您可以使用

newdict['name'+str(i)] = tdict.copy()

newdict['name'+str(i)] = dict(tdict)

希望有所帮助