Re: Pickling and unpickling inherited attributes
- From: Steve Holden <steve@xxxxxxxxxxxxx>
- Date: Mon, 31 Oct 2005 02:03:39 +0000
Alex wrote:
You have explicitly told the objects' class definition to only store the C attribute as a part of the object state.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
obj=Child(1) obj.A=2 obj.B=3 obj.A
2
obj.B
3
obj.C
1
objct.Z=4
Traceback (most recent call last): File "<pyshell#60>", line 1, in -toplevel- objct.Z=4 AttributeError: 'Child' object has no attribute 'Z'
So far so good.. Object obj inherited attributes (A and B) from the parent class and refuses to take any new ones. But look what happens when I try to pickle and unpickle it:
import cPickle File=open('test', 'w') cPickle.dump(obj, File) File.close()
file1=open('test', 'r') objct=cPickle.load(file1) file1.close() objct.A
Traceback (most recent call last): File "<pyshell#55>", line 1, in -toplevel- objct.A AttributeError: A
objct.C
1
Its own attribute (C) value is restored but the value of an inherited attribute (A) is not. I tried pickling protocol 2, and module pickle instead of cPickle, all with the same result.
What can be done?! Or maybe nothing can be done?
I would greatly appreciate an advice. A lot of code is written, but now we have a need for pickling and unpickling objects and discovered this problem.
If you change the definition of child to:
class Child(Parent):
__slots__=['C',] def __init__(self, c): self.C=c def __getstate__(self): return self.A, self.B, self.C, def __setstate__(self, tup): self.A, self.B, self.C, =tup
everything works as you expect. But I presume you want the subclass to require no knowledge of the superclass state?
In that case you might consider rewriting Child as
class Child(Parent):
__slots__ = ['C'] # only tuples need trailing comma
def __init__(self, c):
self.C = c
def __getstate__(self):
return Parent.__getstate__(self) + (self.C, )
def __setstate__(self, t):
self.C = t[-1]
Parent.__setstate__(self, t[:-1])This would work adequately. May I ask your use case for __slots__? I presume there is a specific reason why you can't just code the classes as
class Parent(object):
def __init__(self, a, b):
self.A = a
self.B = bclass Child(Parent):
def __init__(self, c):
self.C = csince these definitions will pickle and unpickle perfectly.
A couple of other notes:
First, it's always safest to open pickle files in binary mode, as this will eliminate the chance of platform differences making a pickle written on one architecture or platform being unreadable by another.
Secondly, it's usual to have the subclass explicitly call the superclass to initialize that portion of the instance. So it would be more typically Pythonic to write
class Child(Parent):
def __init__(self, c):
Parent.__init__(self, a, b)
self.C = cThis allows you to pass the a and b values into the creator call in the following way:
obj = Child(2, 3, 1)
rather than explicitly setting attributes of the Child instance in line. If your inheritance patterns are complex you may find it useful to investigate the super() function.
regards Steve -- Steve Holden +44 150 684 7255 +1 800 494 3119 Holden Web LLC www.holdenweb.com PyCon TX 2006 www.python.org/pycon/
.
- Prev by Date: need start point for getting html info from web
- Next by Date: Re: Scanning a file
- Previous by thread: Re: Pickling and unpickling inherited attributes
- Next by thread: Re: Controlling output using print with format string
- Index(es):
Relevant Pages
|