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)
将使其对长阵列更有效。