Как выбрать объект класса B (имеющий много переменных), который наследуется от A, который определяет __setstate__ и __getstate__ - PullRequest
3 голосов
/ 20 декабря 2011

Моя проблема:

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 из внешней библиотеки.

Твердый раствор

Этого я бы хотел избежать

При мариновании Б, маринование, конечно, использует методы класса 101 * *, __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

Есть еще идеи?

Библиотека А:

Хорошо, так что для любого из вас, кто интересуется, это graph_tool.Graph: Код SRC

line 786: class Graph(object)

...

line 1517: __getstate__

...

line 1533: __setstate__

Ответы [ 2 ]

4 голосов
/ 20 декабря 2011

В соответствии с документацией, когда __getstate__ не определен, экземпляр __dict__ будет засечен, поэтому, возможно, вы можете использовать его для определения собственных методов состояния как комбинации методов A и экземпляра __dict__ * * 1005

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
0 голосов
/ 20 декабря 2011

Поведение по умолчанию для Pickle: __getstate__ не определено для выбора содержимого атрибута объектов __dict__ - именно там хранятся атрибуты экземпляра.

Следовательно, это выглядит как в вашем случаевсе, что вам нужно сделать, это сделать A get и set state, чтобы сохранить значения, найденные в self.__dict__, и затем восстановить при __setstate__ - это должно сохранить также переменные экземпляра всех экземпляров подклассов A.

...