[Python] pickle di una classe derivata

Simone Ziraldo simone.ziraldo a gmail.com
Mer 5 Dic 2012 18:13:57 CET


On 05/dic/2012, at 10.05, Marco Giusti wrote:

> On Wed, Dec 05, 2012 at 12:04:54AM +0100, Simone Ziraldo wrote:
>> Ciao a tutti,
>> 
>> il problema che ho è questo: quando faccio il pickle di una classe derivata di numpy.ndarray non mi salva gli attributi che ho definito io.
>> Un codice semplice che genera questo problema è questo:
>> 
>> import pickle
>> import numpy
>> 
>> class prova( numpy.ndarray ):
>>    def __new__(cls,size):
>>        return numpy.ndarray.__new__( cls, size )
>>    def __init__(self,size ):
>>        self.__size__ = size
>> 
>> s = prova(2)
>> 
>> f = open("prova.out", 'w')
>> pickle.dump(s,f)
>> f.close()
>> 
>> f = open("prova.out", 'r')
>> obj = pickle.load(f)
>> f.close
>> 
>> print obj.__size__
>> 
>> e mi viene restituito questo errore:
>> AttributeError: 'prova' object has no attribute '__size__'
> 
> 	>>> class prova2(numpy.ndarray):
> 	...  def __init__(self, size):
> 	...   numpy.ndarray.__init__(self, size)
> 	...   self.__size__ = size
> 	...  def __reduce__(self):
> 	...   t = numpy.ndarray.__reduce__(self)
> 	...   klass, args = t[:2]
> 	...   func, args = t[:2]
> 	...   return (reconstruct, (func, args, self.__size__)) + t[2:]
> 	...
> 	>>> def reconstruct(f, args, size):
> 	...  o = f(*args)
> 	...  o.__size__ = size
> 	...  return o
> 	...
> 	>>> p3 = pickle.loads(pickle.dumps(p2))
> 	>>> p3
> 	prova2([  6.90286283e-310,   6.90286283e-310,   1.58101007e-322])
> 	>>> p3.__dict__
> 	{'__size__': 3}
> 	>>> 
> 
> la documentazione su pickle spiega tutto

Grazie!

Mi sono guardato la documentazione e mi sono rimasti dei dubbi.
Ad esempio non mi è ben chiaro quando nel dump decide di usare il metodo __reduce__ invece di __getstate__. La guida dice che usa __reduce__ "When the Pickler encounters an object of a type it knows nothing about", però ad esempio se faccio il dump di una classe nuova non usa __reduce__ ma __getstate__.
Ad esempio:
class trial():
    def __reduce__(self):
        print "Hello from reduce"
    def __getstate__(self):
        print "Hello from getstate"
pickle.loads(pickle.dumps( trial()))

stampa: Hello from getstate

Quindi, trial è un type che "conosce", mentre una classe derivata da numpy.ndarray (nell'esempio iniziale) è un type che non conosce...

Grazie,
Simone



Maggiori informazioni sulla lista Python