3

我正在尝试创建numpy.ndarray. 它非常简单,只是一个带有一些额外属性和操作这些属性的方法的 numpy 数组。在大多数情况下,它工作正常,但是在使用像np.sum.

首先,我已经阅读了Subclassing ndarrayZero-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'>

我对此很好,除了两个问题:

  1. 这是做这种特殊情况的正确地方吗?对于普通的 numpy 数组,我无法弄清楚这种转换发生在哪里,所以我不知道它应该发生在我的派生类的哪里。

  2. 这足以让我的子类工作,还是我会继续遇到兼容性问题。我应该放弃子类化的想法ndarray吗?

这里的目标是与常规 numpy 数组 100% 兼容。可以并且预期某些操作会丢失派生类型信息并返回ndarray基类。我对此很好,我只是无法编写代码来操作ndarray's break。

4

0 回答 0