我正在努力对我的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
运行这段代码会得到如下输出:
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的子类,因此在调用B的init方法之前会调用A的new方法。因此,为了修复这个问题,我认为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的类。为什么会这样呢?
我很困惑,如果有人能够解释一下,我将不胜感激。
super(B, cls).__new__
而不是A.__new__
,但是这是相当标准的。你也可以更改A
以处理可变数量的参数或类似的内容,但这可能超出了这个问题的范围。 - agf