一种常见的算法要求是能够遍历多维数组中的所有元素。数组迭代器对象使这种方法易于以通用方式完成,适用于任何维度的数组。当然,如果您知道要使用的维数,那么您始终可以编写嵌套for循环来完成迭代。但是,如果要编写适用于任意数量维度的代码,则可以使用数组迭代器。访问数组的.flat属性时返回数组迭代器对象。
基本用法是调用PyArray_IterNew
(array),其中array是ndarray对象(或其子类之一)。返回的对象是一个array-iterator对象(由ndarray的.flat属性返回的同一对象)。此对象通常强制转换为PyArrayIterObject *,以便可以访问其成员。所需的唯一成员iter->size包含数组的总大小iter->index,其中包含数组的当前1-d索引,以及iter->dataptr指向数组当前元素的数据的指针。有时,访问iter->ao哪个是指向底层ndarray对象的指针也很有用。
在数组的当前元素处理数据之后,可以使用macro PyArray_ITER_NEXT
(iter)获取数组的下一个元素
。迭代总是以C风格的连续方式进行(最后一个索引变化最快)。的
PyArray_ITER_GOTO (iter,destination)可以用来跳到一个特定点的数组,其中在destination是npy_intp数据类型与空间的数组,以处理潜在的数组中的维度中的至少数。有时使用PyArray_ITER_GOTO1D
(iter,index)将跳转到由值给出的1-d索引是有用的index。但是,最常见的用法在以下示例中给出。
PyObject *obj; /* assumed to be some ndarray object */
PyArrayIterObject *iter;
...
iter = (PyArrayIterObject *)PyArray_IterNew(obj);
if (iter == NULL) goto fail; /* Assume fail has clean-up code */
while (iter->index < iter->size) {
/* do something with the data at it->dataptr */
PyArray_ITER_NEXT(it);
}
…
您还可以使用PyArrayIter_Check
(obj)来确保您拥有迭代器对象和PyArray_ITER_RESET
(iter)以将迭代器对象重置回数组的开头。
在这一点上应该强调的是,如果你的数组已经是连续的,你可能不需要数组迭代器(使用数组迭代器可以工作,但会比你写的最快的代码慢)。数组迭代器的主要目的是使用任意步长将迭代封装在N维数组上。它们在NumPy源代码本身的许多地方使用。如果您已经知道您的数组是连续的(Fortran或C),那么只需将元素大小添加到正在运行的指针变量就可以非常有效地引导您完成数组。换句话说,在连续的情况下(假设为双精度),这样的代码可能会更快。
npy_intp size;
double *dptr; /* could make this any variable type */
size = PyArray_SIZE(obj);
dptr = PyArray_DATA(obj);
while(size--) {
/* do something with the data at dptr */
dptr++;
}
迭代除一个轴之外的所有轴
一种常见的算法是循环遍历数组的所有元素,并通过发出函数调用对每个元素执行一些函数。由于函数调用可能非常耗时,因此加速此类算法的一种方法是编写函数,使其获取数据向量,然后编写迭代,以便一次对整个数据维度执行函数调用。这增加了每个函数调用完成的工作量,从而将函数调用开头减少到总时间的一小部分。即使在没有函数调用的情况下执行循环的内部,在具有最大数量元素的维度上执行内循环也是有利的,以利用在使用流水线操作来增强基础操作的微处理器上可用的速度增强。
的PyArray_IterAllButAxis
(array,&dim)构造被修改,使得它不会在由暗淡指示的尺寸迭代的迭代器对象。这个迭代器对象的唯一限制是不能使用PyArray_Iter_GOTO1D(it,ind)宏(因此,如果将此对象传递回Python,则平面索引将不起作用 - 所以你不应该这样做)。请注意,此例程中返回的对象仍然通常转换为PyArrayIterObject *。所做的就是修改返回迭代器的步幅和尺寸,以模拟迭代数组[…,0,…],其中0放在
维度上。如果dim为负,则找到并使用具有最大轴的尺寸。
更多请见:http://www.mark-to-win.com/tutorial/52200.html