Python 当对ndarray进行子类化时,为什么转置发生在_数组u finalize _uu之后而不是之前?
为了简单起见,让我们从numpy文档复制诊断ndarray子类:Python 当对ndarray进行子类化时,为什么转置发生在_数组u finalize _uu之后而不是之前?,python,numpy,subclassing,Python,Numpy,Subclassing,为了简单起见,让我们从numpy文档复制诊断ndarray子类: import numpy as np class MySubClass(np.ndarray): def __new__(cls, input_array, info=None): obj = np.asarray(input_array).view(cls) obj.info = info return obj def __array_finalize__(s
import numpy as np
class MySubClass(np.ndarray):
def __new__(cls, input_array, info=None):
obj = np.asarray(input_array).view(cls)
obj.info = info
return obj
def __array_finalize__(self, obj):
print('In __array_finalize__:')
print(' self is %s' % repr(self))
print(' obj is %s' % repr(obj))
if obj is None: return
self.info = getattr(obj, 'info', None)
现在让我们做一个简单的例子:
>>> x = MySubClass(np.ones((1,5)))
In __array_finalize__:
self is MySubClass([[1., 1., 1., 1., 1.]])
obj is array([[1., 1., 1., 1., 1.]])
>>> y = x.T
In __array_finalize__:
self is MySubClass([[1., 1., 1., 1., 1.]])
obj is MySubClass([[1., 1., 1., 1., 1.]])
正如我们所看到的,转置被传递到\uuu数组\uu finalize\uu
。除了将“finalize”一词的含义延伸到整个新领域之外,这种行为的目的是什么
发送实际输出,即通过这个钩子进行转置,以便最终确定是否更有意义
用我的子类可能需要的任何后处理来修饰基本转置的推荐方法是什么?这是因为创建新对象时,它们依赖于已经可用的(公共)函数来处理内存分配。的源代码显示,首先从现有阵列创建具有相似形状和步幅的新对象,然后通过访问先前分配的内存来更正这些对象:
/*
* this allocates memory for dimensions and strides (but fills them
* incorrectly), sets up descr, and points data at PyArray_DATA(ap).
*/
Py_INCREF(PyArray_DESCR(ap));
ret = (PyArrayObject *) PyArray_NewFromDescrAndBase(
Py_TYPE(ap), PyArray_DESCR(ap),
n, PyArray_DIMS(ap), NULL, PyArray_DATA(ap),
flags, (PyObject *)ap, (PyObject *)ap);
if (ret == NULL) {
return NULL;
}
/* fix the dimensions and strides of the return-array */
for (i = 0; i < n; i++) {
PyArray_DIMS(ret)[i] = PyArray_DIMS(ap)[permutation[i]];
PyArray_STRIDES(ret)[i] = PyArray_STRIDES(ap)[permutation[i]];
}
/*
*这会为维度和步幅分配内存(但会填充它们)
*不正确),设置descr,并在PyArray_数据(ap)处点数据。
*/
Py_INCREF(PyArray_DESCR(ap));
ret=(PyArrayObject*)PyArray_NewFromDescrAndBase(
Py_类型(ap),Py阵列描述(ap),
n、 PyArray_DIMS(ap),NULL,PyArray_数据(ap),
标志,(PyObject*)ap,(PyObject*)ap);
if(ret==NULL){
返回NULL;
}
/*修复返回数组的尺寸和步长*/
对于(i=0;i
此处
PyArray\u NewFromDescrAndBase
负责,因此该方法接收形状和步幅不正确的版本(即未转置)。可能会有不同的做法,但需要为PyArray\u newfromdscrandbase
提供一个额外的参数,以延迟调用\uuuu array\u finalize\uuu
,然后可以在调整形状和步幅后手动执行。需要明确的是,y
仍然是x
的转置,按预期设置info
。在我自己的测试中,一些方法显然在进行更改之前调用了finalize
(如此转置),但另一些方法显然在创建实例时调用了finalize
(通过new/init
或某种视图
),但一些处理,像转置一样,在后面应用ufunc
显示为创建一个右子类、形状和数据类型的空的,并将其用作输出
,在完成后赋值。谢谢PyArray\u NewFromDescrAndBase
似乎采用了一个dims
和一个strips
参数,因此在调用它之前很容易进行转置,对吧?@PaulPanzer确实,这似乎是一种可能性。但这需要事先分配内存,而当前的解决方案却无法做到这一点。也许没有人考虑过与\uuuu数组\uu finalize\uuuu
的交互(这可能是后来介绍的,尽管我无法使用git gun
找到确切的日期),而当前版本似乎是一个简单的解决方案。