python – 子类化numpy.ma.MaskedArray

我正在尝试将numpy的MaskedArray子类化为添加属性,但似乎无法获得正确的结果.

我开始遵循the example为子类化numpy.ndarray,这很好.

然后我尝试子类化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.ma.MaskedArray(input_array).view(cls)或obj = np.ma.MaskedArray .__ new __(cls,input_array)替换行obj = np.asarray(input_array).view(cls)解决这个问题(我这样做了,因为我想在未来的子类化身中将* args和** kwargs传递给__new__.)

请注意,我还必须在子类’__array_finalize__中添加对MaskedArray .__ array_finalize的调用,与ndarray子类的示例相反;如果我不这样做,则找不到_mask属性.

也许有人可以启发我:

>如何获取obj [1:].info以保留原始的obj.info
>为什么ndarray不需要__array_finalize__的超类调用,但MaskedArray确实需要(更多的是红利问题).

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

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

最佳答案 为了让切片按照您的意愿工作,您可能需要重载__getitem__:

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

同上__setitem__.

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

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参数).有关子类化的更多信息,请查看此link.

在您的示例中,您使用自己的__array_finalize__来设置.info属性.在这种情况下,你必须调用父方法MaskedArray .__ array_finalize__,它是基本的Python子类.请注意,如果你采用_optinfo方式,则不必显式定义__array_finalize__ …

注意

> __array_prepare__和__array_wrap__方法实际上用于在向函数应用函数之前准备ndarray子类的实例并处理函数的结果

点赞