我正在尝试将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子类的实例并处理函数的结果