所以你的数组是dtype=object(打印出来)并且每个元素都指向你的类的一个实例:
items = np.array([TestClass() for _ in range(10)])
现在试试:
items.active
items 是一个数组; active 是类的属性,而不是对象数组的属性。您的定义不会向ndarray 类添加任何功能。错误不在掩蔽中;它是在尝试获取实例属性。
像这样的数组上的许多操作都是迭代完成的。这种数组类似于普通的 Python 列表。
[obj.active for obj in items]
或将其转回数组
np.array([obj...])
items[[True,False,True,...]] 应该可以工作,但那是因为掩码已经是一个布尔列表或数组。
=====================
让我们修改你的类,让它显示一些有趣的东西。请注意,我将 active 分配给实例,而不是像您所做的那样分配给类:
In [1671]: class TestClass:
...: def __init__(self,val):
...: self.active = bool(val%2)
In [1672]: items = np.array([TestClass(i) for i in range(10)])
In [1674]: items
Out[1674]:
array([<__main__.TestClass object at 0xb106758c>,
<__main__.TestClass object at 0xb117764c>,
...
<__main__.TestClass object at 0xb269850c>], dtype=object)
# print of the array isn't interesting. The class needs a `__str__` method.
这个简单的迭代访问属性:
In [1675]: [i.active for i in items]
Out[1675]: [False, True, False, True, False, True, False, True, False, True]
np.frompyfunc 提供了一种更强大的方式来访问数组的每个元素。 operator.attrgetter('active')(i) 是i.active 的一种功能性方式。
In [1676]: f=np.frompyfunc(operator.attrgetter('active'),1,1)
In [1677]: f(items)
Out[1677]: array([False, True, False, True, False, True, False, True, False, True], dtype=object)
但是当我改变数组的形状时,这个函数的主要优点就显现出来了:
In [1678]: f(items.reshape(2,5))
Out[1678]:
array([[False, True, False, True, False],
[True, False, True, False, True]], dtype=object)
注意这个数组是 dtype 对象。这就是frompyfunc 所做的。要获取布尔数组,我们需要更改类型:
In [1679]: f(items.reshape(2,5)).astype(bool)
Out[1679]:
array([[False, True, False, True, False],
[ True, False, True, False, True]], dtype=bool)
np.vectorize 使用frompyfunc,并使 dtype 更加用户友好。但在时间上它有点慢。
================
扩展 Jon 的评论
In [1702]: class TestClass:
...: def __init__(self,val):
...: self.active = bool(val%2)
...: def __bool__(self):
...: return self.active
...: def __str__(self):
...: return 'TestClass(%s)'%self.active
...: def __repr__(self):
...: return str(self)
In [1707]: items = np.array([TestClass(i) for i in range(5)])
items 现在以信息丰富的方式显示;并转换为字符串:
In [1708]: items
Out[1708]:
array([TestClass(False), TestClass(True), TestClass(False),
TestClass(True), TestClass(False)], dtype=object)
In [1709]: items.astype('S20')
Out[1709]:
array([b'TestClass(False)', b'TestClass(True)', b'TestClass(False)',
b'TestClass(True)', b'TestClass(False)'],
dtype='|S20')
并转换为bool:
In [1710]: items.astype(bool)
Out[1710]: array([False, True, False, True, False], dtype=bool)
实际上astype 正在将转换方法应用于数组的每个元素。我们还可以定义__int__、__add__,这表明向自定义类添加功能比向数组类本身添加功能更容易。我不希望获得与原生类型相同的速度。