【问题标题】:How to unpickle a Python instance that was saved before the class changed a member variable to a property?如何取消在类将成员变量更改为属性之前保存的 Python 实例?
【发布时间】:2021-06-01 10:59:32
【问题描述】:

我有一个类,以前有一个字段 data,但后来该类被更改,现在 data 是一个属性。

我希望能够取消在更改之前腌制的实例,以保持向后兼容性。一个用于说明的最小示例(在 Python 2 中,尽管在 Python 3 中应该相同):

import pickle

class X(object):
    def __init__(self):
        self.data = 100

pickle.dump(X(), open("x-file",'w'))

# Redefine the class
class X(object):
    def __init__(self):
        self._data = 101
    @property
    def data(self):
        return self._data

y = pickle.load(open("x-file")) # cannot access the original data through y
print(y.data)

我想要定义一个函数load 来解开对象,检测它是旧样式(例如,通过看到它没有_data 字段),并返回一个带有它的新样式实例数据代替。但是,由于字段 data 现在是一个属性,旧的 data 字段被类定义覆盖。

有什么简单的方法可以访问旧数据(例如,除了自己解析 pickle 文件之外)?

编辑 在彼得伍德的回答之后,我得到了这个解决方案:

import pickle

class X(object):
    def __init__(self):
        self.data = 100

pickle.dump(X(), open("x-file",'w'))

# Redefine the class
class X(object):
    def __init__(self):
        self._data = 101
    @property
    def data(self):
        return self._data
    def __setstate__(self, state):
        if not '_data' in state:
            self._data = state['data']
            del state['data']
        self.__dict__.update(state)

y = pickle.load(open("x-file")) # cannot access the original data through y
print(y.data)

【问题讨论】:

标签: python serialization pickle


【解决方案1】:

documentationWhat can be pickled and unpickled? 中说:

如果您计划拥有可以看到多个版本的长寿命对象 一个类,可能值得在对象中放置一个版本号 以便班级的__setstate__() 可以进行适当的转换 方法。

这是您可以在类中定义的四种“神奇”方法之一,以促进序列化。见Pickling Class Instances

【讨论】:

  • 太棒了,这正是我想要的正是。我使用__setstate__() 在解决方案中进行了编辑。
  • @doetoe 太好了,感谢您的反馈。
猜你喜欢
  • 1970-01-01
  • 2018-02-20
  • 2017-04-24
  • 2011-05-13
  • 1970-01-01
  • 1970-01-01
  • 2019-12-09
  • 2023-03-27
相关资源
最近更新 更多