簡體   English   中英

如何正確更新 python 中列表中的嵌套字典值?

[英]How do I correctly update nested dictionary values from a list in python?

請告訴我我做錯了什么!

我希望從列表中更新字典中的條目。 這是我的(簡化的)字典和列表:

scene_dict = {0: {'speaker': None, 'listener': None}, 1: {'speaker': None, 'listener': None}}
speaker_list = ["Horatio", "Marcellus"]

我想達到以下結果:

scene_dict = {0: {'speaker': "Horatio", 'listener': None}, 1: {'speaker': "Marcellus", 'listener': None}}

這似乎是一個直截了當的問題。

為了獲得所需的結果,我執行以下操作:

for i, j in enumerate(scene_dict):
    scene_dict[j]["speaker"] = speaker_list[i]

然后給出我想要的結果,是的!

print(scene_dict)

{0: {'speaker': 'Horatio', 'listener': None}, 1: {'speaker': 'Marcellus', 'listener': None}}

那么,“問題出在哪里?” 你可能會問。 好吧,實際上,我正在處理的名單要長得多。 因此,我的字典需要相應地更長,但它具有完全相同的形式。 自然地,我不想通過明確地寫下來來定義我的字典。 我需要以某種方式生成它,我這樣做如下:

para_dict = {"speaker": None, "listener": None}
scene_dict = {}

for k in range(0,2):
    scene_dict[k] = para_dict 

這個“似乎”工作正常,並且“似乎”給出了與我開始時完全相同的字典:

print(scene_dict)

{0: {'speaker': None, 'listener': None}, 1: {'speaker': None, 'listener': None}}

但是,當我現在在我的(“完全相同”)生成的字典上重新運行上面完全相同的 for 循環時,為了將我的列表的元素傳輸到字典中的值

for i, j in enumerate(scene_dict):
    scene_dict[j]["speaker"] = speaker_list[i]

我得到一個不同的(錯誤的)結果:

print(scene_dict)

{0: {'speaker': 'Marcellus', 'listener': None}, 1: {'speaker': 'Marcellus', 'listener': None}}

這次 for 循環顯然同時將兩個字典鍵(“speaker”)等同於列表中的第一個名字,然后將兩個鍵與列表中的第二個名字等同,即它與 Horatio 等同,然后與 Marcellus 等同.

我很困惑。 我做錯什么了? 我怎樣才能做得更好?

任何意見,將不勝感激。

啊你被 python objects are all references trick 騙了!

對於每個 object、 dictarrayObject等的上下文。 綁定到變量作為存儲在 memory 中的實際 object 的引用或指針。當你做類似的事情時

obj = {"Hello" : "I'm an object"}
obj2 = obj

您沒有制作obj的副本並將其存儲在obj2中。 obj2只是再次引用obj 如果您使用id function打印objobj2的 memory 地址,您將獲得相同的地址

現在以你的例子為例,當你這樣做時

para_dict = {"speaker": None, "listener": None}
scene_dict = {}

for k in range(0,2):
    scene_dict[k] = para_dict

您將對scene_dict的相同引用分配給para_dict中的每個條目。 那是,

{
   0 : {"speaker" : None, "listener" : None},
   1 : {"speaker" : None, "listener" : None}
}

實際上是

{
   0 : para_dict, # These are actually the same object!
   1 : para_dict
}

所以當你修改你的scene_dict時,

for i, j in enumerate(scene_dict):
    scene_dict[j]["speaker"] = speaker_list[i]

您修改已分配的para_dict的每個實例。 所以通過循環你會得到。

start    | {0: {'speaker': None, 'listener': None}, 1: {'speaker': None, 'listener': None}}
1st iter | {0: {'speaker': 'Horatio', 'listener': None}, 1: {'speaker': 'Horatio', 'listener': None}}
2nd iter | {0: {'speaker': 'Marcellus', 'listener': None}, 1: {'speaker': 'Marcellus', 'listener': None}}

現在修復非常簡單,而不是分配para_dict只是每次都制作字典。

scene_dict = {}

for k in range(0,2):
    scene_dict[k] = {"speaker": None, "listener": None}

這將在循環的每次迭代中創建一個新字典,而不是對已創建字典的引用。 如果您的para_dict變得復雜,您可以查看copy function

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM