5

我正在尝试对 numpy 进行子类化MaskedArray以添加属性,但似乎无法获得正确的结果。

我首先按照子类化 a的示例numpy.ndarray开始,它工作正常。

然后我尝试将 a 子类numpy.ma.MaskedArray化,如下所示:

import numpy as np

class MyMaskedArray(np.ma.MaskedArray):

    def __new__(cls, input_array, info=None):
        obj = np.asarray(input_array).view(cls)
        obj.info = info
        return obj

    def __array_finalize__(self, obj):
        if obj is None: return
        self.info = getattr(obj, 'info', None)
        super(MyMaskedArray, self).__array_finalize__(obj)

arr = np.arange(5)
obj = MyMaskedArray(arr, info='information')
print obj.info
print obj[1:].info

这导致

information
None

我曾两次期待“信息”。

obj = np.asarray(input_array).view(cls)obj = np.ma.MaskedArray(input_array).view(cls)或没有解决该问题替换该行obj = np.ma.MaskedArray.__new__(cls, input_array)(我走这条路,因为我想通过*args**kwargs__new__未来的子类化身中传递。)

请注意,与子类的示例相反,我还必须MaskedArray.__array_finalize在我的子类中添加一个调用;如果我不这样做,则找不到该属性。__array_finalize__ndarray_mask

也许有人可以启发我:

  • 如何obj[1:].info保持原件obj.info

  • 为什么ndarray不需要超类调用__array_finalize__,但MaskedArray确实需要(更多的奖励问题)。

我想继承MaskedArray而不是编写容器类,因为后者会失去MaskedArrays 带来的一些便利。

(注意:这与这个问题不同,因为我已经“解决”了__init__/__new__问题。)

4

1 回答 1

2

为了让切片按您的意愿工作,您可能需要重载__getitem__

def __getitem__(self, item):
    out = np.ma.MaskedArray.__getitem__(self, item)
    out.info = self.info
    return out

同上__setitem__

如果您的info属性相对简单,例如在您的示例中,您可能需要查看 的_optinfo属性MaskedArray,该属性是为此目的而设计的:它只是一个存储一些必须以某种方式保存的信息的字典。这是一个例子:

class MyMaskedArray(np.ma.MaskedArray):

    def __new__(cls, input_array, info=None):
        obj = np.asarray(input_array).view(cls)
        obj._optinfo['info'] = info
        return obj

    @property
    def info(self):
        return self._optinfo.get('info', None)

请注意,这里.info是一个只读属性,但使其可写很简单。

关于 __array_finalize__

我不确定我是否理解您的问题:ndarray它本身就是超类。MaskedArray是一个子类,ndarray因此需要定义一个__array_finalize__方法,特别是告诉如何设置掩码(通过_mask参数)。检查此链接以获取有关子类化的更多信息。

在您的示例中,您使用自己的属性__array_finalize__来设置.info属性。在这种情况下,您必须调用父方法MaskedArray.__array_finalize__,它是基本的 Python 子类化。__array_finalize__请注意,如果您走这条路,您不必明确定义_optinfo......

笔记

  • __array_prepare__and__array_wrap__方法实际上用于在将函数应用到子类之前准备子类的实例并ndarray处理函数的结果
于 2013-01-28T23:53:44.133 回答