我正在尝试将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.asarray(input_array).view(cls)
或obj = np.ma.MaskedArray(input_array).view(cls)
替换行obj = np.ma.MaskedArray.__new__(cls, input_array)
并没有解决问题(我这样做了,因为我想传递*args
和{{在未来的子类化身中,1}}到**kwargs
。)
请注意,我还必须在我的子类“__new__
中添加对MaskedArray.__array_finalize
的调用,而不是__array_finalize__
子类的示例;如果我不这样做,则找不到ndarray
属性。
也许有人可以启发我:
如何让_mask
保留原始obj[1:].info
为什么obj.info
不需要ndarray
的超级电话,但是__array_finalize__
会更多(更多的是奖金问题)。
我想继承MaskedArray
而不是编写容器类,因为后者会失去MaskedArray
附带的一些便利。
(注意:这与this question不同,因为我已“解决”了MaskedArray
/ __init__
问题。)
答案 0 :(得分: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
参数)。有关子类化的更多信息,请查看此link。
在您的示例中,您使用自己的__array_finalize__
来设置.info
属性。在这种情况下,您必须调用父方法MaskedArray.__array_finalize__
,它是基本的Python子类。请注意,如果您采用__array_finalize__
方式...
_optinfo
注意强>
__array_prepare__
和__array_wrap__
方法实际上用于在向函数应用函数之前准备ndarray
子类的实例并处理函数的结果