Cython中def,cdef,cpdef的区别
问题
我想知道在我声明⼀个函数时def, cdef, cpdef的区别。
def与其他两种的区别还算⼤致清晰。可是有时我见到声明时添加了返回值,有时见到的声明却没有添加返回值。
我还想知道在cython中如何声明⼀个字符串变量,因为我不知道怎么搞,我就按照声明对象的⽅式做了。
回答0
def⽤来在Python中声明⼀个函数。因为Cython是基于C runtime的,所以允许我们使⽤cpdef。
cdef在C语⾔层⾯声明了函数。正如我们所知道的在C语⾔中你必须为每⼀个函数定义返回值的类型。有事函数返回值为void,这就等于Python中的return。
Python是⼀个⾯向对象的语⾔。所以我们还可以在C++层⾯定义类⽅法,并在⼦类中重新。
举个栗⼦~
cdef class A:
cdef foo(self):
print "A"
cdef class B(A)
cdef foo(self, x=None)
print "B", x
cdef class C(B):
cpdef foo(self, x=True, int k=3)
print "C", x, k
总结⼀下,为什么我们要使⽤def, cdef, cpdef呢?因为我们使⽤Cython,你的Python代码在编译之前,会被转换为C代码。鉴于此,我们可以控制会变成C代码的那些项⽬。
回答1
最关键的不同在于 where the function can be called from,def函数可以被Python和Cython调⽤,cdef函数可以被Cython和C调⽤。
这两种类型的函数都是既可以被带类型的变量也可以被不带类型的变量被声明,并且都会被Cython编译为C。
# A Cython class for illustrative purposes
cdef class C:
pass
def f(int arg1, C arg2, arg3):
# takes an integer, a "C" and an untyped generic python object
pass
cdef g(int arg1, C arg2, arg3):
pass
上⾯的栗⼦中,f对Python可见(⼀旦它被imported Cython module中。⽽g不可能被call from Python,它将被翻译成C signature:PyObject* some_name(int, struct __pyx_obj_11name_of_module_C *, PyObject*)
其中的struct __pyx_obj_11name_of_module_C *是我们的 class C 翻译成的 C struct。这就允许我们把它传递给 C 函数,⽐如作为⼀个函数指针。
相对⽽⾔,f就不能轻易的被C调⽤了。
cdef函数的限制
cdef函数不能在我们的函数内定义。这是因为没有⽅法可以存储获取变量在C函数指针,如下代码就是不允许的。
# WON'T WORK!
def g(a):
cdef (int b):
字符串函数怎么获取return a+b
cdef函数不能处理*args*kwargs类型的变量。这主要是因为它们不能轻易的翻译成 C signature。
cdef函数的优势
cdef函数可以接受任何类型的变量,包括哪些Python中没有的类型,⽐如指针。
def函数总是返回⼀个Python对象,所以不能是⼀个具体返回值类型。
cdef int h(int* a):
# specify a return type and take a non-Python compatible argument
return a[0]
cdef函数⽐def函数调⽤更快,因为它们会被翻译成⼀个更加简单的 C 函数调⽤。
cpdef函数
cpdef函数让Cython产⽣⼀个cdef函数(使得从Cython进⾏快速的函数调⽤)和⼀个def函数(使得我们可以从Pyhton调⽤)。就允许的变量类型⽽⾔,cpdef函数具有cdef和def函数的限制。
什么时候使⽤cdef和cpdef函数?
⼀旦函数被调⽤,那么 cdef 和 def 函数内部代码的运⾏速度没有区别。
因此我们仅在以下条件下使⽤ cdef 函数:
1. 需要传递⾮Python类型
2. 需要传递它作为⼀个函数指针到C
3. 需要经常调⽤(加速函数调⽤很重要)⽽且不需要从Python调⽤
使⽤ cpdef 函数的条件:
1. 需要经常调⽤(所以使⽤加速函数调⽤很重要)⽽且需要从Python调⽤
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论