Hi Christiaan

On Sun, Apr 15, 2007 at 02:03:49PM +0900, Christian K wrote:
> could someone please provide example code for how to make a subclassed ndarray
> pickable? I don't quite understand the docs of ndarray.__reduce__.
> My subclassed ndarray has just one additional attribute.
> 

__reduce__ is part of the pickle protocol, which is described at

http://docs.python.org/lib/node321.html

You need to modify __reduce__ to store the complete state of your
custom object, as well as __setstate__ which restores the state on
unpickling.

See the attached code as an example.  There, I have an InfoArray,
which is a subclassed numpy.ndarray.  The InfoArray contains an
additional member, info, which is a dictionary.

The __reduce__ method calls ndarray's __reduce__, then adds to the
result the state of the InfoArray.  Conversely, the __setstate__
method calls ndarray's __setstate__ as well as restoring the info
member.

Regards
Stéfan
import numpy as N

class InfoArray(N.ndarray):
    def __new__(subtype, data, dtype=None, info=None, copy=False):
        subtype.__defaultinfo = info
        
        if copy:
            data = N.array(data,dtype=dtype)
        else:
            data = N.asarray(data,dtype=dtype)

        data = data.view(subtype)
        return data

    def __array_finalize__(self,obj):
        if not hasattr(self, "info"):
            # The object does not already have an `.info` attribute: we use the default
            self.info = getattr(obj,'info',self.__defaultinfo)
            
    def __reduce__(self):
        object_state = list(N.ndarray.__reduce__(self))
        subclass_state = (self.info,)
        object_state[2] = (object_state[2],subclass_state)
        return tuple(object_state)
    
    def __setstate__(self,state):
        nd_state, own_state = state
        N.ndarray.__setstate__(self,nd_state)
        
        info, = own_state
        self.info = info

    def __repr__(self):
        desc="""\
array(data=
  %(data)s,
      tag=%(tag)s)"""
        return desc % {'data': str(self), 'tag':self.info }

import numpy as N
x = InfoArray(N.arange(10), info={'name':'x'})
print repr(x)
y = InfoArray(N.arange(10), info={'name':'y'})
assert (x.info['name']=='x')
assert (y.info['name']=='y')
z = N.sqrt(x)
print repr(z)

# -- demonstrate that instance of subclass can be pickled --

import pickle
print "\n\nBefore pickling:"
print repr(z)

jar = pickle.dumps(z)
z = pickle.loads(jar)

print "\n\nAfter pickling:"
print repr(z)

_______________________________________________
Numpy-discussion mailing list
[EMAIL PROTECTED]
http://projects.scipy.org/mailman/listinfo/numpy-discussion

Reply via email to