簡體   English   中英

Python:在類實例中設置嵌套字典列表的值

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

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