Cython能否在函数签名中声明列表参数的cdef类元素类型?
解答
原生Python list是动态异构容器,Cython旧版本不支持直接在函数签名中声明list的元素类型,你尝试的list Shrubbery list_of_sh不符合Cython语法规范,无法运行。
你可以通过以下几种方式实现需求,无需单独声明局部变量:
方案1:在for循环中直接标注迭代变量类型(兼容所有Cython版本)
这是最简便的修改方式,Cython支持直接在for迭代时指定变量类型,无需提前单独cdef声明:
# 先在参数声明中指定参数为list类型 cdef widen_shrubberies(list list_of_sh, int extra_width): # 迭代时直接标注变量类型 for Shrubbery sh in list_of_sh: sh.width += extra_width
注意你原有变通方案里的for i in len(list_of_sh)存在语法错误,需要改为for i in range(len(list_of_sh))才能正常运行。
方案2:用Cython 3+的泛型类型标注
如果你使用Cython 3及以上版本,可以借助PEP 484泛型标注在函数签名中声明列表的元素类型,编译阶段会做静态类型检查:
from typing import List cdef class Shrubbery: cdef int width, height cdef float depth cdef widen_shrubberies(List[Shrubbery] list_of_sh, int extra_width): for sh in list_of_sh: sh.width += extra_width
这种方式仅做编译期静态检查,运行时不会强制校验列表内的元素类型,如果你传入了非Shrubbery类型的元素,依然会出现运行时错误。
方案3:使用C++类型化容器(高性能场景)
如果你的场景不需要和Python侧做频繁的列表交互,可以改用C++的std::vector存储cdef类的指针,这种容器支持在函数签名中明确声明元素类型,编译期会做严格的类型校验,性能也远高于Python原生list:
# 声明使用C++编译 # distutils: language = c++ from libcpp.vector cimport vector cdef class Shrubbery: cdef int width, height cdef float depth cdef widen_shrubberies(vector[Shrubbery*]& list_of_sh, int extra_width): cdef Shrubbery* sh for i in range(list_of_sh.size()): sh = list_of_sh[i] sh.width += extra_width
内容的提问来源于stack exchange,提问作者mbpaulus
相关产品推荐
相关产品推荐

