如何在Cython中对列表进行切片

3
我有一个Cython的列表,想要对它进行切片操作,而不使用Python对象(以提高速度)。
cdef int len = 100    
cdef int *q
cdef int *r

q = <int *>malloc( len *cython.sizeof(int) )

r = q[50:]

我遇到了这个错误:

r = q[50:]
    ^
------------------------------------------------------------

hello.pyx:24:9: Slicing is not currently supported for 'int *'.

有一种高效的方法来做吗?"... not currently supported..."让我有点担心。我使用的是cython 0.18。

q 不是一个列表,而是一个本地数组。我猜你需要使用更低级别的东西来处理它们。(传递一个数组和起始+结束索引。) - millimoose
@millimoose,我看了一下文档中的memoryview内容,但是我无法将其与我的简单示例配合使用。我对Cython和C编程都很陌生。你说的“低级别”和“传递数组和起始+结束索引”是什么意思?谢谢。 - Jean-Francois Gallant
在C语言中,当你使用数组时,通常不仅使用数组本身,还会使用“起始”和“长度”参数来指示函数应该处理的数组部分。数组和这两个索引一起表示一个“切片”(如果你查看快速排序等示例代码,就会发现这一点)。话虽如此,对于我不是非常熟悉的Cython来说,这可能是过度设计了。 - millimoose
@millimoose,你能告诉我在哪里可以找到快速排序的示例代码吗?这正是我需要切片数组的原因,为了实现KD树的多个qsort(我已经用Python完成了,但需要将其转换为Cython以提高速度)。 - Jean-Francois Gallant
1个回答

3
通过Typed Memoryviews,可以快速切片和实现一些其他很酷的功能。但是为了进行切片,您需要一些有关数组的元数据,因此最好使用数组类型而不是普通指针。查看文档以获取更多信息:http://docs.cython.org/src/userguide/memoryviews.html
对问题的修改如下:
cdef int q_array[5] # c array
cdef int[:] q # 1D memview
cdef int[:] r # another 1D memview

q = q_array # point q to data
r = q[2:] # point r to a slice of q

r[0] = 5 # modify r

# test                                                                      
print q[2]
print r[0]

你仍然可以从切片中创建指针,如果你真的很想要它:
# ...

cdef int* r_ptr
cdef int* q_ptr

r_ptr = &r[0]
q_ptr = &q[0]

print q_ptr[2]
print r_ptr[0]

还可以与numpy数组一起使用:

import numpy as np

cdef int[:] q = np.arange(100).astype('int32') # slow
cdef int[:] r

r = q[50:] # fast slicing

print r[0]

好的,你的例子帮助我更好地理解了memview如何对数组进行切片。但是,当我尝试编译任何带有memview声明的代码时,我会遇到错误。每次我添加像这样的一行:cdef int[:] r - Jean-Francois Gallant
我按照Cython文档中的说明进行编译。使用标准的setup.py,在Windows 7 64位系统上使用gcc(MinGW)。以下是部分错误信息(过长):build\temp.win32-3.3\Release\hello.o:hello.c:(.text+0x1032):未定义对__sync_fetch_and_sub_4'的引用 build\temp.win32-3.3\Release\hello.o:hello.c:(.text+0x21e5):未定义对__sync_fetch_and_add_4'的引用 build\temp.win32-3.3\Release\hello.o:hello.c:(.text+0xa3d0):未定义对`__sync_fetch_and_sub_4'的引用 collect2: ld返回1个执行状态码 错误:命令"gcc"执行失败,退出状态码为1 - Jean-Francois Gallant
嗯...错误可能出现在pyx-> c阶段。当您发出“cython-a hello.pyx”时,是否一切顺利? - dmytro
我在Cython邮件组中发了错误信息,他们认为这可能是Python 3.3的一个bug。因为它似乎在Python 2.7中运行正常。你使用的是哪个版本?我使用的是Python 3.3,Cython 0.18和MinGW GCC 4.6.2。 - Jean-Francois Gallant
哦,我明白了,那很可能是Py3k的问题...我正在Linux下使用Python-2.7,从未尝试过Python 3。 - dmytro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接