0

I am migrating some of my code from MATLAB. I was wondering if a functionality exists where I define a certain class (3d vector) and I could define arrays (or lists?) of this class. I would like to be able to use slicing operations on this array.

For example, MATLAB has this functionality:

obj = class(s,'class_name') 

creates an array of class class_name objects using the struct s as a pattern to determine the size of obj.

I understand that numpy offers everything I need for array operations. I am trying to learn right now and this is just and example. So, I would like to do this without numpy arrays.

I might be completely wrong in approaching it this way, so please feel free to suggest if there are any better methods out there to do this. I was looking into subclassing ndarray, but that seems like I would just be creating an array again. Any suggestions are greatly appreciated.

My code so far:

class vector3d(object):

    def __init__(self,*args):
        nargs = len(args);
        if(nargs == 0): # Null Vector
            self.x = None; self.y = None; self.z = None;
        elif(nargs==1):
            if (type(args[0]) is vector3d):
                self = args[0];
            elif(type(args[0]) is np.ndarray):
                Vec = args[0];
                if (np.shape(Vec)[0]==1 or np.shape(Vec)[1]==1):
                    if (np.shape(Vec) == (3,1)):
                        self.x = Vec[0,0]; self.y = Vec[1,0]; 
                        self.z = Vec[2,0];

                    elif (np.shape(Vec) == (1,3)):
                        self.x = Vec[0,0]; self.y = Vec[0,1]; 
                        self.z = Vec[0,2];
                    else:
                        raise Exception('Wrong Type of Inputs');
                else:
                    raise Exception('Wrong Type of Inputs');

VecArray = np.ndarray((10,), dtype=np.object);
print np.shape(VecArray);
for i in range(10):
    print i;
    VecArray[i] = vector3d(np.random.rand(3,1));

After running the code, when I try the following:

>>> VecArray[1].x

>>> 0.36923808713820772

>>> VecArray[1:5].x

AttributeError                            Traceback (most recent call last)
<ipython-input-92-899463ad0461> in <module>()
----> 1 VecArray[1:5].x

AttributeError: 'numpy.ndarray' object has no attribute 'x'

I understand that I could make lists of the object. I should have been more specific. I would like to get an indexable variable as output. For example, something that does not give the above as error.

10
  • 1
    You can put whatever you want into regular Python lists, including instances of your custom class. Commented Aug 6, 2014 at 13:51
  • 3
    Have you tried anything at all? Commented Aug 6, 2014 at 13:52
  • @timgeb: So I just define a class and make lists of that class? What if I want to pass numpy arrays as input to the class? I would ideally want it to output a list (or array) of the class. For example, if I input numpy 3X10 array of floats.. I would like to have a list of 10 vector3d objects. Could this be done in the definition of the class? Commented Aug 6, 2014 at 13:56
  • @Lidtke: Yes, I have tried defining the class by itself. I am stuck in trying to figure out how to handle array inputs. As I had already mentioned, I am trying subclassing ndarray as well. But this just ended up creating another array of type vector3d. Commented Aug 6, 2014 at 13:58
  • 1
    It does (finally) make sense, but I don't think it's (easily) possible - a slice returns a container, which doesn't have the same attributes as the objects inside. You could maybe create some custom container that implements __getattr__ and checks its contents for any attributes it doesn't have itself, but that's a lot of work. Commented Aug 6, 2014 at 14:42

2 Answers 2

4

You can use numpy datatypes: http://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html

>>> dt = np.dtype([('x', np.int32), ('y', np.int32), ('z', np.int32)])
>>> x = np.array([(1, 2, 3), (3, 2, 1)], dtype = dt)
>>> print x 
[(1, 2, 3) (3, 2, 1)]
>>> print x['x'], x['y'], x['z']
[1 3] [2 2] [3 1]
>>> print x[0]['x']
1

Extending example to add some numpy/matlab indexing:

>>> x = np.array([(1, 2, 3), (4, 5, 6), (7, 8, 9)], dtype = dt)
>>> print x[1:]['x']
[4 7]

You can notice that it omits the first element in the X axis (the 1)


EDIT to add some information about how to subclass using custom data type. Using the example in answer from a similar question https://stackoverflow.com/a/5154869/764322 and sightly modifying it:

>>> class Data(np.ndarray):
        def __new__(cls, inputarr):
            dt = np.dtype([('x', np.int32), ('y', np.int32), ('z', np.int32)])
            obj = np.asarray(inputarr, dtype = dt).view(cls)
            return obj

        def remove_some(self, col, val):
            return self[self[col] != val]

>>> a = Data([(1,2,3), (4,5,6), (7,8,9)])
>>> print a
[(1, 2, 3) (4, 5, 6) (7, 8, 9)]
>>> print a.remove_some('x', 4)
[(1, 2, 3) (7, 8, 9)]
Sign up to request clarification or add additional context in comments.

4 Comments

Perfect.. Thank you so much! This is exactly what I was looking for! I think, if I am not mistaken, you defined a data type here. Would it be possible to extend this to a class? I would like to define a few methods for this class. Thank you! (PS: I would upvote your answer but all the down-votes to my question ended up reducing my points below 15! Sorry.)
If I don't get it wrong, this might be what you want: docs.scipy.org/doc/numpy/user/… . You can force the numpy array to be the type of dt and then add new methods.
Oh, okay! Looks like subclassing is the way to go. Thank you!
I've just edited to give you an example of how to subclass. Note the custom datatype in the new method.
1

I think what you want is numpy.empty:

>>> import numpy as np
>>> a = np.empty((2, 2), dtype=np.object_)
>>> a
array([[None, None],
       [None, None]], dtype=object)

This creates an empty array with the specified shape (in this case 2x2) and dtype (in this case, generic objects).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.