[Tutor] Pickling

Kent Johnson kent37 at tds.net
Sun Feb 13 14:37:53 CET 2005


Johan,

The problem is in your class V. You have

> class V:
>     a=[]
>         
>     def add(self, s):
>         self.a.append(s)

The problem is that 'a' is a *class* variable, not an instance variable. The correct way to define V 
is like this:

class V:
     def __init__(self):
         self.a=[]  # Now 'a' is an instance variable

     def add(self, s):
         self.a.append(s)

Why does this cause the behaviour you are seeing? Let's take a look at your assign() and add() 
functions:

> def assign():
>     p=V()

At this point p has no 'a' attribute of its own, just the class attribute inherited from V.

>     p.a = [1,2,3,4]

This assignment *creates* an 'a' attribute in the object p. Now when you pickle p, it gets the list 
saved with it.

>     f = open ("blah.dat", 'a')
>     print 'assign:', p.a
>     pickle.dump(p,f)
>     f.close()
> 

OK, how about add()?
> def add():
>     p=V()
>     p.add(1);p.add(2);p.add(3);p.add(4);

This is changing the *class* attribute 'a'! The object p has no attribute 'a', so when p is pickled, 
no list is saved with it.

>     print 'add:', p.a
>     f = open("blah.dat", 'a')
>     pickle.dump(p,f)
>     f.close()

The reason you see the expected list when you run both versions is because you have changed the 
class attribute.

A little dabbling in the Python interpreter might clarify a bit more:

  >>> class V:
  ...     a=[]
  ...     def add(self, s):
  ...         self.a.append(s)
  ...
  >>> p=V()
  >>> p.a
[]
  >>> V.a
[]
  >>> p.add(1)
  >>> p.add(2)
  >>> p.a
[1, 2]
  >>> V.a
[1, 2]

p.a is actually accessing V.a.

  >>> p=V()
  >>> p.a = [3,4]
  >>> p.a
[3, 4]
  >>> V.a
[1, 2]

Now p has it's own a and V.a is unchanged.

Kent

Johan Kohler wrote:
> Hi
> I still have problems pickling and unpickling.  After I couldn't get
> "complicated" objects to work, i decided to use simple lists.  But now
> there seems to be a difference between assigning a list value, and using
> the .append method.  Please try out the code at
> http://goose.cs.und.ac.za/python/save1.py     There are two "use cases" 
>  WorkingCase() and BrokenCase.  
> 
> WorkingCase() saves data in a list using assignment, and by appending,
> and then reads it back from the file.  BrokenCase performs only the
> reading back step.   Now, there are no problems when the two cases are
> run consecutively.  Do this once.  Then comment out the WorkingCase()
> statement, and run only BrokenCase().  This should read back all the
> list entries, but all the ones created by "appending" are blank!  I
> should mention, that in my application I want to append items one by one
> to the list.
> 
> Please can someone help me with this?  I am getting extremely frustrated
> by not being able to get supposedly simple stuff to work.
> 
> Thanks in advance,
> Johan
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> http://mail.python.org/mailman/listinfo/tutor
> 



More information about the Tutor mailing list