如何取消 Python 在 class 将成员变量更改为 属性 之前保存的实例?
How to unpickle a Python instance that was saved before the class changed a member variable to a property?
我有一个 class,它曾经有一个字段 data
,但后来 class 被更改了,现在 data
是一个 属性。
我希望能够取消在更改之前被 pickle 的实例,以保持向后兼容性。一个最小的说明示例(在 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
字段),以及 return 一个带有数据的新样式实例。但是,由于字段 data
现在是 属性,旧的 data
字段被 class 定义覆盖。
有没有什么简单的方法可以访问旧数据(例如,除了自己解析泡菜文件)?
编辑
在 Peter Wood 的回答之后,我找到了这个解决方案:
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)
documentation says in What can be pickled and unpickled?:
If you plan to have long-lived objects that will see many versions of
a class, it may be worthwhile to put a version number in the objects
so that suitable conversions can be made by the class’s __setstate__()
method.
这是您可以在 类 上定义以促进序列化的四种“神奇”方法之一。参见 Pickling Class Instances。
我有一个 class,它曾经有一个字段 data
,但后来 class 被更改了,现在 data
是一个 属性。
我希望能够取消在更改之前被 pickle 的实例,以保持向后兼容性。一个最小的说明示例(在 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
字段),以及 return 一个带有数据的新样式实例。但是,由于字段 data
现在是 属性,旧的 data
字段被 class 定义覆盖。
有没有什么简单的方法可以访问旧数据(例如,除了自己解析泡菜文件)?
编辑 在 Peter Wood 的回答之后,我找到了这个解决方案:
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)
documentation says in What can be pickled and unpickled?:
If you plan to have long-lived objects that will see many versions of a class, it may be worthwhile to put a version number in the objects so that suitable conversions can be made by the class’s
__setstate__()
method.
这是您可以在 类 上定义以促进序列化的四种“神奇”方法之一。参见 Pickling Class Instances。