Python 从NumPy中的对象数组获取属性

Python 从NumPy中的对象数组获取属性,python,numpy,Python,Numpy,假设我有一个名为Star的类,它有一个属性color。我可以用星号获得颜色。颜色 但是如果我有一个由这些Star对象组成的NumPy数组呢。获得一系列颜色的首选方法是什么 我可以用它来做 colors = np.array([s.color for s in stars]) 但这是最好的方法吗? 如果我能像在其他语言中那样做colors=star.color或colors=star->color等,那就太好了。有 在numpy中执行此操作的一种简单方法?最接近您想要的方法是使用recarray

假设我有一个名为
Star
的类,它有一个属性
color
。我可以用星号获得颜色。颜色

但是如果我有一个由这些
Star
对象组成的NumPy数组呢。获得一系列颜色的首选方法是什么

我可以用它来做

colors = np.array([s.color for s in stars])
但这是最好的方法吗? 如果我能像在其他语言中那样做
colors=star.color
colors=star->color
等,那就太好了。有
在numpy中执行此操作的一种简单方法?

最接近您想要的方法是使用
recarray
而不是Python对象的
ndarray

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

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

使用Python对象的NumPy数组通常不如使用普通的
列表
,而
重新数组
以更高效的格式存储数据。

您可以使用
NumPy.fromiter(s.color表示星中的s)
(注意缺少方括号)。这将避免创建中间列表,我想如果使用numpy,您可能会关心这个问题


(感谢@SvenMarnach和@DSM在下面的更正)。

如果
star
是一个更复杂的
,下面是一种获取和设置 属性的顶部有一个helper

import numpy as np

class star:
    def __init__(self, mass=1, radius=1):
        self.mass = mass
        self.radius = radius

class 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**3
print(S.density)
print(s1.density)
当然,如果该类可以重新实现为
重新排列
,那么它应该会更高效。然而,这样的重新实施可能是不可取的


注意,外部计算,如密度计算,仍然是矢量化的。通常,这些可能是瓶颈,而不是设置和获取属性。

可能与Cool重复。所以它使它们就像IDL结构数组一样,这正是我想要的。如果已经定义了一个常规python类,那么如何使用它?有没有一个简单的方法可以做到这一点?@Dave31415:IDL?你是天文学家,还是天文学以外的人真的在用这个?至于你的问题:没有看到类定义,这有点难以回答。使用NumPy,您通常不希望“方法”对单个记录进行操作,而是希望函数能够同时对整个数组进行操作。所以你需要将你的方法矢量化,努力成为一名前天文学家。所以我想你说的是对象数组不是numpy的首选数据结构。但那又是什么呢?我可以创建属性为numpy数组的类。这是更好的方法吗?这听起来不像我想要的。@Dave31415:我现在很困惑。我所说的是,与Python对象的NumPy数组相比,使用NumPy
recarray
更可取,至少在使用NumPy时是这样。如果一个普通的
Star
实例列表为您完成了任务,那么您最好使用一个普通列表。同样,在不了解更多用例的情况下很难给出建议。首先,我的类可能没有方法。它们基本上就像C或python中的“结构”。如果是这样的话,看来重新安排会很好地解决这个问题,对吗?在这种情况下,您甚至会费心定义类还是直接去定义数据类型?不幸的是,这样做行不通:您会得到类似于
array(,dtype=object)
的结果。(我曾经在我的代码中有一个bug,这最终是因为我认为这会起作用。)为此,您需要使用
numpy.fromiter()
。注意:要在最近的numpy中起作用,您需要
numpy.fromiter((s.color表示星中的s),float)
。另外,添加
count=len(stars)
将使其对长阵列更有效。