我正在尝试在cython中实现通用排序算法。因此,我创建了以下模块,该模块在类sorter_t
中实现了Heapsort算法:
# file general_sort_c.pyx
from libc.stdint cimport int32_t
cdef bint bint_true = 1
cdef bint bint_false = 0
cdef class sorter_t:
cdef object sortable_object
def __init__(self,sortable_object):
self.sortable_object = sortable_object
cpdef sort_c(self):
"""
https://en.wikipedia.org/wiki/Heapsort
"""
cdef int32_t end
cdef int32_t count = self.sortable_object.num_elements_int32
self.heapify_c(count)
end = count-1
while end > 0:
self.sortable_object.swap_c(0,end)
end = end - 1
self.siftDown_c(0,end)
cdef heapify_c(self,int32_t count):
cdef int32_t start = (count - 2)/2
while start >= 0:
self.siftDown_c(start, count-1)
start -= 1
cdef siftDown_c(self,int32_t start, int32_t end):
cdef int32_t root = start
cdef int32_t swap
cdef int32_t child
while root * 2 + 1 <= end:
child = root * 2 + 1
swap = root
# if "swap" < "child" then ...
if self.sortable_object.lt_c(swap,child) == 1:
swap = child
if child+1 <= end and self.sortable_object.lt_c(swap,child+1) == 1:
swap = child + 1
if swap != root:
self.sortable_object.swap_c(root,swap)
root = swap
else:
return
当你定义一个sorter_t
类型的对象时,你必须提供一个sortable_object
,它有自己特定的cdef函数lt_c
的实现(用于比较一个元素是否小于另一个元素) )和swap_c
(用于交换元素)。
例如,以下代码将从列表中定义并创建sortable_object
,并将使用sortable_object
测试“sorter_t”的实现。
import numpy
cimport numpy
from libc.stdint cimport int32_t
import general_sort_c
cdef class sortable_t:
cdef public int32_t num_elements_int32
cdef int32_t [:] mv_lista
def __init__(self,int32_t [:] mv_lista):
self.num_elements_int32 = mv_lista.shape[0]
self.mv_lista = mv_lista
cdef public bint lt_c(self, int32_t left, int32_t right):
if self.mv_lista[left] < self.mv_lista[right]:
return 1 # True
else:
return 0 # False
cdef public bint gt_c(self, int32_t left, int32_t right):
if self.mv_lista[left] > self.mv_lista[right]:
return 1 # True
else:
return 0 # False
cdef public swap_c(self, int32_t left, int32_t right):
cdef int32_t tmp
tmp = self.mv_lista[right]
self.mv_lista[right] = self.mv_lista[left]
self.mv_lista[left] = tmp
def probar():
lista = numpy.array([3,4,1,7],dtype=numpy.int32)
cdef int32_t [:] mv_lista = lista
cdef sortable = sortable_t(mv_lista)
cdef sorter = general_sort_c.sorter_t(sortable)
sorter.sort_increasing_c()
print list(lista)
在IPython控制台中编译两个.pyx
文件并运行以下命令后,出现以下错误:
In [1]: import test_general_sort_c as tgs
In [2]: tgs.probar()
...
general_sort_c.sorter_t.siftDown_increasing_c (general_sort_c.c:1452)()
132
133 #if mv_tnet_time[swap] < mv_tnet_time[child]:
--> 134 if self.sortable_object.lt_c(swap,child) == bint_true:
135 swap = child
136
AttributeError: 'test_general_sort_c.sortable_t' object has no attribute 'lt_c'
所以,问题是从模块lt_c
中的代码看不到函数general_sort_c.pyx
的实现。如果我使用lt_c
而不是cpdef
定义函数cdef
,它将起作用,但是你会有很多Python开销。如何以cdef
(“纯C”)方式调用此函数?
答案 0 :(得分:1)
不幸的是,我不确定如何使用融合类型,但其余的很简单:
test_general_sort_c.pyx
需要免费test_general_sort_c.pxd
:
from libc.stdint cimport int32_t
cdef class sortable_t:
cdef public int32_t num_elements_int32
cdef int32_t [:] mv_lista
cdef public bint lt_c(self, int32_t left, int32_t right)
cdef public bint gt_c(self, int32_t left, int32_t right)
cdef public swap_c(self, int32_t left, int32_t right)
general_sort_c.pyx
必须cimport
test_general_sort_c
并输入self.sortable_object
作为test_general_sort_c.sortable_t
。
如果您可以拥有多种受支持的类型,那么这会好得多。不过,我现在还不确定你是怎么做的。
此外,内置True
和False
可以自行正常工作。
如果你更信任Cython,你会发现你可以写
cdef public bint lt_c(self, int32_t left, int32_t right):
return self.mv_lista[left] < self.mv_lista[right]
cdef public bint gt_c(self, int32_t left, int32_t right):
return self.mv_lista[left] > self.mv_lista[right]
cdef public swap_c(self, int32_t left, int32_t right):
self.mv_lista[right], self.mv_lista[left] = self.mv_lista[left], self.mv_lista[right]
好的。 :)