如何同时序列化类变量和实例变量?
在pickle的文档中提到,“当我们把一个类的实例进行序列化时,它所属类的数据不会被一起序列化,只有实例的数据会被序列化。”有没有人能分享一下如何在序列化和反序列化时,把类变量和实例变量都包含进去的方法呢?
3 个回答
0
这里有一个只使用标准库模块的解决方案。只需执行下面的代码块,从那时起,pickle就会按照你想要的方式工作。正如Mike McKerns所说,dill
在背后做了类似的事情。
相关讨论可以在这里找到。
import copy_reg
def _pickle_method(method):
func_name = method.im_func.__name__
obj = method.im_self
cls = method.im_class
return _unpickle_method, (func_name, obj, cls)
def _unpickle_method(func_name, obj, cls):
for cls in cls.mro():
try:
func = cls.__dict__[func_name]
except KeyError:
pass
else:
break
return func.__get__(obj, cls)
copy_reg.pickle(types.MethodType, _pickle_method, _unpickle_method)
2
你可以通过使用标准库中的函数,轻松实现这个功能,具体方法是使用 __getstate__
和 __setstate__
:
class A(object):
y = 1
x = 0
def __getstate__(self):
ret = self.__dict__.copy()
ret['cls_x'] = A.x
ret['cls_y'] = A.y
return ret
def __setstate__(self, state):
A.x = state.pop('cls_x')
A.y = state.pop('cls_y')
self.__dict__.update(state)
8
用 dill
替代 pickle
,然后按照你之前的方式编写代码就可以了。
>>> class A(object):
... y = 1
... x = 0
... def __call__(self, x):
... self.x = x
... return self.x + self.y
...
>>> b = A()
>>> b.y = 4
>>> b(2)
6
>>> b.z = 5
>>> import dill
>>> _b = dill.dumps(b)
>>> b_ = dill.loads(_b)
>>>
>>> b_.z
5
>>> b_.x
2
>>> b_.y
4
>>>
>>> A.y = 100
>>> c = A()
>>> _c = dill.dumps(c)
>>> c_ = dill.loads(_c)
>>> c_.y
100