我正在尝试创建numpy.ndarray
. 它非常简单,只是一个带有一些额外属性和操作这些属性的方法的 numpy 数组。在大多数情况下,它工作正常,但是在使用像np.sum
.
首先,我已经阅读了Subclassing ndarray和Zero-Rank Arrays。
似乎当我创建它的子类时,ndarray
它在零秩数组 -> 标量转换方面的行为不同。
在这个例子中,我只使用了最简单的派生类,它实际上并没有做任何事情:
class XArray(np.ndarray):
pass
x = np.eye(2)
y = x.view(type=XArray)
print type(np.sum(x)), type(np.sum(y))
<type 'numpy.float64'> <type '__main__.XArray'>
前者是一个 numpy 标量,后者是我的子类的零秩数组。覆盖__new__
并__array_finalize__
如数组子类化指南中所述不会改变这种行为。
首先,我的问题:这打破了面向对象的特性。 XArray
实例不能在ndarray
不破坏大量代码的情况下透明地替换实例。
我可以通过覆盖__array_wrap__
方法来解决这个问题:
class XArray(np.ndarray):
def __array_wrap__(self, obj):
if len(obj.shape)==0:
return obj[()]
else:
return np.ndarray.__array_wrap__(obj)
a = np.sum(np.eye(2).view(XArray))
print type(a)
<type 'numpy.float64'>
我对此很好,除了两个问题:
这是做这种特殊情况的正确地方吗?对于普通的 numpy 数组,我无法弄清楚这种转换发生在哪里,所以我不知道它应该发生在我的派生类的哪里。
这足以让我的子类工作,还是我会继续遇到兼容性问题。我应该放弃子类化的想法
ndarray
吗?
这里的目标是与常规 numpy 数组 100% 兼容。可以并且预期某些操作会丢失派生类型信息并返回ndarray
基类。我对此很好,我只是无法编写代码来操作ndarray
's break。