Как выбрать объект класса B (имеющий много переменных), который наследуется от A, который определяет __setstate__ и __getstate__
Моя проблема:
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
А из внешней библиотеки.
Трудное решение
Этого я бы хотел избежать
При мариновании Б, маринование, конечно, использует класс А __setstate__
, __getstate__
методы, поэтому для того, чтобы засолка работала, я должен сделать что-то вроде этого:
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
Мой вопрос:
Как я могу избежать определения __setstate__
а также __getstate__
в B, так что pickle выполняет работу по травлению переменных самостоятельно? Все переменные в B относятся к типу, который 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
Очевидное решение
class B(object):
def __init__(self):
#creates many object variables here
a = A()
Однако я хотел бы, чтобы B наследовал от A. Есть идеи, как решить эту проблему или хотя бы автоматизировать переменные травления / расщепления в B?
Обходное решение:
Что касается автоматизации травления в Hard Solution
Добавьте в B словарь, содержащий переменные для 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
Есть другие идеи?
Библиотека А:
Итак, для любого из вас, кто интересуется, A это graph_tool.Graph: код src
line 786: class Graph(object)
...
line 1517: __getstate__
...
line 1533: __setstate__
2 ответа
Согласно документации, когда __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
Поведение Pickle по умолчанию: __getstate__
не определено, чтобы травить содержимое объектов __dict__
Атрибут - это место, где хранятся атрибуты экземпляра.
Поэтому, похоже, в вашем случае все, что вам нужно сделать, это сделать A
получить и установить состояние, чтобы сохранить значения, найденные в self.__dict__
и восстановить затем в __setstate__
- это должно сохранить также переменные экземпляров всех экземпляров подклассов A.