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.
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.