繁体   English   中英

如何取消在 class 将成员变量更改为属性之前保存的 Python 实例?

[英]How to unpickle a Python instance that was saved before the class changed a member variable to a property?

我有一个 class 曾经有一个字段data ,但后来 class 被更改,现在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)

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

有什么简单的方法可以访问旧数据(例如,除了自己解析 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)

文档中说什么可以腌制和解封?

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

这是您可以在类上定义以促进序列化的四种“魔术”方法之一。 请参阅酸洗 Class 实例

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM