Cython中def,cdef,cpdef的区别

这是我的第一篇翻译,希望大家多多给出意见和建议。
如有转载,请注明出处。
原文来自:https://stackoverflow.com/questions/28362009/definition-of-def-cdef-and-cpdef-in-cython

问题

我想知道在我声明一个函数时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代码的那些项目。

更多拓展的信息我还是建议你去看官方的文档。
http://docs.cython.org/src/reference/language_basics.html

回答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 函数具有 cdefdef 函数的限制。

什么时候使用 cdefcpdef 函数?

一旦函数被调用,那么 cdef 和 def 函数内部代码的运行速度没有区别。
因此我们仅在以下条件下使用 cdef 函数:

  1. 需要传递非Python类型
  2. 需要传递它作为一个函数指针到C
  3. 需要经常调用(加速函数调用很重要)而且不需要从Python调用

使用 cpdef 函数的条件:

  1. 需要经常调用(所以使用加速函数调用很重要)而且需要从Python调用

转载于:https://www.cnblogs.com/lidyan/p/7474244.html

### Cython 使用及其相关头文件 Cython 是一种编程语言,它旨在提高 Python 的执行速度并允许轻松编写 C 扩展模块。通过将 Python 代码转换成高效的 C 或 C++ 代码来实现这一点[^1]。 #### 安装 Cython 为了使用 Cython,首先需要安装该工具包。可以通过 pip 来完成这一操作: ```bash pip install cython ``` #### 基本语法与特性 当编写 Cython 文件时(通常具有 .pyx 后缀),可以混合使用 Python 和 C 类型声明。这使得能够定义静态类型的变量、函数参数以及返回值,从而获得接近原生的速度性能提升。 例如,下面是一个简单的 Cython 函数用于计算两个整数之和: ```cython def add(int a, int b): return a + b ``` 此代码片段展示了如何利用 `int` 关键字指定输入参数的数据类型为整数,并且自动推断出返回的结果也是相同类型。 #### 头文件支持 对于更复杂的项目来说,可能还需要引入外部库中的结构体或其他组件。这时就可以借助于 `.pxd` 文件作为接口描述符;这些文件包含了只读属性、常量以及其他可以在多个地方共享的信息。另外还可以包含来自标准 C 库或者其他第三方资源的头文件,以便访问特定功能或数据结构[^2]。 假设要调用 POSIX 系统 API 中 fork() 方法,则可在相应的 pxd 文件内加入如下语句: ```cython from libc.stdlib cimport system cdef extern from "<unistd.h>": pid_t fork() ``` 上述例子说明了怎样把 Unix/Linux 下创建子进程所需的命令封装到 Cython 模块当中去。 #### 编译过程概述 一旦完成了源代码撰写之后,下一步就是将其编译为目标平台上的二进制形式。一般情况下会采用 distutils 工具集来进行这项工作——只需准备 setup.py 脚本来指导整个构建流程即可[^3]。 setup.py 示例: ```python from setuptools import Extension, setup from Cython.Build import cythonize extensions = [ Extension( name="example", sources=["example.pyx"], libraries=[], include_dirs=[] ) ] setup(ext_modules=cythonize(extensions)) ``` 这段脚本指定了待处理的目标文件名 (`example`) 及其位置 (`example.pyx`) ,同时也为空列表留出了空间供日后添加额外依赖项所用。 #### 性能优化技巧 除了基本的功能外,Cython 还提供了多种手段帮助开发者进一步挖掘程序潜力。比如启用 boundscheck=False 参数可关闭数组越界检测机制以减少开销;而 wraparound=False 则阻止负索引运算的发生,这两者结合起来往往能在循环密集型算法上带来显著改进效果[^4]。 ```cython @cython.boundscheck(False) # Remove bounds checking. @cython.wraparound(False) # Remove negative index wrapping. cpdef double compute_sum(double[:] array): cdef Py_ssize_t i, n = array.shape[0] cdef double total = 0.0 for i in range(n): total += array[i] return total ``` 以上代码段显示了一个经过高度优化后的数值累加器版本,其中禁用了不必要的安全措施,使运行效率更高。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值