Python惰性求值numpy ndarray

Python惰性求值numpy ndarray,python,arrays,numpy,multidimensional-array,lazy-evaluation,Python,Arrays,Numpy,Multidimensional Array,Lazy Evaluation,我有一个大的2D数组,我只想声明一次,偶尔根据参数只更改一些值,而不遍历整个数组 为了构建这个数组,我用dtype=object对numpy-ndarray类进行了子类化,并将其分配给我想要更改函数的元素,例如: def f(parameter): return parameter**2 for i in range(np.shape(A)[0]): A[i,i]=f for j in range(np.shape(A)[0]): A[i,j]=1.

我有一个大的2D数组,我只想声明一次,偶尔根据参数只更改一些值,而不遍历整个数组

为了构建这个数组,我用
dtype=object
对numpy-ndarray类进行了子类化,并将其分配给我想要更改函数的元素,例如:

def f(parameter):
     return parameter**2

for i in range(np.shape(A)[0]):
    A[i,i]=f
    for j in range(np.shape(A)[0]):
        A[i,j]=1.
然后,我重写了
\uuuu getitem\uuuu
方法,这样,如果函数是可调用的,它将返回具有给定参数的函数的求值,否则将返回值本身

    def __getitem__(self, key):
        value = super(numpy.ndarray, self).__getitem__(key)
        if callable(value):
            return value(*self.args)
        else:
            return value
其中,
self.args
先前被赋予myclass的实例

然而,最后我需要使用浮点数组,我不能简单地用这种技术将这个数组转换成
dtype=float
数组。我还尝试使用numpy视图,这对
dtype=object
也不起作用

你有更好的选择吗?我应该重写view方法而不是getitem吗


编辑我将来可能不得不使用Cython,因此如果您有一个涉及C指针的解决方案,我很感兴趣。

在这种情况下,将转换函数绑定到数组的每个索引是没有意义的

相反,更有效的方法是将转换定义为一个函数,以及它所应用的数组的子集。这是一个基本的实现

import numpy as np

class LazyEvaluation(object):
    def __init__(self):
        self.transforms = []

    def add_transform(self, function, selection=slice(None), args={}):
        self.transforms.append( (function, selection, args))

    def __call__(self, x):
        y = x.copy() 
        for function, selection, args in self.transforms:
            y[selection] = function(y[selection], **args)
        return y
可按如下方式使用:

x = np.ones((6, 6))*2

le = LazyEvaluation()
le.add_transform(lambda x: 0, [[3], [0]]) # equivalent to x[3,0]
le.add_transform(lambda x: x**2, (slice(4), slice(4,6)))  # equivalent to x[4,4:6]
le.add_transform(lambda x: -1,  np.diag_indices(x.shape[0], x.ndim), ) # setting the diagonal 
result =  le(x)
print(result)
它打印

array([[-1.,  2.,  2.,  2.,  4.,  4.],
       [ 2., -1.,  2.,  2.,  4.,  4.],
       [ 2.,  2., -1.,  2.,  4.,  4.],
       [ 0.,  2.,  2., -1.,  4.,  4.],
       [ 2.,  2.,  2.,  2., -1.,  2.],
       [ 2.,  2.,  2.,  2.,  2., -1.]])

通过这种方式,您可以轻松地支持所有高级Numpy索引(元素对元素的访问、切片、奇特的索引等),同时使用本机数据类型(
float
int
)将数据保存在数组中,这比使用
dtype='object'
效率要高得多。这是一种有趣的方法,但我不确定numpy阵列是否适合它。通常,在使用numpy时,您将使用使用完整数组或切片的矢量化操作,而不是逐元素访问。子类化ndarray的方式实际上会失去快速numpy操作的所有优势。您最好从零开始创建自己的类,并将所有内容保存到纯python结构(列表等)中。就性能而言,它将具有可比性。为什么你真的需要懒惰的评估?您只能使用奇特的索引有效地更改某些元素。您是否只有一个函数
f
?使用常量参数?您熟悉
scipy.sparse
dok
格式是一个字典,以
(i,j)
元组作为键。这和
lil
(列表列表)是访问/更改所选项目的两种最快方法。@hpaulj:dok非常有趣。但是,我不能将它与dtype=object一起使用,正如我在上面展示的示例中所示:@rth:我需要延迟求值,而不是使用key访问数组(甚至是高效地),原因是每个假装可能与不同类型的索引相关。对于上面的示例,我只将对角线设置为变量。例如,我也可以将一行(或更复杂的smth)影响到另一个函数g。多亏了,我基本上是作为dict的子类实现的,它的工作方式与我想要的差不多。然而,出于好奇,我想知道是否有可能以更优雅的方式用指针在C/C++中实现类似的东西?例如,可以声明一个由(浮点)指针组成的表,在声明时,每个指针将指向零或函数的结果,这样我就可以通过调用一个(或多个)函数来更新矩阵。但要做到这一点,函数的reach调用必须绑定到一个特定的指针,我不确定这是否可行。我希望我说得够清楚了。