如何子类化numpy.ndarray的子​​类

Ben*_*ale 6 python numpy subclassing

我正在努力子类化我自己的numpy.ndarray子类.我真的不明白问题是什么,并希望有人解释在下列情况下出了什么问题,以及如何做我正在尝试做的事情.

我想要实现的目标:

我有一个numpy.ndarry的子类,其行为符合我的要求(下面的代码中的A类).我想子类A(下面的代码中的B类),以便B包含其他信息(名称)和方法(装饰的.simple_data方法).

情况1:

import numpy as np

class A(np.ndarray):

    def __new__(cls,data):
        obj = np.asarray(data).view(cls)
        return obj

    def __array_finalize(self,obj):
        if obj is None: return

class B(A):

    def __init__(self,data,name):
        super(B,self).__init__(data)
        self.name = name

    @property
    def simple_data(self):
        return [data[0,:],data[:,0]]

if __name__ == '__main__':
    data = np.arange(20).reshape((4,5))
    b = B(data,'B')
    print type(b)
    print b.simple_data
Run Code Online (Sandbox Code Playgroud)

运行此代码会生成输出:

Traceback (most recent call last):
  File "ndsubclass.py", line 24, in <module>
    b = B(data,'B')
TypeError: __new__() takes exactly 2 arguments (3 given)
Run Code Online (Sandbox Code Playgroud)

我假设这与B的构造中的'name'变量有关,并且由于A是numpy.array的子​​类,因此在B的init方法之前调用A的方法.因此,为了解决这个问题,我假设B还需要一个适当处理附加参数的方法.

我的猜测是这样的:

def __new__(cls,data,name):
    obj = A(data)
    obj.name = name
    return obj
Run Code Online (Sandbox Code Playgroud)

应该这样做,但我如何改变obj的类?

案例2:

import numpy as np

class A(np.ndarray):

    def __new__(cls,data):
        obj = np.asarray(data).view(cls)
        return obj

    def __array_finalize__(self,obj):
        if obj is None: return

class B(A):

    def __new__(cls,data):
        obj = A(data)
        obj.view(cls)
        return obj

    def __array_finalize__(self,obj):
        if obj is None: return

    @property
    def simple_data(self):
        return [self[0,:],self[:,0]]

if __name__ == '__main__':
    data = np.arange(20).reshape((4,5))
    b = B(data)
    print type(b)
    print b.simple_data()
Run Code Online (Sandbox Code Playgroud)

运行时输出为:

<class '__main__.A'>
Traceback (most recent call last):
  File "ndsubclass.py", line 30, in <module>
    print b.simple_data()
AttributeError: 'A' object has no attribute 'simple_data'
Run Code Online (Sandbox Code Playgroud)

这让我感到惊讶,因为我期待:

<class '__main__.B'>
[array([0, 1, 2, 3, 4]), array([ 0,  5, 10, 15])]
Run Code Online (Sandbox Code Playgroud)

我假设对B. new()中的view()的调用在某种程度上没有正确设置obj的类.为什么?

我对发生了什么很困惑,如果有人能够解释,我会非常感激.

agf*_*agf 4

对于情况1,最简单的方法是:

class B(A):
    def __new__(cls,data,name):
        obj = A.__new__(cls, data)
        obj.name = name
        return obj
Run Code Online (Sandbox Code Playgroud)

__new__实际上是一个静态方法,它以类作为第一个参数,而不是类方法,因此您可以直接使用要创建实例的类来调用它。

对于情况 2view不能就地工作,您需要将结果分配给某些东西,最简单的方法是:

class B(A):
    def __new__(cls,data):
        obj = A(data)
        return obj.view(cls)
Run Code Online (Sandbox Code Playgroud)

另外,你已经在其中__array_finalize__定义了相同的内容(可能只是一个拼写错误)——你不需要这样做。AB