[Numpy-discussion] python user defined type

Nicolas Rougier Nicolas.Rougier at loria.fr
Thu Jul 10 17:45:29 EDT 2008



Thanks for the precise explanation that make things clearer. In fact,
the example I gave was mainly to illustrate my question in the quickest
way.

Concerning the dtype argument during array creation, I thought it was
here for somehow controlling the type of array elements. For example, if
I use a "regular" numpy array (let's say a float array), I cannot set an
item to a string value (it raises a ValueError: setting an array element
with a sequence).

So what would be the best way to use numpy arrays with "foreign" types
(or is it possible at all) ?  I've designed the "real" Unit in C++ and
exported it to python (via boost and shared pointers) and I would like
to create array of such Units (in fact, I also created an array-like
class but I would prefer to use directly the real array interface to
benefit from the great work of numpy instead of re-inventing the
wheel). 

Ideally, I would like to be able to write 

z = N.array (a, dtype=Unit)

and would expect numpy to make a copy of the array by calling my type
with each element of a. Then, if my type accepts the argument during
creation, everything's fine, else it raises an error.

Nicolas 



On Thu, 2008-07-10 at 13:43 -0700, Christopher Barker wrote:
> Nicolas Rougier wrote:
> > I would like to create numpy array with my own (python) datatype, so I
> > tried the obvious solution:
> > 
> > from numpy import *
> > class Unit(object):
> >     def __init__(self,value=0.0):
> >         self.value = value
> >     def __float__(self):
> >         return self.value
> >     def __repr__(self):
> >         return str(self.value)
> 
> > a = array (array([[1,2],[3,4]]), dtype=Unit)
> 
> the dtype argument is designed to take a numpy type object, not an 
> arbitrary class -- what you want in this case is dtype=numpy.object, 
> which is what you did before. I'm a surprised this didn't raise an 
> error, but it looks like you got an object array, but you objects you 
> gave it are python integers.  All python classes are "objects" as far an 
> numpy is concerned. The numpy dtypes are a description of a given number 
> of bytes in memory -- python classes are stored as a pointer to the 
> python object.
> 
> (and you really don't want to use "import *")
> 
> > Also, the commented line (a[0,0] = 0) makes the item to become an int
> > while I need to set the value of the item instead, is that possible ?
> 
> a[0,0] = Unit(0)
> 
> You're setting the [0,0]th element to an object, you need to give it the 
> object you want, the literal "0" is a python integer with the value zero.
> 
> numpy arrays of python objects act a whole lot like other python 
> containers. What would you expect from :
> 
> a = [1,2,3,4]
> 
> a list of integers, no?
> 
> or
> 
> a = [Unit(1), Unit(2)]
> 
> #  a list of Units..
> 
> then
> 
> # a[0] = 3
> 
> now a list with the integer3 in the zeroth position, and a Unit in the 1st.
> 
> You did it right the first time:
> 
> a = array([[Unit(1), Unit(2)], [Unit(3), Unit(4)]])
> 
> though you need to be careful building object arrays of nested lists -- 
> numpy won't unnecessarily figure out how do d-nest it. You might want to do:
> 
>  >>> import numpy as np
>  >>> a = np.empty((2,2), np.object)
>  >>> a
> array([[None, None],
>         [None, None]], dtype=object)
>  >>> a[:,:] = [[Unit(1), Unit(2)], [Unit(3), Unit(4)]]
>  >>> a
> array([[1, 2],
>         [3, 4]], dtype=object)
> 
> One more note:
> 
> class Unit(object):
>      def __init__(self,value=0.0):
>          self.value = value
>      def __float__(self):
>          return self.value
>      def __repr__(self):
>          return str(self.value)
> 
> 
> __repr__ really should be something like:
>      def __repr__(self):
>          return "Unit(%g)%self.value"
> 
> eval(repr(Object)) == Object, ideally, plus it'll be easier to debug if 
> you can see what it is.
> 
> -Chris
> 
> 
> 




More information about the NumPy-Discussion mailing list