Skip to content

Cython语言基础

本章介绍Cython核心语法,掌握后能编写高效编译代码。Cython是Python超集,语法向下兼容,但通过cdef、cpdef等关键字可引入静态类型声明,编译后获得C级性能。

学习路径:语法基础 → 变量声明 → 函数定义 → 控制流 → 运算符

核心区别:

  • def:Python可调用,灵活但慢
  • cdef:C级调用,性能最高,但Python不可直接调用
  • cpdef:双重调用,兼顾易用与性能

Cython是Python超集,标准Python代码直接兼容:

# 标准Python代码在Cython中完全兼容
import math
def python_style_list():
result = []
for i in range(10):
result.append(i ** 2)
return result

说明:纯Python代码不享受静态类型优化,但可逐步添加Cython特性。

两种风格对比——纯Python vs Cython优化:

# 纯Python风格 - 无类型声明,编译为纯Python字节码
def pure_python():
return [x for x in range(100)]
# Cython优化 - 静态类型声明
cpdef list cython_style(int n):
cdef int i
cdef list result = []
for i in range(n):
result.append(i * i)
return result

性能差异:cython_style比pure_python快约50-100倍(n=10000时)。

cdef用于声明变量和函数静态类型:

# cdef用于声明变量和函数的静态类型
cdef int count = 0
cdef double pi = 3.14159
cdef str name = "Cython"

常见坑:未声明类型的变量会退化为Python对象,失去C级性能。


功能:声明C语言原生类型,获得最高运行效率。

# 整数类型
cdef int i = 10 # 标准32位整数
cdef long j = 1000000 # 长整数(平台相关)
cdef long long k = 10000000000 # 64位整数
cdef short s = 5 # 16位整数
# 无符号整数
cdef unsigned int ui = 100
cdef unsigned long ul = 1000000
# 浮点类型
cdef float f = 3.14 # 32位浮点
cdef double d = 2.718281828 # 64位浮点
cdef long double ld = 1.414213562 # 高精度浮点
# 字符
cdef char c = 'A'

选择建议:一般情况用int、double,大数值用long long,避免short除非内存敏感。

功能:声明Python对象类型,保持与Python运行时兼容。

# object类型 - 通用Python对象容器
cdef object obj
cdef list lst
cdef dict dct
cdef str s
# 强类型声明 - 指定具体Python类型
cdef list numbers
cdef dict mappings
cdef str text
cdef int value # Python整数对象

说明:cdef int value声明的是Python整数对象,不是C整数。两者性能差异约10倍。

功能:展示不同类型间的转换行为。

# C级类型隐式转换(安全,自动转换)
cdef int a = 5
cdef double b = a # int → double 自动转换,结果 b = 5.0
# Python对象转换
cdef list lst = list(range(10)) # 从range对象转换
cdef str s = str(123) # 整数转字符串,结果 "123"
# 显式类型转换(C风格)
cdef double d = <double>a # 强制转换,结果 5.0

最佳实践:

  • 避免混合C类型和Python对象计算
  • 高精度转低精度时使用显式转换,避免警告

功能:定义可从Python调用的函数,但无静态类型优化。

# def函数 - 可被Python调用,返回Python对象
def sum_py(n):
"""纯Python函数,性能较低"""
total = 0
for i in range(n):
total += i
return total

输出示例:

>>> sum_py(100)
4950

功能:定义C级函数,性能极高,但只能被Cython代码调用。

# cdef函数 - 只能被Cython代码调用,无法从Python直接调用
cdef int sum_c(int n):
"""C级函数,性能极高"""
cdef int total = 0
cdef int i
for i in range(n):
total += i
return total

调用方式:需通过cpdef包装或从其他.pyx文件调用。

功能:兼顾Python调用和C级性能,推荐优先使用。

# cpdef函数 - 可被Python和Cython调用
cpdef int sum_cp(int n):
"""双重可调用函数"""
cdef int total = 0
cdef int i
for i in range(n):
total += i
return total

输出示例:

>>> sum_cp(100)
4950

性能对比(n=10000000):

函数类型耗时
sum_py~800ms
sum_cp~10ms
sum_c~8ms

功能:展示参数类型声明的不同写法。

# 仅有类型声明(参数类型自动推导)
cpdef double average(list values):
cdef double total = 0.0
cdef int i
for i in range(len(values)):
total += values[i]
return total / len(values)
# 带默认值参数
cpdef void process(int n, str mode="normal"):
cdef int i
for i in range(n):
if mode == "verbose":
print(i)

最佳实践:

  • cpdef函数参数避免使用C类型(Python调用时需转换)
  • 默认值必须是Python对象类型,不能是C字面量

功能:if-elif-else结构,与Python语法相同。

