问题
My problem is:
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
A is from an external library.
Hard solution
This I would like to avoid
When pickling B, pickle of course uses class A's __setstate__, __getstate__ methods, so in order for pickle to work I should do something like this:
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
My question is:
How can I avoid defining __setstate__ and __getstate__ in B so that pickle does the job of pickling variables by itself?
All variables in B are of type that pickle may pickle(handle) by itself.
So if B didn't inherit from A, it would be possible with good results:
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
The obvious solution
class B(object):
def __init__(self):
#creates many object variables here
a = A()
However I would like B to inherit from A. Any idea how to solve this or at least automate pickling/unpickling variables in B?
The workaround solution:
As for automating pickling in the Hard Solution
Add to B a dictionary holding variables to pickle:
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
Any other ideas?
A's library:
Ok so for any of you interested A is graph_tool.Graph: A src code
line 786: class Graph(object)
...
line 1517: __getstate__
...
line 1533: __setstate__
回答1:
According to the documentation, when __getstate__ isn't defined, the instance's __dict__ is pickled so maybe, you can use this to define your own state methods as a combination of the A methods and the instance's __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
回答2:
The default behavior of Pickle is __getstate__ is not defined is to pickle the contents of the objects __dict__ attribute - that is where the instance attributes are stored.
Therefore it looks like in your case, all you need to do is to make A's get and set state to preserve the values found in self.__dict__ and restore then at __setstate__ - this should preserve the instance variables of all instances of subclasses of A as well.
来源:https://stackoverflow.com/questions/8574742/how-to-pickle-an-object-of-a-class-b-having-many-variables-that-inherits-from