Python字典不知怎么在更新
我尽了最大的努力想弄明白,但我一辈子也弄不明白。我有一本字典,里面有很多不同的值,包括另一本字典。在为字典中的字典设置值之前,我尝试将这些值设置为“空白”字典,以便在后续步骤中更新它 简短的故事是:我有两句话不知怎么地改变了一本我意想不到的词典。鉴于一些格言:Python字典不知怎么在更新,python,python-3.x,dictionary,Python,Python 3.x,Dictionary,我尽了最大的努力想弄明白,但我一辈子也弄不明白。我有一本字典,里面有很多不同的值,包括另一本字典。在为字典中的字典设置值之前,我尝试将这些值设置为“空白”字典,以便在后续步骤中更新它 简短的故事是:我有两句话不知怎么地改变了一本我意想不到的词典。鉴于一些格言: blankresiduedict={stuff:[stuff],stuff:[stuff]};blankidentifiers={stuff:stuff,stuff:stuff} 台词 self.pdb_chain_dict['1MH9_
blankresiduedict={stuff:[stuff],stuff:[stuff]};blankidentifiers={stuff:stuff,stuff:stuff}
台词
self.pdb_chain_dict['1MH9_B'] = (blankresiduedict.copy(),blankidentifiers.copy())
self.pdb_chain_dict['1MH9_B'][0][(stuff)][0] = residuedict[('A','D','41')]
正在以某种方式将blankresiduedict的值更改为等于residuedict
知道这是怎么发生的吗?在这段代码中,实际上没有其他对blankresiduedict的引用,当我查看输出时,blankresiduedict开始时是精确的,然后随着每个循环不断地改变值,使之等于该循环的剩余dict。
(以下是更详细的说明) 这是一个非常大的项目的一小部分,因此其中一些可能很难以紧凑的形式表示。我会尽力消除不必要的东西。这是一个类中的方法,我正试图使用它来更新类实例的字典
blankresiduedict = {}
blankidentifiers = {}
self.allowmultiples = True
self.ancestorline = [
'1MH9',
'A', 'D', '41',
'A', 'D', '43',
'A', 'T', '130',
#etc...
]
self.no_key_residues = 6
self.pdb_chain_dict = {
'1MH9_B': (
{
('A','D','41'): [('B','D','41')],
('A','D','43'): [('B','D','43')],
('A','T','130'): [('B','T','130')]
},
#{identifiers dictionary}
),
'1MH9_C': (
#{etc},{etc}
),
# etc...
}
for i in range(1, (3*self.no_key_residues)+1, 3): # Using this loop structure allows a variable number of key residues to be given
if not self.allowmultiples:
raise Exception("Do some stuff here")
else:
blankresiduedict[(self.ancestorline[i],self.ancestorline[i+1],self.ancestorline[i+2])] = [('-','-','-')]
blankidentifiers = {'EC Num':'-','Sprot':'-','Class':'-','Keywords':'-','Title':'-','SeqRepr':'-'}
### Begin some loop structure, where for every loop, the following is basically happening
residuedict = {
('A','D','41'): ('B','D','10'),
('A','D','43'): ('B','D','12')
} #in actuality this value would change for every loop, but just showing what a typical loop would look like
self.pdb_chain_dict['1MH9_B'] = (blankresiduedict.copy(),blankidentifiers.copy())
self.pdb_chain_dict['1MH9_B'][0][('A','D','41')][0] = residuedict[('A','D','41')]
这里应该发生的是,pdb_chain_dict中的值被设置为两个空白字典({residuedict},{identifiers})的元组。在本例中,我基本上不使用标识符字典,因为它有完全相同的问题。然而,我发现blankresiduedict实际上正在改变。而且,在做了大量测试之后,它正在改变的行是self.pdb_chain_dict['1MH9_B'][0][('a,'D','41')][0]=residuedict[('a','D','41')]
这对我来说毫无意义……BlankResistueDict甚至没有涉及,但不知何故,它的值在该步骤中发生了变化。这是因为字典的副本不是深度副本,而您的dict值是列表,它们是可变的。下面是一个再现您的问题的最小示例:
d1 = {"foo": [1, 2, 3]}
d2 = d1.copy()
# Add a new element to d2 to show that the copy worked
d2["bar"] = []
# The two dicts are different.
print d1
print d2
# However, the list wasn't copied
# it's the same object that shows up in 2 different dicts
print d1["foo"] is d2["foo"]
# So that's what happens in your code: you're mutating the list.
d1["foo"].append(5)
print d2["foo"]
这是因为字典的副本不是深度副本,而dict值是列表,它们是可变的。下面是一个再现您的问题的最小示例:
d1 = {"foo": [1, 2, 3]}
d2 = d1.copy()
# Add a new element to d2 to show that the copy worked
d2["bar"] = []
# The two dicts are different.
print d1
print d2
# However, the list wasn't copied
# it's the same object that shows up in 2 different dicts
print d1["foo"] is d2["foo"]
# So that's what happens in your code: you're mutating the list.
d1["foo"].append(5)
print d2["foo"]
这是因为字典的副本不是深度副本,而dict值是列表,它们是可变的。下面是一个再现您的问题的最小示例:
d1 = {"foo": [1, 2, 3]}
d2 = d1.copy()
# Add a new element to d2 to show that the copy worked
d2["bar"] = []
# The two dicts are different.
print d1
print d2
# However, the list wasn't copied
# it's the same object that shows up in 2 different dicts
print d1["foo"] is d2["foo"]
# So that's what happens in your code: you're mutating the list.
d1["foo"].append(5)
print d2["foo"]
这是因为字典的副本不是深度副本,而dict值是列表,它们是可变的。下面是一个再现您的问题的最小示例:
d1 = {"foo": [1, 2, 3]}
d2 = d1.copy()
# Add a new element to d2 to show that the copy worked
d2["bar"] = []
# The two dicts are different.
print d1
print d2
# However, the list wasn't copied
# it's the same object that shows up in 2 different dicts
print d1["foo"] is d2["foo"]
# So that's what happens in your code: you're mutating the list.
d1["foo"].append(5)
print d2["foo"]
哦,哇,我没意识到。这很好地说明了副本是如何不“深入”的,但如何在保留列表的同时生成一份真实副本?我刚刚尝试过的一种方法是“为每个循环重新创建”空白字典,这样它们就可以有效地不被重写。然而,这并不是一种非常“Pythonic”的处理方式。问题不在于dict本身,而是它包含的列表。我建议重新创建列表,而不是对其进行变异,例如在我的示例中,
d2[“foo”]=[1,2,3,5]
,或者在您的示例中重建self.pdb_chain_dict['1MH9_B'][0][('A,'d','41')]
。或者,deepcopy
模块将,顾名思义,制作深度拷贝,但我发现它的使用令人反感。我会使用copy.deepcopy
(或者一种所有东西都是可变的语言)。@sweeneyrod:注意,在这种情况下,可变性是问题的首要原因;)@MaxNoel是的,我是说不可变的!哦,哇,我没意识到。这很好地说明了副本是如何不“深入”的,但如何在保留列表的同时生成一份真实副本?我刚刚尝试过的一种方法是“为每个循环重新创建”空白字典,这样它们就可以有效地不被重写。然而,这并不是一种非常“Pythonic”的处理方式。问题不在于dict本身,而是它包含的列表。我建议重新创建列表,而不是对其进行变异,例如在我的示例中,d2[“foo”]=[1,2,3,5]
,或者在您的示例中重建self.pdb_chain_dict['1MH9_B'][0][('A,'d','41')]
。或者,deepcopy
模块将,顾名思义,制作深度拷贝,但我发现它的使用令人反感。我会使用copy.deepcopy
(或者一种所有东西都是可变的语言)。@sweeneyrod:注意,在这种情况下,可变性是问题的首要原因;)@MaxNoel是的,我是说不可变的!哦,哇,我没意识到。这很好地说明了副本是如何不“深入”的,但如何在保留列表的同时生成一份真实副本?我刚刚尝试过的一种方法是“为每个循环重新创建”空白字典,这样它们就可以有效地不被重写。然而,这并不是一种非常“Pythonic”的处理方式。问题不在于dict本身,而是它包含的列表。我建议重新创建列表,而不是对其进行变异,例如在我的示例中,d2[“foo”]=[1,2,3,5]
,或者在您的示例中重建self.pdb_chain_dict['1MH9_B'][0][('A,'d','41')]
。或者,deepcopy
模块将,顾名思义,制作深度拷贝,但我发现它的使用令人反感。我会使用copy.deepcopy
(或者一种所有东西都是可变的语言)。@sweeneyrod:注意,在这种情况下,可变性是问题的首要原因;)@MaxNoel是的,我是说不可变的!哦,哇,我没意识到。这很好地说明了副本是如何不“深入”的,但如何在保留列表的同时生成一份真实副本?我刚刚尝试过的一种方法是“为每个循环重新创建”空白字典,这样它们就可以有效地不被重写。然而,这并不是一种非常“Pythonic”的处理方式。问题不在于dict本身,而是它包含的列表。我建议重新创建列表,而不是对其进行修改,例如d2[“foo”]