ndarray按需更新其数据

时间:2013-10-13 11:27:53

标签: python arrays numpy

我想有一个系统,我有一个"数据类"有一些数组和一个"选择类"具有相同的数组名称,其数据仅仅是来自Data类的数组子集的视图。哪些应该由选择类的实例确定。如果在Selection类的实例中改变某些东西,它应该被映射回相应的Data类并使事情变得非常困难,不仅应该选择类中的数组是真正的ndarrays(因此方法应该工作),它们也应该只是原始数据的视图或仅按需创建。

我到目前为止创建的脚手架是

import numpy as np

class DataObj():
    def __init__( self, Data_dict ):
        self.arrays = [ n for n,d in Data_dict.iteritems() ]
        for n,d in Data_dict.iteritems():
            setattr( self, n, d )

class Darray(np.ndarray):
    def __new__(cls, input_array, SelObj, *args, **kwargs):
        obj = np.asarray(input_array[ SelObj.selA, SelObj.selB ]).view(cls)
        obj.SelObj = SelObj
        return obj

    def __array_finalize__(self, obj):
        if obj is None: return  

    def __getitem__(self, index):
        return super(Darray, self).__getitem__(index)      


class SelObj():
    def __init__(self, DataObj, selA, selB):
        self.selA = selA
        self.selB = selB
        self.DataObj = DataObj

        for n in DataObj.arrays:
            Darr = Darray( getattr( self.DataObj, n), self )
            setattr( self, n, Darr )

### creating some objects
DObj  = DataObj({ "X":ones((10,20)),
                  "Y":zeros((10,20)),
                  "Z":arange(10*20).reshape(10,20) })

SObj1 = SelObj( DObj, array([1,3,4]), slice(None,None,2) )
SObj2 = SelObj( DObj, array([4,5,7]), slice(None,2,None) )
SObj3 = SelObj( DObj, array([1,3,4]), slice(None)        )

这有效,但现在如果做了

SObj1.X = 10

它失去了连接,只有一个10而不是原始数组。即使我做了一些真正有意义的事情,比如

SObj1.X[0,0] = 10.

这不会出现在DObj中(因为input_array[ SelObj.selA, SelObj.selB ]我创建了数组的副本)。 Ans现在每个SObj都会拥有自己的数据,最终会堵塞内存。

我知道我想要的东西并不容易,但我仍然愿意这样做。我也在研究房产,让每一个Darray成为SObj的财产;每当调用属性时按需执行切片。然而,像

这样的事情
SObj1.X[0,0] = 10.

将不再起作用,因为该属性已经切片,并且不再映射回另一个切片。

我会非常感谢能够指出这种结构解决方案的任何提示。

大卫

1 个答案:

答案 0 :(得分:0)

如果你想要一个像

这样的表达式
SObj1.X = 10

要更改某些远程来源的值,您应该覆盖__setattr__课程中的SelObj方法。像这样:

class SelObj():
    def __init__(self, DataObj, selA, selB):
        self.selA = selA
        self.selB = selB
        self.DataObj = DataObj

        for n in DataObj.arrays:
            Darr = Darray( getattr( self.DataObj, n), self )
            setattr( self, n, Darr )

    def __setattr__(self, name, value):
        setattr(self.DataObj, name, value) # updates the source of the data
        super(SelObj, self).__setattr__(name, value) # updates the representation