能否将Cython类型存入变量,简化模板类实例化的分支判断?
解决方案
Cython的C++模板参数属于编译期常量,无法在运行时通过动态变量直接传入Number[xxx]的模板参数位置,你想要的Number[dict_types[dtype]]()写法没办法直接实现,不过可以用下面两种方式简化代码,避免手动编写大量if分支:
方案1:工厂函数字典
提前把每个类型的实例化逻辑包装为无参工厂函数,存入字典,运行时直接根据dtype取对应函数调用即可:
# pyx文件 from Number cimport Number # 提前定义工厂函数字典,新增支持类型只需要在这里加一行 cdef dict number_factory = { "int": lambda: Number[int](), "float": lambda: Number[float](), "double": lambda: Number[double](), } def func(dtype): if dtype not in number_factory: raise ValueError(f"不支持的dtype: {dtype}") # 直接调用对应工厂函数生成实例 n = number_factory[dtype]() # 后续处理逻辑
注意:如果你的
n变量需要用cdef声明静态类型,不同模板实例化的Number[T]属于完全不同的C++类型,不能共用同一个静态类型声明,这种场景下你可以:
- 把
Number[T]封装为统一的Python扩展类型,返回Python对象即可无需静态声明- 如果后续逻辑也是泛型实现,可以搭配融合类型使用
方案2:使用Cython融合类型(Fused Types)
如果你的调用场景是在Cython内部,或者dtype可以对应到标准数值类型,可以直接用融合类型实现编译期的自动分发:
from Number cimport Number cimport cython # 定义融合类型,包含所有支持的数值类型,新增类型只需要在这里添加 ctypedef fused number_type: cython.int cython.float cython.double # 泛型实现函数,编译期会自动为每个类型生成对应版本 cdef Number[number_type] create_number(number_type dummy): return Number[number_type]() # 对外暴露的接口 def func(dtype): cdef: int dummy_int float dummy_float double dummy_double if dtype == "int": return create_number(dummy_int) elif dtype == "float": return create_number(dummy_float) elif dtype == "double": return create_number(dummy_double) else: raise ValueError(f"不支持的dtype: {dtype}")
如果配合numpy的dtype使用,还可以直接通过numpy的类型对象触发融合类型分发,连最外层的dtype判断都可以省略。
内容的提问来源于stack exchange,提问作者AlexSp3
相关产品推荐
相关产品推荐

