【问题标题】:Is python dict.copy() not working properly? [duplicate]python dict.copy() 不能正常工作吗? [复制]
【发布时间】:2021-04-17 06:44:13
【问题描述】:

我正在制作配置程序来帮助用户配置.json 文件。该程序的功能之一是检查保存的json 是否与用户创建的新json 文件相同。如果两个.json不相同,它会告诉用户保存程序中正在配置的.json文件。

我的第一个想法是每次检查两个.json 文件是否相同时都从.json 文件中读取。它看起来像这样:

# read from the saved json file
new_settings = {"key1": 1, "key2": 2, "array1": []} # json.load(open('config.json', 'r').read())
# modifying new_settings
new_settings['array1'].append('Data')

def checkIsDifferent():
    # read from the saved json file
    saved_settings = {"key1": 1, "key2": 2, "array1": []} # json.load(open('config.json', 'r').read())
    if saved_settings == new_settings:
        print('Configuration is saved')
    else:
        print('(*)Configuration is not saved')

我不认为经常从文件中读取将是比较“设置”的好方法,所以我想出了另一种方法,将保存的 .json 复制到一个变量中,然后使用要比较的变量:

saved_settings = {"key1": 1, "key2": 2, "array1": []} # read from the saved json file
new_settings = saved_settings.copy()

# modify
new_settings['array1'].append('Data')

def checkIsDifferent():
    if saved_settings == new_settings:
        print('Configuration is saved')
    else:
        print('(*)Configuration is not saved')

第一个解决方案符合预期。运行checkIsDifferent()函数时输出“(*)配置未保存”。但是当我在第二个解决方案上运行checkIsDifferent() 时,它会输出“配置已保存”。

python 中的dict.copy() 坏了吗?对于第二种解决方案,我该如何解决?

系统环境:

Python 版本:Python 3.8.5 (tags/v3.8.5:580fbb0, Jul 20 2020, 15:43:08) [MSC v.1926 32 bit (Intel)]

操作系统:Windows 10

【问题讨论】:

  • dict.copy() 执行“浅”复制:saved_settings['array1']new_settings['array1'] 都是对同一个列表的引用,并且附加会影响两者。请改用copy.deepcopy
  • 很确定你需要做一个深拷贝才能让它们与众不同。指向列表的指针将被复制,但列表将是相同的。
  • 当您调用 copy 时,它将采用“key1”并为 1 分配新内存,因为 1 是不可变的(它是一个整数)。但是当它使用“array1”时,它不会为 [] 分配新内存,因为列表是可变的。
  • @LPR Python 还必须为空列表分配内存。
  • @mkrieger1 是的,您是对的,但是当您以这种方式执行复制时,两个字典中的列表将是相同的。它不会创建新列表。

标签: python json dictionary


【解决方案1】:

copy() 只会复制对任何非原始类型的引用。请改用 deepcopy。

from copy import deepcopy

saved_settings = {"key1": 1, "key2": 2, "array1": []} # read from the saved json file
new_settings = deepcopy(saved_settings)
# modify
new_settings['array1'].append('Data')

def checkIsDifferent():
    if saved_settings == new_settings:
        print('Configuration is saved')
    else:
        print('(*)Configuration is not saved')

【讨论】:

  • 第一句话是什么意思?列表是对其他对象的引用的集合,无论底层类型如何,副本都会复制这些引用
  • 我认为 copy 也会复制对“原始类型”的引用(我不确定这个概念是否存在于 Python 中)。一切都是对象,列表包含对对象的引用。
  • @IainShelvington 抱歉,措辞不当。是的,它会复制列表,但列表中非原始类型(int、float、chr、str)的所有内容都只会被引用
  • @rabl 根本不是这样,那些“原始”类型的对象也只会被引用
  • @IainShelvington 看看这段代码;我刚刚用 Python3 对其进行了测试,断言失败,这意味着它没有通过引用传递 int 类型:import copy; list = [2, 3]; reference = copy.copy(list); list[1] = 6; assert(reference[1] == list[1];
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-10
  • 2022-11-17
  • 1970-01-01
  • 1970-01-01
  • 2020-08-22
  • 1970-01-01
  • 2020-10-05
相关资源
最近更新 更多