CodeWalk

Cython基础:cdef/cpdef/def三种函数类型详解

作者:我还是少年 · 2026-05-30 12:55

请解释Cython中cdefcpdefdef三种函数类型的区别和各自的使用场景。cdef函数为什么不能被Python调用?cpdef如何在Python和C之间提供混合调度?给出一个Cython加速数值计算的完整示例(编译前和编译后性能对比)。说明Cython类型声明的语法和性能影响。

回答

我还是少年

三种函数类型对比: | 函数类型 | Python可调用 | C可调用 | 调用开销 | 适用场景 | |---------|------------|---------|---------|---------| | def | ✅ | ❌ | Python完整调用 | API接口、需灵活处理 | | cdef | ❌ | ✅ | 零开销 | 内部函数、循环热路径 | | cpdef | ✅ | ✅ | 小开销(双入口) | 需要Python可见的内部函数 |

性能对比示例

# calc.pyx
def py_sum(int n):  # 纯Python级
def py_sum(n):  # Python级
    cdef int i
    cdef long total = 0
    for i in range(n):
        total += i
    return total

cdef long c_sum(int n) nogil:  # C级,可释放GIL
    cdef int i
    cdef long total = 0
    for i in range(n):
        total += i
    return total

cpdef long cp_sum(int n):  # 双入口
    with nogil:
        return _c_sum(n)

编译(setup.py)

from setuptools import setup
from Cython.Build import cythonize

setup(ext_modules=cythonize('calc.pyx', language_level='3'))

性能数据(求和10^8):

  • 纯Python:~8秒
  • def + C类型声明:~0.5秒
  • cdef + nogil:~0.15秒
  • 优化后接近C性能

类型声明语法

cdef:
    int i
    double x = 3.14
    list py_list = []  # Python对象
    Py_ssize_t idx     # 索引类型(平台无关)

最佳实践

  • 内层循环变量加类型声明
  • 计算密集型函数用cdef+nogil
  • 外部API用cpdef提供Python接口
  • 使用-a选项生成HTML注释查看优化情况
  • 复杂项目可用Cython.Build.cythonize(compiler_directives={'boundscheck': False, 'wraparound': False})