创建一个numpy数组子类,使所有形状更改操作返回普通数组
我有一个数组的子类,其中一些额外的属性只对对象的原始形状有效。有没有办法确保所有改变数组形状的操作都返回一个普通的 numpy 数组,而不是我这个类的实例呢?
我已经写了 `array_wrap`,但这似乎对像 np.mean
、np.sum
或 np.rollaxis
这样的操作没有任何影响。这些操作都只是返回了我这个类的实例。
import numpy as np
class NewArrayClass(np.ndarray):
__array_priority__ = 3.0
def __array_wrap__(self, out_arr, context=None):
if out_arr.shape == self.shape:
out = out_arr.view(new_array)
# Do a bunch of class dependant initialization and attribute copying.
# ...
return out
else:
return np.asarray(out_arr)
A = np.arange(10)
A.shape = (5, 2)
A = arr.view(NewArrayClass)
# Would like this to be np.ndarray, but get new_array_class.
print type(np.sum(A, 0))
我想我需要在 __new__
或 __array_finalize__
中做些什么,但我完全不知道该怎么做。
更新:
在仔细阅读了 numpy 关于子类化的文档后(http://docs.scipy.org/doc/numpy/user/basics.subclassing.html),我发现所有改变数组形状的操作都在执行“从模板新建”的操作。所以问题变成了,如何让“从模板新建”的操作返回 ndarray 实例,而不是我这个类的实例。根据我所了解,__new__
在这些函数中从未被调用。
替代方案:
假设上面的事情不可能实现,我至少如何在 __array_finalize__
中识别出“从模板新建”的操作(与视图转换不同)?这至少可以让我解除一些通过引用复制的属性。我也可以设置一个标志,告诉新实例它的形状是无效的。
1 个回答
1
如果你在你的 NewArrayClass
实例中没有添加任何新的成员,你可以重新指定返回实例的 __class__
属性。
A.__class__ = np.ndarray
关键是,为什么你想这么做呢?你在其他地方会进行严格的类型检查吗?其实用“鸭子类型”会更有效。