我正在努力子类化我自己的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的子类,因此在B的 new 方法> init 方法。因此,为了解决这个问题,我假设B还需要一个适当处理附加参数的 new 方法。
我的猜测是这样的:
def __new__(cls,data,name):
obj = A(data)
obj.name = name
return obj
应该这样做,但是如何更改obj的类?
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类。为什么呢?
我对发生了什么感到困惑,如果有人能够解释,我会非常感激。
答案 0 :(得分:4)
对于案例1 ,最简单的方法是:
class B(A):
def __new__(cls,data,name):
obj = A.__new__(cls, data)
obj.name = name
return obj
__new__
实际上是一个静态方法,它将类作为第一个参数而不是类方法,因此您可以直接使用要创建实例的类来调用它。
对于案例2 ,view
无法就地工作,您需要将结果分配给某些内容,最简单的方法是:
class B(A):
def __new__(cls,data):
obj = A(data)
return obj.view(cls)
此外,您__array_finalize__
和A
中的B
定义相同(可能只是一个错字) - 您不需要这样做。