【发布时间】:2015-02-27 21:09:36
【问题描述】:
我想处理类属性不通过 Python for 循环。要处理大型数组,numpy 是最好/最快的,但是否可以访问 numpy 数组中的类属性?考虑以下简单的代码:
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 类,但它似乎不是我的解决方案,因为我使用的类是一个子类(确切地说是一个 pyglet Sprite),所以我确实需要使用 Python 类。
编辑
跟进 hpaulj 评论,我正在尝试使用该类的矢量化函数来更新其属性。这是更新类的所有实例的有效方法吗?
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 返回 20 而不是 15! myarray2[1].myvar1 确实返回 15,数组的其余部分也是如此。为什么myarray2[0] 在这里不一样?
解决方案
向量化类的函数允许在没有 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)
注意:在使用vectorize和处理对象时添加otype=[object]。
【问题讨论】:
-
是您想要避免 for 循环的唯一原因,因为您希望/期望它在没有循环的情况下更快?
-
这是主要原因之一,但即使它没有提高性能,我仍然想知道是否可以访问 numpy 数组中对象的属性。
-
myarray2有dtype=object。因此,其数据缓冲区中的每个条目都是指向内存中其他位置的实例的指针。该类型数组的矢量化(使用编译代码)操作非常初级。 -
recarray是结构化数组的覆盖。数据存储为恒定大小的“元组”(与数字或指针相反)。使用结构化数组,您可以使用myarray3['myvar1'] +=1 -
感谢您的帮助。我看不出
recarray是如何一次更新所有python 类实例的,你能解释一下吗?对于矢量化操作,请查看我的编辑,如果我朝着正确的方向前进,请告诉我。
标签: python class numpy attributes