【问题标题】:Restoring old data to modified class [duplicate]将旧数据恢复到修改后的类[重复]
【发布时间】:2021-09-05 23:36:33
【问题描述】:

我有一个用 JSON 序列化的 python 类。

import json

class Data:
    def __init__(self):
        self.ival = 45
        self.fval = 0.5
        self.str = 'A string'
       
    def save(self, filename):
        with open(filename, 'w') as dfile:
            jstr = json.dumps(self.__dict__)
            dfile.write(jstr)
    
    def load(self, filename):
        with open(filename, 'r') as dfile:
            jstr = dfile.read()
            jdict = json.loads(jstr)
            # Save what is currently there
            jsave = self.__dict__
            # Restore the old stuff
            self.__dict__ = jdict
            # Restore the original stuff
            for member in jsave.keys():
                if not member in jdict:
                    self.__dict__[member] = jsave[member]
    
    def scramble(self):
        self.ival = 99
        self.fval = 3.162
        self.str = 'another'

dfilename = './data.json'
dobj = Data()
dobj.save(dfilename)

一段时间后,我为类添加了另一个值

class Data:
    def __init__(self):
        ...
        self.itwo = 2

...
dfilename = './data.json'
dobj = Data()
dobj.load(dfilename)
print(dobj.itwo)

这似乎有效。

问题是,这是恢复字典的最佳方式吗?我希望恢复存在的价值,但保留不存在的价值。除了像我所做的那样一次通过一个键之外,还有更好的方法来合并字典吗?

【问题讨论】:

  • 您在寻找dict.update吗?
  • 是的 - dict.update 正是我正在寻找的。真的应该阅读文档。将代码替换为 self.__dict__.update(jdict) 并且可以正常工作。如果你想写出来作为答案,我会接受。

标签: python


【解决方案1】:

如果你想用文件中的内容破坏内存中的现有值:

self.__dict__.update(jdict)

如果您想另辟蹊径,有几个简单的选择。两者都以

开头
jdict.update(self.__dict__)

然后您可以交换引用

self.__dict__ = jdict

或将值复制回来:

self.__dict__.update(jdict)

【讨论】:

    【解决方案2】:

    这当然不是最好的方法,但要以最小的努力实现这一点,您可以在 dict 上使用 setdefault() 方法。

    self.__dict__[member] = jsave[member]
    

    ->

    self.__dict__.setdefault(member, jsave[member])
    

    关于更好的方法:看看getstate and setstate 或一些高级工具,如PydanticDataclasses

    【讨论】:

      【解决方案3】:

      您可以使用dict.update 或联合|

      def load(self, filename):
          with open(filename, 'r') as dfile:
              jdict = json.load(dfile)
              jsave = self.__dict__
              self.__dict__ = jdict | jsave
      
              # self.__dict__ = jdict
              # self.__dict__.update(jsave)
      

      还有一些注意事项:尽可能使用json.loadjson.dumpfor key in jsave 是有效的,因为您默认迭代键。也请查看setattr

      编辑: 正如 madbird 在 cmets 中指出的那样,如果您使用的是 Python 3.9 之前的版本,您将无法使用联合运算符。 dict.update 在 Python 2 中已经存在,但如果您不想使用临时分配,可以按照 madbird 的建议使用 {**jdict, **jsave}

      【讨论】:

      • Dicts union 在 3.8 iirc 之前的 python 版本中不可用,因此我建议在答案中使用一些较旧的方法,例如 {**a, **b}
      • 好点。我刚查了一下,是introduced in Python 3.9。我应该考虑版本。谢谢。
      • 不幸的是,我正在使用 3.7,但当我迁移到 3.9 时值得考虑。
      猜你喜欢
      • 1970-01-01
      • 2013-06-10
      • 2021-10-27
      • 1970-01-01
      • 2013-09-17
      • 2020-04-29
      • 2014-03-31
      • 2023-04-06
      • 2019-02-15
      相关资源
      最近更新 更多