Да, это возможно -
Всякий раз, когда вы хотите настроить поведение Pickle и Unpickle для ваших объектов, вам просто нужно установить методы "__getstate__
" и "__setstate__
" в классесама по себе.
В этом случае это немного сложнее: как вы заметили, существует необходимость в существовании класса в глобальном пространстве имен, который является классом выбранного в данный момент объекта: это должен быть тот же классс тем же именем.Хорошо, дело в том, что этот класс, существующий в пространстве глобальных имен, может быть создан во время Pickle.
Во время Unpickle должен существовать класс с тем же именем, но он не должен быть таким жеобъект - просто ведите себя так, как он это делает - и так как __setstate__
вызывается в процессе Unpickling, он может воссоздать параметризованный класс объекта orignal и установить собственный класс таким, устанавливая атрибут __class__
объектаobject.
Установка атрибута __class__
объекта может показаться нежелательной, но именно так OO работает в Python, и это официально задокументировано, даже работает в разных реализациях.(Я тестировал этот фрагмент в Python 2.6 и Pypy)
class Base(object):
def m(self):
return self.__class__.PARAM
def __getstate__(self):
global AutoSub
AutoSub = self.__class__
return (self.__dict__,self.__class__.PARAM)
def __setstate__(self, state):
self.__class__ = make_parameterized(state[1])
self.__dict__.update(state[0])
def make_parameterized(param_value):
class AutoSub(Base):
PARAM = param_value
return AutoSub
class AutoSub(Base):
pass
if __name__ == "__main__":
from pickle import dumps, loads
a = make_parameterized("a")()
b = make_parameterized("b")()
print a.PARAM, b.PARAM, type(a) is type(b)
a_p = dumps(a)
b_p = dumps(b)
del a, b
a = loads(a_p)
b = loads(b_p)
print a.PARAM, b.PARAM, type(a) is type(b)