扩展类型与类
本章讲解Cython扩展类型的定义和优化。cdef class是Cython的高性能类定义方式,比Python类快10-100倍。
学习路径:类定义 → 属性优化 → 继承限制 → 结构体嵌入 → 描述符
核心概念:
cdef class:扩展类型,C级属性访问cpdef:双重可调用方法cdef struct:嵌入C结构体
11.1 cdef class定义
Section titled “11.1 cdef class定义”功能说明:使用cdef声明C级属性,绕过Python字典查找。
# Cython扩展类型cdef class Point: cdef double x cdef double y
def __init__(self, double x, double y): self.x = x self.y = y
cpdef double distance(self): return (self.x ** 2 + self.y ** 2) ** 0.5输出示例:
>>> p = Point(3.0, 4.0)>>> p.distance()5.0功能说明:三种方法类型:cdef(最快)、cpdef(双重调用)、def(仅Python)。
cdef class Circle: cdef double _x cdef double _y cdef double _radius
def __init__(self, double x, double y, double radius): self._x = x self._y = y self._radius = radius
# C级方法 - 最快,但Python不可直接调用 cdef double area(self): return 3.14159 * self._radius ** 2
# Python可调用方法 cpdef double circumference(self): return 2.0 * 3.14159 * self._radius
# 属性定义 property x: def __get__(self): return self._x def __set__(self, value): self._x = value性能对比(1000万次调用):
| 方法类型 | 耗时 |
|---|---|
| cdef | ~50ms |
| cpdef | ~150ms |
| def | ~800ms |
初始化与销毁
Section titled “初始化与销毁”功能说明:使用__cinit__和__dealloc__管理资源。
cdef class Resource: cdef void* _handle cdef bint _valid
def __cinit__(self, str name): self._handle = open_resource(name) if self._handle == NULL: raise MemoryError("Failed to open resource") self._valid = True
def __dealloc__(self): if self._valid and self._handle != NULL: close_resource(self._handle) self._valid = False11.2 属性访问优化
Section titled “11.2 属性访问优化”cpdef属性
Section titled “cpdef属性”功能说明:cpdef方法可在Python和Cython中调用。
cdef class Optimized: cdef int _value cdef list _cache
def __init__(self, int value): self._value = value self._cache = []
# cpdef方法 - C和Python都可调用 cpdef int get_value(self): return self._value
cpdef void set_value(self, int value): self._value = value功能说明:延迟计算直到真正需要结果。
cdef class LazyClass: cdef int _expensive_result cdef bint _computed cdef list _data
def __init__(self, list data): self._data = data self._computed = False
cdef int _ensure_computed(self): if not self._computed: self._expensive_result = sum(self._data) self._computed = True return self._expensive_result
cpdef int get_result(self): return self._ensure_computed()功能说明:缓存计算结果避免重复计算。
cdef class CachedClass: cdef object _cache cdef int _value
def __init__(self, int value): self._value = value self._cache = {}
cdef object _get_cached(self, str key): if key not in self._cache: self._cache[key] = self._compute(key) return self._cache[key]
cdef object _compute(self, str key): # 昂贵的计算 return self._value * len(key)11.3 继承与多态
Section titled “11.3 继承与多态”功能说明:Cython支持单继承,实现多态。
cdef class Animal: cdef str _name
def __init__(self, str name): self._name = name
cpdef str speak(self): return "..."
cdef class Dog(Animal): cdef str _breed
def __init__(self, str name, str breed): super().__init__(name) self._breed = breed
cpdef str speak(self): return "Woof!"
cdef class Cat(Animal): cpdef str speak(self): return "Meow!"输出示例:
>>> dog = Dog("Buddy", "Labrador")>>> dog.speak()'Woof!'>>> cat = Cat("Whiskers")>>> cat.speak()'Meow!'功能说明:Cython不支持多继承,使用组合替代。
# Cython不支持多继承# cdef class A: pass# cdef class B: pass# cdef class C(A, B): # 错误
# 使用组合代替cdef class A: cdef int value_a
cdef class B: cdef int value_b
cdef class C: cdef A _a cdef B _b
def __init__(self): self._a = A() self._b = B()功能说明:通过方法检查模拟抽象类。
# Cython中没有抽象类的直接支持# 使用方法检查
cdef class AbstractBase: cpdef str operation(self): raise NotImplementedError("Subclasses must implement")
cdef class Concrete(AbstractBase): cpdef str operation(self): return "Concrete implementation"11.4 C结构体嵌入
Section titled “11.4 C结构体嵌入”cdef struct as attributes
Section titled “cdef struct as attributes”功能说明:在扩展类型中嵌入C结构体。
cdef struct Point3D: double x double y double z
cdef class Vector: cdef Point3D _origin
def __init__(self, double x, double y, double z): self._origin.x = x self._origin.y = y self._origin.z = z
cpdef double magnitude(self): return (self._origin.x ** 2 + self._origin.y ** 2 + self._origin.z ** 2) ** 0.5输出示例:
>>> v = Vector(1.0, 2.0, 2.0)>>> v.magnitude()3.0内存布局控制
Section titled “内存布局控制”功能说明:使用packed确保结构体紧凑。
# 确保结构体紧凑(无padding)cdef packed struct CompactPoint: double x # 8字节 double y # 8字节 # 总共16字节,无padding
# 普通结构体可能有paddingcdef struct NormalPoint: double x double y # 编译器可能添加padding对齐FFI互操作
Section titled “FFI互操作”功能说明:与C结构体互操作。
cdef extern from "myheader.h": cdef struct NativePoint: double x double y
cdef class PyNativeBridge: cdef NativePoint _native
def __init__(self, double x, double y): self._native.x = x self._native.y = y
cpdef (double, double) get_coords(self): return (self._native.x, self._native.y)11.5 描述符协议
Section titled “11.5 描述符协议”property
Section titled “property”功能说明:使用property定义属性访问逻辑。
cdef class Celsius: cdef double _celsius
def __init__(self, double temp): self._celsius = temp
property fahrenheit: def __get__(self): return self._celsius * 9.0/5.0 + 32.0 def __set__(self, double value): self._celsius = (value - 32.0) * 5.0/9.0输出示例:
>>> c = Celsius(100)>>> c.fahrenheit212.0>>> c.fahrenheit = 32>>> c._celsius0.0功能说明:实现__get__和__set__的描述符类。
cdef class RangeValidator: cdef int _min cdef int _max
def __init__(self, int min_val, int max_val): self._min = min_val self._max = max_val
def __get__(self, obj, objtype=None): return obj._value if obj else self
def __set__(self, obj, value): if value < self._min or value > self._max: raise ValueError(f"Must be between {self._min} and {self._max}") obj._value = value
cdef class Temperature: cdef int _value cdef RangeValidator _validator
def __init__(self, int initial=0): self._value = initial self._validator = RangeValidator(0, 100)类型性能对比
Section titled “类型性能对比”| 特性 | 语法 | 性能 |
|---|---|---|
| cdef class | 扩展类型 | 最快 |
| cpdef | 双重可调用 | 中 |
| property | 属性访问 | Python开销 |
| cdef struct | C结构体 | 极快 |
最佳实践清单
Section titled “最佳实践清单”- 类属性用
cdef而非cdef public - 方法优先用
cdef,需要Python调用时用cpdef - 继承只支持单继承,用组合替代多继承
- 资源管理用
__cinit__和__dealloc__ - 频繁访问的属性用缓存
- 实现一个Complex复数类(支持加减乘除)
- 创建带惰性计算的类(缓存结果)
- 实现继承体系(Animal -> Dog, Cat)
- 使用C结构体嵌入表示几何对象
- 实现描述符进行输入验证(如范围检查)
- 比较cdef属性和cdef public属性的访问性能