子类化ndarray相对简单,但与其他Python对象相比,它有一些复杂性。在这个页面上,我们解释了允许你子类化ndarray的机制,以及实现子类的含义。
ndarray的子类化很复杂,因为ndarray类的新实例可以以三种不同的方式出现。这些是:
最后两个是ndarrays的特性 - 为了支持数组切片之类的东西。子类化ndarray的复杂性是由于numpy必须支持后两种实例创建路径的机制。
视图投影 是标准的ndarray机制,通过它您可以获取任何子类的ndarray,并将该数组的视图作为另一个(指定的)子类返回:
>>> import numpy as np>>> # create a completely useless ndarray subclass>>> class C(np.ndarray): pass>>> # create a standard ndarray>>> arr = np.zeros((3,))>>> # take a view of it, as our useless subclass>>> c_arr = arr.view(C)>>> type(c_arr)
当numpy发现它需要从模板实例创建新实例时,ndarray子类的新实例也可以通过与视图投影非常相似的机制来实现。
这个情况的最明显的时候是你正为子类数组切片的时候。例如:
>>> v = c_arr[1:]>>> type(v) # the view is of type 'C'>>> v is c_arr # but it's a new instanceFalse
切片是原始 c_arr 数据的 视图 。因此,当我们从ndarray中获取视图时,我们返回一个同一类的新ndarray,它指向原始数据。
在使用ndarrays时还有其它要点,我们需要这样的视图,例如复制数组(c_arr.copy()),创建ufunc输出数组(参见__array_wrap__用于ufuncs和其他函数),
以及减少方法(如c_arr.mean()。
这些路径都使用相同的机器。我们在这里进行区分,因为它们会为您的方法带来不同的输入。具体来说,
视图投影意味着您已从ndarray的任何潜在子类创建了数组类型的新实例。
从模板创建意味着您已从预先存在的实例创建了类的新实例,例如,允许您跨特定于您的子类的属性进行复制。
如果我们将 ndarray 子类化,我们不仅需要处理数组类型的显式构造,还需要处理视图投影或
从模板创建。NumPy有这样的机制,这种机制使子类化略微不标准。
ndarray用于支持视图和子类中的从模板创建的机制有两个方面。
第一种是使用该ndarray.__new__方法进行对象初始化的主要工作,而不是更常用的__init__
方法。第二个是使用该__array_finalize__方法在模板创建视图和新实例后允许子类清理。
__new__是一个标准的Python方法,如果存在,__init__在我们创建类实例之前调用它。
有关更多详细信息,请参阅python __new__ 文档
。
例如,请考虑以下Python代码:
。。。。。。。。。。。。。
作者:柯广
篇幅有限更多请见扩展链接:http://www.mark-to-win.com/tutorial/52207.html
留言与评论(共有 0 条评论) “” |