[英]using iterator in cython
I am trying to learn cython and I modified the example found here . 我正在尝试学习cython,并修改了此处找到的示例。
#pyx file
import numpy as np
cimport numpy as np
import cython
np.import_array()
def test1(a):
out = np.empty(a.shape, np.double)
cdef np.flatiter ita = np.PyArray_IterNew(a)
cdef np.flatiter ito = np.PyArray_IterNew(out)
cdef double value
cdef double i
i = 0.0
while np.PyArray_ITER_NOTDONE(ita):
value = (<double*>np.PyArray_ITER_DATA(ita))[0]
print(ita) # for debugging
print(value,i) # for debugging
value = value + i
(<double*>np.PyArray_ITER_DATA(ito))[0] = value
i += 1.0
np.PyArray_ITER_NEXT(ita)
np.PyArray_ITER_NEXT(ito)
return out
So I expect the function to add each element of the input array by i
, where the value of i
increases by one each time the iterator passes to the next element. 因此,我期望函数将输入数组的每个元素加
i
,其中,每当迭代器传递到下一个元素时, i
的值就会增加一个。 When I run the function with a=np.arange(10)
, the print statement shows something like: 当我使用
a=np.arange(10)
运行该函数时,print语句显示如下内容:
(2.121995791e-314, 0.0)
(<numpy.flatiter object at 0x0000024A2CE27B20>)
(4.2439915824e-314, 1.0)
(<numpy.flatiter object at 0x0000024A2CE27B20>)
(6.365987374e-314, 2.0)
(<numpy.flatiter object at 0x0000024A2CE27B20>)
(8.4879831653e-314, 3.0)
(<numpy.flatiter object at 0x0000024A2CE27B20>)
# rest not shown here
which isn't what I expect as it seems that the iterator is still pointing to the same element of the array, and the value returned by value
is essentially zero, but not the values of a
(number 0-9). 这不是我期望的,因为迭代器似乎仍指向数组的同一元素,并且value所返回的
value
本质上为零,而不是a
(数字0-9)的值。 But the iterator does seem to stop at the end as the function terminates successfully and the returned array has the same shape as a
. 但是,迭代器似乎停止在最后作为函数成功终止并返回的数组具有相同的形状作为
a
。
So my question is: 所以我的问题是:
What does the line value = (<double*>np.PyArray_ITER_DATA(ita))[0]
actually mean? 行
value = (<double*>np.PyArray_ITER_DATA(ita))[0]
实际含义是什么? <double*>
declares the pointer type? <double*>
声明指针类型? np.PyArray_ITER_DATA
is just what the API says. API所说的就是
np.PyArray_ITER_DATA
。 Then what about [0]
? 那
[0]
呢?
What did I get wrong and how to modify the code? 我怎么了?怎么修改代码? If
a=np.arange(2,8)
, then test1(a)
should give array([ 2, 4, 6, 8, 10, 12])
. 如果
a=np.arange(2,8)
,则test1(a)
应该给出array([ 2, 4, 6, 8, 10, 12])
a=np.arange(2,8)
array([ 2, 4, 6, 8, 10, 12])
。
The problem was that arange
gives you an int
array by default, which you're then interpreting as if it was a double
array (small integers misinterpreted as doubles are often around 1e-300 ish, so this is usually a good clue). 问题在于,默认情况下,
arange
会为您提供一个int
数组,然后您将其解释为一个double
精度数组(被误解为双精度的小整数通常在1e-300 ish左右,因此通常是个很好的线索)。 Ideally you should make sure you check the dtype
in the function. 理想情况下,您应确保检查函数中的
dtype
。
To answer your further questions: 要回答您的其他问题:
print(ita)
is printing the address of the iterator object, not the data it's currently accessing. print(ita)
正在打印迭代器对象的地址,而不是其当前正在访问的数据。 Therefore it always shows the same address. 因此,它始终显示相同的地址。
np.PyArray_ITER_DATA(ita)
gets a pointer to the address of the current bit of data. np.PyArray_ITER_DATA(ita)
获取一个指向当前数据位地址的指针。 Since it's designed as a generic interface for any numpy array we don't know the type so it's a void*
. 由于它被设计为任何numpy数组的通用接口,我们不知道类型,所以它是
void*
。 <double*>
is you telling Cython that this pointer actually points to a double
. <double*>
是要告诉Cython该指针实际上指向double
。 [0]
looks up the value stored at that pointer [0]
查找该指针处存储的值
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.