Pickling and unpickling inherited attributes

Alex Martelli aleaxit at yahoo.com
Mon Oct 31 01:25:25 CET 2005


Alex <OurLab at gmail.com> wrote:

> I have a serious problem and I hope there is some solution. It is
> easier to illustrate with a simple code:
> 
> >>> class Parent(object):
>       __slots__=['A', 'B']
>       def __init__(self, a, b):
>               self.A=a; self.B=b
>       def __getstate__(self):
>               return self.A, self.B
>       def __setstate__(self, tup):
>               self.A, self.B=tup
> 
> 
> >>> class Child(Parent):
>       __slots__=['C',]
>       def __init__(self, c):
>               self.C=c
>       def __getstate__(self):
>               return self.C,
>       def __setstate__(self, tup):
>               self.C, =tup

Child.__getstate__ and __setstate__ need to cooperate with those of
Parent, not just override them as yours do.  __getstate__ is easy:

in Child:

   def __getstate__(self):
       return super(Child, self).__getstate__ + (self.C,)

i.e., each class will successively append its parts of state to the
resulting overall tuple.  It's harder to do for __setstate__ without
building into it a strong dependency on how many items of the tuple the
Parent is taking for its own use; you need to establish some protocol of
your own for that purpose, such as:

in Parent:

   def __setstate__(self, tup):
       self.A, self.B = tup[:2]
       self._tup = tup[2:]

in Child:

   def __setstate__(self, tup):
       super(Child, self).__setstate__(tup)
       self.C, = self._tup[:1]
       self._tup = self._tup[1:]

(the last statement is needed in case Child was further subclassed by a
Grandchild class following the same set-state protocol).

Working with lists rather than tuples might in fact be simpler.  But
simplest might be if __setstate__ was allowed to return something
different than None, so it could return "whatever's left of the tuple"
rather than relying on that nasty self._tup thingy (which is going to be
left there, empty, in the end -- though, each class could conditionally
delete it if it was empty).  However, while I believe it is not
currently enforced that __setstate__ might return a non-None value to be
ignored, I'm not sure it's _allowed_, either, so I wouldn't try (lest
this application should break in strange ways in future Python
versions).


Alex




More information about the Python-list mailing list