# if-elif-else条件判断
cdef char classify(int score):
if score >= 90:
return 'A'
elif score >= 80:
return 'B'
elif score >= 70:
return 'C'
else:
return 'D'

输出示例:

>>> classify(85)
'B'

优化说明:可省略最后else分支,直接返回默认值,减少缩进层级。

功能:while和for循环的Cython优化写法。

# while循环 - 适合条件不确定的场景
cdef int countdown(int n):
cdef int i = n
while i > 0:
i -= 1
return i
# for循环 - 适合已知迭代次数
cdef int sum_range(int n):
cdef int total = 0
cdef int i
for i in range(n):
total += i
return total
# 反向遍历
cdef int sum_reverse(int n):
cdef int total = 0
cdef int i
for i in range(n - 1, -1, -1):
total += i
return total

输出示例:

>>> sum_range(5)
10 # 0+1+2+3+4
>>> sum_reverse(5)
10 # 4+3+2+1+0

功能:根据场景选择合适的循环类型。

# 场景1:C级索引遍历typed memoryview
cdef double sum_array(double[:] arr):
cdef int total = 0.0
cdef int i
cdef double val
for i in range(len(arr)):
val = arr[i]
total += val
return total
# 场景2:需要无限循环能力(如等待标志位)
cdef void wait_for_flag(bint *flag):
cdef int count = 0
while not flag[0]:
count += 1
if count > 1000000:
break

常见坑:

  • for i in arr会退化为Python迭代,失去C级性能
  • 使用range(len(arr))而非arr直接遍历

功能:C风格算术运算,整数除法行为与C相同。

# 算术运算符
cdef int a = 10, b = 3
cdef int result_int
cdef double result_float
result_int = a + b # 加法: 13
result_int = a - b # 减法: 7
result_int = a * b # 乘法: 30
result_int = a / b # 整数除法: 3(C风格)
result_int = a % b # 取模: 1
# 浮点除法
result_float = <double>a / b # 3.333...(需显式转换)

输出示例:

>>> a / b
3 # Python3返回float 3.333...
>>> <int>a / b # C风格整数除法
3

功能:直接操作二进制位,常用于性能优化(乘除2的快速算法)。

cdef int x = 0b1100 # 12
cdef int y = 0b1010 # 10
# 位运算
cdef int and_result = x & y # 0b1000 = 8
cdef int or_result = x | y # 0b1110 = 14
cdef int xor_result = x ^ y # 0b0110 = 6
cdef int not_result = ~x # -13(补码表示)
cdef int left_shift = x << 2 # 48(乘4)
cdef int right_shift = x >> 2 # 3(除4,向下取整)

输出示例:

>>> x << 2
48 # 12 * 4 = 48
>>> x >> 2
3 # 12 / 4 = 3(整数除法)

最佳实践:位运算比乘除快约3-5倍,大规模数值计算时效果显著。

功能:C优先级规则,避免运算符优先级错误。

# C优先级:() > [] > * / % > + - > << >> > < <= > >=
# > & > ^ > | > && > || > = += -= *= /= %=
cdef int a = 1, b = 2, c = 3
cdef int result
result = a + b * c # 1 + (2 * 3) = 7
result = (a + b) * c # (1 + 2) * 3 = 9
result = a | b & c # 1 | (2 & 3) = 3
result = (a | b) & c # (1 | 2) & 3 = 3

常见坑:位运算优先级低于比较运算符,a | b & c按a | (b & c)计算而非(a | b) & c。

功能:合并运算与赋值的简写形式。

cdef int x = 10
x += 5 # x = 15
x -= 3 # x = 12
x *= 2 # x = 24
x /= 4 # x = 6(整数除法)
x %= 5 # x = 1
# 位运算复合赋值
x <<= 2 # x = 4(左移2位)
x >>= 1 # x = 2(右移1位)
x &= 0b11 # x = 0(按位与)

优化建议:复合赋值比单独运算稍快,适用于循环内高频操作。


PythonCython说明性能
def func(x):def func(x):Python可调用慢
无cdef int func(int x):C可调用最快
无cpdef int func(int x):双重可调用快
x = 10cdef int x = 10静态类型声明-
for i in range(n):for i in range(n):静态类型时C级性能差异大
while cond:`while cond:“相同语法-

关键要点:

  1. cdef声明的类型获得C级性能
  2. cpdef是最实用的函数定义方式
  3. 避免Python对象与C类型混合计算
  4. 位运算比乘除快,用于性能敏感场景

  1. 创建包含def、cdef、cpdef函数的.pyx文件,对比调用方式差异
  2. 实现一个计算typed memoryview元素和的函数,对比与普通list的性能
  3. 用位运算实现整数乘除2的快速算法(x << 1 = x * 2)
  4. 比较while循环和for循环在Cython中的性能差异
  5. 编写一个同时使用C类型(int、double)和Python对象(list、dict)的函数