Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 当对ndarray进行子类化时,为什么转置发生在_数组u finalize _uu之后而不是之前?_Python_Numpy_Subclassing - Fatal编程技术网

Python 当对ndarray进行子类化时,为什么转置发生在_数组u finalize _uu之后而不是之前?

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

为了简单起见,让我们从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__(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
找到确切的日期),而当前版本似乎是一个简单的解决方案。