处理 numpy 数组中 class 的属性

Handling attributes of a class within a numpy array

我想处理 class 属性 而无需通过 Python for 循环 。要处理大型数组,numpy 是 best/fastest 但是否可以访问 numpy 数组中的 class 属性?考虑以下简单代码:

import numpy as np

class MyClass():
    def __init__(self):
        self.myvar1 = 10
        self.myvar2 = 20

myarray1 = np.arange(0, 1000, 1)
myarray2 = np.array([MyClass() for i in range(1000)])

myarray1 的所有值都可以通过一行轻松修改:

myarray1 += 5

但是我如何访问 myarray2 中所有 MyClass 个实例的 myvar1 并一次性修改它? (甚至可能吗?)我知道以下内容不起作用,但它给出了我想要实现的目标的想法:

myarray2.myvar1 += 5
myarray2[myarray2.myvar1] += 5

我一直在四处寻找解决方案,我能找到的最接近的东西是 numpy 的 recarray,它可以模仿 Python classes,但它似乎不是我使用的 class 的解决方案是 subclass (确切地说是 pyglet Sprite)所以我确实需要使用 Python class.

编辑

根据 hpaulj 评论,我正在尝试使用 class 的矢量化函数来更新其属性。它是更新 class 的所有实例的有效方法吗?

class MyClass():
    def __init__(self):
        self.myvar1 = 10
        self.myvar2 = 20
    def modifyvar(self):
        self.myvar1 += 5
        return self

vecfunc = np.vectorize(MyClass.modifyvar)
myarray2 = np.array([MyClass() for i in range(1000)])
myarray2 = vecfunc(myarray2)

然而,另一个问题出现了:当使用这个代码时,myarray2[0].myvar1 returns 20 而不是 15! myarray2[1].myvar1 做 return 15,数组的其余部分也是如此。为什么 myarray2[0] 这里不一样?


解决方案

矢量化 class 的函数允许在没有 for 循环的情况下处理其多个实例的属性。解法代码:

class MyClass():
    def __init__(self):
        self.myvar1 = 10
        self.myvar2 = 20
    def modifyvar(self):
        self.myvar1 += 5
        return self

vecfunc = np.vectorize(MyClass.modifyvar, otypes=[object])
myarray2 = np.array([MyClass() for i in range(1000)])
vecfunc(myarray2)

注意:在使用向量化和处理对象时添加otype=[object]

modifyvar 对第一个元素的额外应用是由于 vectorize 试图将数组类型确定为 return。指定 otypes 可以解决该问题:

vecfunc = np.vectorize(MyClass.modifyvar,otypes=[object])

有了这个'inplace'修饰符,你就不用关注returned:

是什么了
vecfunc(myarray2)

足够了。

来自 vectorize 文档:

The data type of the output of vectorized is determined by calling the function with the first element of the input. This can be avoided by specifying the otypes argument.

如果您定义了一个 add5 方法,例如:

    def add5(self):
        self.myvar1 += 5
        return self.myvar1

然后

vecfunc = np.vectorize(MyClass.add5,otypes=[int])
vecfunc(myarray2)

会return一个数值数组,同时修改myarray2

array([15, 15, 15, 15, 15, 15, 15, 15, 15, 15])

显示我使用的值:

[x.myvar1 for x in myarray2]

我真的应该定义一个向量化的'print'。

这看起来像是 vectorize 的更好应用之一。它不会给你任何编译速度,但它确实让你在一个一个地操作你的实例时使用数组符号和广播。例如 vecfunc(myarray2.reshape(2,5)) returns 一个 (2,5) 值数组。