【问题标题】:Lists unintentionally change simultaneously列表无意同时更改
【发布时间】:2020-07-02 15:31:19
【问题描述】:

我的 Python 库的 functionfile_contents 获取预定义的字典列表(file_contents 来自 *.json 文件,该文件的路径在 self.full_path 中指定)并更改这些字典。

事情是这样的:

  1. changed_list_dictionaries 作为start_list_dictionaries 的副本。
  2. 然后将changed_list_dictionaries 更改为所需的值。
  3. file_contents 中删除start_list_dictionaries 中的所有字典。
  4. 使用changed_list_dictionaries 中的字典扩展file_contents

我遇到了问题:列表start_list_dictionarieschanged_list_dictionaries 同时更改,但不应该。我该如何解决这个问题?

提前致谢!

def change_several_books(self, start_list_dictionaries):
        changed_list_dictionaries = start_list_dictionaries.copy()
        shortest_dict = min(changed_list_dictionaries, key=len)
        dict_for_change = shortest_dict.copy()
        for key, value in dict_for_change.items():
            if isinstance(value, dict):
                for desc, type_value in value.items():
                    new_value = input(f"--------<{desc}>: ")
                    if new_value in ["del", "<del>"]:
                        dict_for_change[key] = "<del>"
                    elif new_value == "":
                        dict_for_change[key] = "<continue>"
                    else:
                        if isinstance(type_value, (str, int, dict)):
                            changed_dictionary[key_in_initial_dict] = {desc: new_value}
                        elif isinstance(type_value, list):
                            try:
                                changed_dictionary[key_in_initial_dict] =\
                                    {desc: json.loads(new_value)}
                            except json.decoder.JSONDecodeError:
                                changed_dictionary[key_in_initial_dict] =\
                                    {desc: [new_value]}
           
 
        for dictionary in changed_list_dictionaries:
            for initial_key in dictionary.copy().keys():
                for key_for_change, value_for_change in dict_for_change.items():
                    if initial_key == key_for_change:
                        if value_for_change == "<continue>":
                            pass
                        elif value_for_change == "<del>":
                            del dictionary[initial_key]
                        elif isinstance(value_for_change, dict):
                            dictionary[initial_key] = value_for_change
 
        with open(self.full_path, 'r') as file:
            file_contents = json.load(file)
 
        file_contents = [
            element
            for element in file_contents
            if element not in start_list_dictionaries
        ]
        file_contents.extend(changed_list_dictionaries)
 
        with open(self.full_path, 'w') as file:
            json.dump(file_contents, file)
 
        print("\nSuccess!")

【问题讨论】:

  • 显示问题中的代码。您几乎可以肯定没有复制您在第 1 点中声称的列表。
  • 嗯,我的第一个建议不正确。问题是您正在制作 shallow 副本而不是 deepcopies
  • 非常感谢 deepcopy 的评论!在导入“复制”库并使用 deepcopy 后,它可以按我的意愿工作。谢谢!请把它写成答案,我会投票并标记为正确

标签: python json list function oop


【解决方案1】:

使用start_list_dictionaries.copy() 会返回列表的浅表副本 (documentation on data structures),但您需要 副本。当您复制的对象是集合的集合时,浅拷贝和深拷贝的区别很重要。 (Docs for shallow and deep copying) 在你的情况下,你有一个 listdict objs。 start_list_dictionaries 的浅表副本将为 相同的旧 dicts 创建一个新 references 的新列表。但是您想要的是这些字典的新副本 列表。这就是浅拷贝和深拷贝的基本区别。

在许多使用内置类型(如listdict)的情况下,可以像这样获得深拷贝:

from copy import deepcopy

obj_dc = deepcopy(obj)

【讨论】:

    猜你喜欢
    • 2015-09-01
    • 2014-01-18
    • 2022-07-06
    • 1970-01-01
    • 2023-03-28
    • 2018-10-16
    • 2015-06-29
    相关资源
    最近更新 更多