You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

子类化dict从JSON文件初始化值未达预期问题

子类化dict实现自动读取JSON文件的问题解决

问题场景

拥有C/C++开发背景,尝试子类化dict实现自动读取JSON文件的功能,代码如下:

import json

class DictFromJSON(dict):
    def get_from_file(self, filename):
        with open(filename,) as file_reader:
            self = json.load(file_reader)
        print(self)

    def save(self, filename):
        with open(filename, "w") as file_writer:
            json.dump(self, file_writer)

    def __setitem__(self, key, value):
        super().__setitem__(key, value)
        self.save()

    def __init__(self, filename, *args):
        super().__init__(args)
        self.get_from_file(filename)

json_dict = DictFromJSON("myjson.json")
print(json_dict)

测试JSON文件内容为{"mykey": true},运行后输出:

{'mykey': True}
{}

get_from_file内部打印的self符合预期,但外部打印类实例时为空。

问题原因

Python中self是方法的局部变量,在get_from_file里执行self = json.load(file_reader),只是让局部变量self指向了json.load返回的新dict对象,并没有修改原来的DictFromJSON实例本身。原来的实例还是__init__中初始化的空dict,所以外部打印结果为空。

另外两处细节问题:

  1. __init__里的super().__init__(args)错误:args是元组,直接传入会把元组作为单个键值对的键,应该用super().__init__(*args)解包参数。
  2. __setitem__里的self.save()缺少文件名参数,会直接触发调用报错。

修正后的代码

import json

class DictFromJSON(dict):
    def __init__(self, filename, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.filename = filename  # 把文件名保存为实例属性
        self.get_from_file()

    def get_from_file(self):
        with open(self.filename) as file_reader:
            loaded_data = json.load(file_reader)
            self.clear()  # 清空当前实例原有内容
            self.update(loaded_data)  # 将JSON加载的内容更新到当前实例
        print(self)

    def save(self):
        # 直接使用实例保存的文件名,无需重复传入
        with open(self.filename, "w") as file_writer:
            json.dump(self, file_writer)

    def __setitem__(self, key, value):
        super().__setitem__(key, value)
        self.save()

# 测试
json_dict = DictFromJSON("myjson.json")
print(json_dict)
json_dict["new_key"] = "new_value"  # 修改后会自动保存到文件

关键修改说明

  • 避免直接给self赋值,改用self.clear() + self.update()修改当前实例的内容,确保操作的是原对象
  • 在__init__中保存文件名到实例属性,简化后续方法的调用逻辑
  • 修正父类构造方法的参数传递方式,正确解包*args和**kwargs
  • 调整save方法的参数逻辑,直接复用实例保存的文件名

内容的提问来源于stack exchange,提问作者Kiwewi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 13:15:59