【问题标题】:How to subclass a subclass of numpy.ndarray如何子类化 numpy.ndarray 的子类
【发布时间】:2011-09-08 02:52:35
【问题描述】:

我正在努力继承我自己的 numpy.ndarray 子类。我真的不明白问题出在哪里,希望有人解释在以下情况下出了什么问题以及如何做我想做的事情。

我想要达到的目标:

我有一个 numpy.ndarry 的子类,它的行为如我所愿(下面代码中的 A 类)。我想继承 A(下面代码中的 B 类),以便 B 包含附加信息(名称)和方法(装饰的 .simple_data 方法)。

案例一:

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

运行此代码会产生输出:

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

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

我的猜测是这样的:

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

应该可以,但是如何改变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()

运行时输出为:

<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'

这出乎我的意料:

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

我假设 B.new() 中对 view() 的调用以某种方式未正确设置 obj 的类。为什么?

我对发生的事情感到困惑,如果有人能解释一下,我将不胜感激。

【问题讨论】:

    标签: python numpy subclassing


    【解决方案1】:

    对于案例1,最简单的方法是:

    class B(A):
        def __new__(cls,data,name):
            obj = A.__new__(cls, data)
            obj.name = name
            return obj
    

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

    对于案例2view 不能原地工作,你需要将结果赋值给某个东西,最简单的方法是:

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

    另外,您在AB 中定义了相同的__array_finalize__(可能只是一个错字)——您不需要这样做。

    【讨论】:

    • 啊...所以我可以强制 A.__new__ 通过将该类传递给 A.__new__ 来查看将数组数据转换为正确的类。这是pythonic的方式吗?
    • @Ben 我会使用super(B, cls).__new__ 而不是A.__new__,但是是的,这是相当标准的。您还可以更改 A 以便它可以处理可变数量的参数或类似的东西,但这可能超出了这个问题的范围。
    • 太棒了!那么我对上述两种情况的猜测是否正确?
    • 好的...明白了。非常感谢所有的帮助!如果我可以投票给你的答案,我会的。
    猜你喜欢
    • 2014-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-31
    • 1970-01-01
    • 2011-09-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多