Reputation: 829
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.
Upvotes: 0
Views: 2235
Reputation: 15909
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)]
Upvotes: 4
Reputation: 122091
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).
Upvotes: 0