[英]Python: setting values of a list of nested dictionaries in class instances
我有一个亟待解决的问题,我只是想不通。 假设您有一个类,该类将嵌套字典的列表作为输入。 它将使用新的空字典初始化每个词典的键之一。 稍后,我想将列表中对象的嵌套值之一设置为某种值。 由于某种原因,这似乎会影响列表中的其他对象?
我知道这听起来很令人费解,所以这里有个例子:
class Tester():
def __init__(self, stuff):
# stuff is a list of dictionaries
self.stuff = stuff
# Each item in the list should be initialized to this dictionary
inside_init_dict = {'test': True}
for x in self.stuff:
x['info'] = inside_init_dict
if __name__ == '__main__':
new_stuff = [{'info': {}}, {'info': {}}, {'info': {}}]
mytest = Tester(new_stuff)
print(mytest.stuff)
# >>> [{'info': {'test': True}}, {'info': {'test': True}}, {'info': {'test': True}}]
# I want to just set a value in the nested dict of the first item in the list
mytest.stuff[0]['info']['test'] = False
# However, all items in the list change
print(mytest.stuff)
# >>> [{'info': {'test': False}}, {'info': {'test': False}}, {'info': {'test': False}}]
这在Python 2和Python 3上都发生。我可以解决的唯一方法是不使用单独的变量“ inside_init_dict”,而直接设置初始化的字典:
class Tester():
def __init__(self, stuff):
# stuff is a list of dictionaries
self.stuff = stuff
# Each item in the list should be initialized to this dictionary
for x in self.stuff:
x['info'] = {'test': True}
if __name__ == '__main__':
new_stuff = [{'info': {}}, {'info': {}}, {'info': {}}]
mytest = Tester(new_stuff)
print(mytest.stuff)
# >>> [{'info': {'test': True}}, {'info': {'test': True}}, {'info': {'test': True}}]
mytest.stuff[0]['info']['test'] = False
# This is what I want
print(mytest.stuff)
# >>> [{'info': {'test': False}}, {'info': {'test': True}}, {'info': {'test': True}}]
这里发生了什么? 我尝试在各种地方设置变量“ inside_init_dict”,例如作为类变量或在类外部。 问题仍然存在。
在第一个示例中,您在循环外部创建了一个字典inside_init_dict
,并将其放在多个位置。 列表中的每个元素都具有相同的inside_init_dict
。 您所看到的并不是列表中的其他对象受到影响,只有一个对象被多次显示。
在第二个示例中:
for x in self.stuff:
x['info'] = {'test': True}
现在,每个x
都有自己的字典。 一开始它们都具有相同的值,但是它们是不同的实例,就像同卵双胞胎一样。
发生这种情况是因为dicts
是易变的 ,这意味着您可以更改其内容而无需更改其标识。 这是您看到的行为的一个简单得多的示例:
my_dict = { "key" : "value" }
my_list = [ my_dict, my_dict ]
my_list[0]["key"] = "new_value"
print(my_list) # [ {"key" : "new_value"}, {"key": "new_value"} ]
为什么会这样:
在此代码的第一行中,我创建了一个新字典{"key" : "value"}
,并为其分配名称my_dict
。
在第二行中,我创建一个列表,其第零个元素和第一个元素都指向my_dict
。
在第三行中,我访问my_dict
(通过my_list[0]
),并对它进行突变 :更改与"key"
关联的值。
在第四行中,我检查my_list
的值。 my_list
的第零个元素和第一个元素都仍指向my_dict
并且我们更改了my_dict
。 因此,更改将反映在列表的两个元素中。
解决它的一种方法:
而不是两次指向同一个字典,而是创建两个具有相同值的字典:
my_list = [ { "key" : "value" } , { "key" : "value" } ]
my_list[0]["key"] = "new_value"
print(my_list) # [ {"key" : "new_value"}, {"key": "value"} ]
将密钥分配给inside_init_dict
词典的不同副本,而不是相同的副本:
...
inside_init_dict = {'test': True}
for x in self.stuff:
x['info'] = inside_init_dict.copy()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.