Numba jitclass如何实现支持None或numpy数组取值的类属性?
问题解答
你的判断是正确的:Numba的jitclass默认要求所有属性的类型在编译阶段静态确定,本身不支持属性在None和numpy数组两种类型之间动态切换,因为jitclass运行在nopython模式下,不允许类型动态变化。
你现有代码有两处核心错误:
- property的getter方法存在递归调用:
return self.sources是调用属性本身,直接触发编译死循环,是你当前报错的直接诱因,正确写法应该返回私有属性self._sources。 - sources属性的返回值类型不固定:一会返回
None一会返回numpy数组,不符合nopython模式的类型静态要求。
实现方案
Numba提供了Optional类型专门用来标注可以为None的属性,不需要额外增加布尔变量做标记,正确实现代码如下:
import numba from numba.experimental import jitclass from numba import Optional import numpy as np # 用Optional标注_sources支持两种类型:None/int32二维数组 spec = [ ("_sources", Optional(numba.int32[:, :])) ] @jitclass(spec) class MyClass: def __init__(self, sources = None): if sources is not None: self._sources = sources.astype(np.int32) else: self._sources = None @property def sources(self): return self._sources if __name__ == "__main__": # 两种初始化方式都可以正常运行 obj1 = MyClass(None) print(obj1.sources) # 输出None obj2 = MyClass(np.array([[1,2],[3,4]])) print(obj2.sources) # 输出[[1 2],[3 4]]
低版本兼容方案
如果你使用的Numba版本较旧,不支持jitclass的Optional属性,可以保留布尔标记的思路,但不要返回动态类型,改为提供两个固定返回类型的方法供调用方使用:
import numba from numba.experimental import jitclass import numpy as np spec = [ ("_is_source_none", numba.bool_), ("_sources", numba.int32[:, :]) ] @jitclass(spec) class MyClass: def __init__(self, sources = None): self._is_source_none = sources is None if not self._is_source_none: self._sources = sources.astype(np.int32) else: # 占位用的空数组,不会被实际调用 self._sources = np.empty((0,0), dtype=np.int32) def has_sources(self): return not self._is_source_none def get_sources(self): # 调用方需要先调用has_sources确认非None再调用本方法 return self._sources if __name__ == "__main__": obj1 = MyClass(None) print(obj1.has_sources()) # 输出False obj2 = MyClass(np.array([[1,2],[3,4]])) if obj2.has_sources(): print(obj2.get_sources()) # 输出[[1 2],[3 4]]
内容的提问来源于stack exchange,提问作者user1315621
相关产品推荐
相关产品推荐

