问题描述
我正在努力继承我自己的numpy.ndarray的子类.我真的不明白问题是什么,而是希望有人解释在以下情况下出了什么问题以及如何去做我想做的事情.
I'm struggling to subclass my own subclass of numpy.ndarray. I don't really understand what the problem is and would like someone to explain what goes wrong in the following cases and how to do what I'm trying to do.
我有一个numpy.ndarry的子类,它的行为与我想要的一样(以下代码中的A类).我想将A子类化(下面的代码中的B类),以便B包含其他信息(名称)和方法(修饰的.simple_data方法).
I have a subclass of numpy.ndarry that behaves as I want (class A in the code below). I want to subclass A (class B in the code below) so that B contains additional information (name) and methods (the decorated .simple_data method).
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
运行此代码将产生输出:
Running this code produces the output:
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的构造中的名称"变量有关,并且由于A是numpy.array的子类,因此在B的 new 方法> init 方法.因此,为了解决这个问题,我假设B也需要一个 new 方法,该方法可以适当地处理其他参数.
I assume that this is related to the 'name' variable in the construction of B and that due to A being a subclass of numpy.array, A's new method is being called before B's init method. Thus to fix this I assume that B also needs a new method that appropriately handles the additional argument.
我的猜测是这样的:
def __new__(cls,data,name):
obj = A(data)
obj.name = name
return obj
应该这样做,但是如何更改obj的类?
should do it, but how do I change the class of 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的类.为什么?
I assume that the call to view() in B.new() is somehow not correctly setting the class of obj. Why?
我对正在发生的事情感到困惑,如果有人可以解释我将不胜感激.
I'm confused as to what is going on and would be very grateful if someone could explain it.
推荐答案
对于案例1 ,最简单的方法是:
For Case 1, the simplest way is:
class B(A):
def __new__(cls,data,name):
obj = A.__new__(cls, data)
obj.name = name
return obj
__new__
实际上是一个静态方法,该方法将类作为第一个参数,而不是类方法,因此您可以直接使用要创建实例的类来调用它.
__new__
is actually a static method that takes a class as the first argument, not a class method, so you can call it directly with the class of which you want to create an instance.
对于第2种情况,view
不能就地工作,您需要将结果分配给某些对象,最简单的方法是:
For Case 2, view
doesn't work in-place, you need to assign the result to something, the simplest way is:
class B(A):
def __new__(cls,data):
obj = A(data)
return obj.view(cls)
此外,您已经在A
和B
中定义了相同的__array_finalize__
(可能只是一个错字)-您不需要这样做.
Also, you've got __array_finalize__
defined the same in A
and B
there (probably just a typo) -- you don't need to do that.
这篇关于如何子类化numpy.ndarray的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!