如何pickle继承自A的类B(具有许多变量)的对象,该对象定义了 __setstate__ 和 __getstate__

use*_*686 5 python inheritance pickle

我的问题是:

class A(object):
    def __init__(self):
        #init
    def __setstate__(self,state):
        #A __setstate__ code here            
    def __getstate__(self):
        #A __getstate__ code here
        return state

class B(A):
    def __init__(self):
        #creates many object variables here
Run Code Online (Sandbox Code Playgroud)

A 来自外部库。

硬解

我想避免这种情况

当 pickle B 时,pickle 当然使用 A 类的__setstate__方法__getstate__,所以为了让 pickle 工作,我应该这样做:

class B(A):
    def __init__(self):
        #creates many object variables here

    def __setstate__(self,state)
        A.__setstate__(self,state)
        #B __setstate__ code here
        #getting various variables from state for example
        self._a0 = state['a0']
        self._a1 = state['a1']
        #...
        self._a100 = state['a100']
        self._a101 = state['a101']

    def __getstate__(self):
        state = A.__getstate__(self)
        #B __setstate__ code here
        #filling state with various variables  
        #getting various variables from state for example
        state['a0'] =  self._a0
        state['a1'] =  self._a1
        #...
        state['a100'] =  self._a100
        state['a101'] =  self._a101           
        return state
Run Code Online (Sandbox Code Playgroud)

我的问题是:

如何避免在 B 中定义__setstate__and ,__getstate__以便 pickle 自行完成酸洗变量的工作?B 中的所有变量都是 pickle 可以自行 pickle(处理)的类型。所以如果B不继承A,也有可能得到好的结果:

b = B()
path = 'path.temp'
fout = open(path,'w')
pickler = pickl.Pickler(fout)

pickler.dump(b)
fout.close()

fin = open(path,'r')
upickler = pickl.Unpickler(fin)
b = unpickler.load()
fin.close()
#b has all variables
Run Code Online (Sandbox Code Playgroud)

显而易见的解决方案

class B(object):
    def __init__(self):
        #creates many object variables here
        a = A()            
Run Code Online (Sandbox Code Playgroud)

但是我希望 B 继承自 A。知道如何解决这个问题,或者至少自动化 B 中的酸洗/反酸洗变量吗?

解决办法:

至于硬解中的自动化酸洗

将保存要 pickle 的变量的字典添加到 B 中:

class B(A):
    __picklableObjects__ = {'_a0', '_a1', ... ,'_a101'}

    def __init__(self):
        #creates many object variables here
        A.__init__(self)
        self._a0 = ...
        ...
        self._a101 = ...

    @staticmethod
    def getPicklableObjects():
        return B.__picklableObjects__

    def __setstate__(self,state):
        A.__setstate__(self,state)
        for po in B.getPicklableObjects():
           __dict__[po] = state[po]

    def __getstate__(self):
        state = A.__getstate__(self)
        for po in B.getPicklableObjects():
            state[po] = copy.deepcopy(__dict__[po])
        return state
Run Code Online (Sandbox Code Playgroud)

还有其他想法吗?

A的图书馆:

好的,对于任何感兴趣的人来说,A 是 graph_tool.Graph: src 代码

line 786: class Graph(object)

...

line 1517: __getstate__

...

line 1533: __setstate__
Run Code Online (Sandbox Code Playgroud)

jco*_*ado 4

根据文档,当__getstate__未定义时,实例的__dict__会被腌制,因此也许您可以使用它来定义自己的状态方法作为方法A和实例的组合__dict__

import pickle

class A(object):
    def __init__(self):
        self.a = 'A state'

    def __getstate__(self):
        return {'a': self.a}

    def __setstate__(self, state):
        self.a = state['a']

class B(A):
    def __init__(self):
        A.__init__(self)
        self.b = 'B state'

    def __getstate__(self):
        a_state = A.__getstate__(self)
        b_state = self.__dict__
        return (a_state, b_state)

    def __setstate__(self, state):
        a_state, b_state = state
        self.__dict__ = b_state
        A.__setstate__(self, a_state)

b = pickle.loads(pickle.dumps(B()))
print b.a
print b.b
Run Code Online (Sandbox Code Playgroud)