[英]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.