python - cython中def、cdef、cpdef的定义

标签 python declaration cython

我想知道在声明函数时defcdefcpdef 之间的区别。 def 和其他 def 之间的区别或多或少是清楚的。 而且我还看到,有时它会在声明中添加返回类型 (cdef void/double/int... name),有时则不会。

我也想知道如何在cython中声明一个字符串变量,因为我不知道,我把它声明为对象。

最佳答案

主要区别在于可以从哪里调用函数: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 可见(一旦它导入了 Cython 模块)而 g 将不会也不能从 Python 调用。 g 将转换为以下的 C 签名:

PyObject* some_name(int, struct __pyx_obj_11name_of_module_C *, PyObject*)

(其中 struct __pyx_obj_11name_of_module_C * 只是我们的类 C 被翻译成的 C 结构)。例如,这允许它作为函数指针传递给 C 函数。相比之下,f 不能(轻易地)从 C 中调用。

cdef 函数的限制:

cdef 函数不能在其他函数中定义 - 这是因为无法将任何捕获的变量存储在 C 函数指针中。例如。以下代码是非法的:

# WON'T WORK!
def g(a):
   cdef (int b):
      return a+b

cdef 函数不能接受 *args**kwargs 类型的参数。这是因为它们不能轻易转换为 C 签名。

cdef 函数的优点

cdef 函数可以采用任何类型的参数,包括那些没有 Python 等价物的参数(例如指针)。 def 函数不能有这些,因为它们必须可以从 Python 调用。

cdef 函数还可以指定返回类型(如果未指定,则它们返回 Python 对象,在 C 中为 PyObject*)。 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 函数(允许你从 Python 中调用它)。 def 函数内部只是调用了 cdef 函数。在允许的参数类型方面,cpdef 函数具有cdefdef 函数的所有限制。

何时使用cdef 函数

调用函数后,cdefdef 函数中的代码运行速度没有差异。因此,仅在以下情况下使用 cdef 函数:

  • 您需要传入或传出非 Python 类型,或者
  • 您需要将其作为函数指针传递给 C,或者
  • 您经常调用它(因此加速函数调用很重要)并且您不需要从 Python 调用它。

当你经常调用它时使用 cpdef 函数(因此加速函数调用很重要)但你确实需要从 Python 调用它。

关于python - cython中def、cdef、cpdef的定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28362009/

相关文章:

python - 为 emacs-jedi 安装 python 服务器

Python 将 numpy 数组写入 CSV 文件

variables - 具有多个变量的简短变量声明

python - Cython:创建数组抛出 "not allowed in a constant expression"

python-3.x - Numpy 在 Cython 中,没有改进

python - 如何要求 sympy 不要将 bm 翻译成 boldsymbol?

python - 我正在使用 cv2.imread() 读取图像,并将其转换为灰度。但是为什么我显示的时候不是灰度的呢?

arrays - 简单但具体的数组编译错误(C)

java - 奇怪的数组返回类型

python - Cython - 检查对象类型