Getting attributes from arrays of objects in NumPy Getting attributes from arrays of objects in NumPy numpy numpy

Getting attributes from arrays of objects in NumPy


The closest thing to what you want is to use a recarray instead of an ndarray of Python objects:

num_stars = 10dtype = numpy.dtype([('x', float), ('y', float), ('colour', float)])a = numpy.recarray(num_stars, dtype=dtype)a.colour = numpy.arange(num_stars)print a.colour

prints

[ 0.  1.  2.  3.  4.  5.  6.  7.  8.  9.]

Using a NumPy array of Python objects usually is less efficient than using a plain list, while a recarray stores the data in a more efficient format.


You could use numpy.fromiter(s.color for s in stars) (note lack of square brackets). That will avoid creating the intermediate list, which I imagine you might care about if you are using numpy.

(Thanks to @SvenMarnach and @DSM for their corrections below).


In case star is a more complicated class, here is an approach to get and setthe attributes with a helper class on top.

import numpy as npclass star:    def __init__(self, mass=1, radius=1):        self.mass = mass        self.radius = radiusclass Stars(list):    __getattr__ = lambda self, attr: np.array([getattr(s, attr) for s in self])    def __setattr__(self, attr, vals):        if hasattr(vals, '__len__'):            [s.__setattr__(attr, val) for (s,val) in zip(self,vals)]        else:            [s.__setattr__(attr, vals) for s in self]s1 = star(1, 1.1)s2 = star(2, 3)S = Stars([s1, s2])print(S.mass)print(S.radius)S.density = S.mass / S.radius**3print(S.density)print(s1.density)

Of course, if the class can be reimplemented into a recarray, it should be more efficient. Yet, such a reimplementaion might be undesirable.

Note, outer computations, like the density calculation, are still vectorised. And often those could be bottleneck, rather than setting and getting attributes.