Cython 子类 "First base of" ... "is not an extension type" 即使它是用 cdef 定义的

Cython subclassing "First base of" ... "is not an extension type" even though it is defined with cdef

我正在使用 Cython 为一个大学项目优化我的 Python 代码。 为此,我想将 python classes 转换为扩展类型。我目前在编译一种扩展类型时遇到问题,应该 是另一种扩展类型的子class。 这是我得到的错误:

src/core/ast/ast_classes/AstPreprocessor.pyx:9:27: First base of 'AstPreprocessor' is not an extension type

AstPreprocessor的定义如下:

#Edit
from src.core.ast.ast_classes.AstBase import AstBase

cdef class AstPreprocessor(AstBase):
    cdef str function_name

    def __init__(self, function_ast, str function_name):
        super().__init__(function_ast)
        self.ast.index = self.ast.index.map(str)
        self.function_name = function_name
        self.symbol_list = super().get_symbol_list(self.function_name)

    #more method declarations     

这是 AstBase class 的一部分,包括 AstPreprocessor#__init__() 中调用的方法:

cdef class AstBase:
    cdef int length
    def __init__(self, df):
        self.ast = df
        self.length = int(df.shape[0])
        self.childrens = {}

    #more method declarations    

    cdef get_symbol_list(self, str function_name):
        symbol_list = []
        for i in self.ast.index:
            i = int(i)
            if self.token(i).startswith('SYMBOL') \
                    and self.text(i) != function_name:
                symbol_list.append(i)
        return symbol_list

这是来自我的 setup.py:

的 cythonize 命令
ext_modules=cythonize(["src/core/ast/ast_classes/*.pyx",
                       "src/core/ast/preprocessing/*.pyx"], 
                       language_level=3, annotate=True),

我查看了文档,但我很难真正理解为什么会出现此错误以及如何修复它。这是我第一次使用 Cython,因此非常感谢任何帮助。

编辑: 我也尝试过使用 cimport 但遗憾的是问题没有改变。

你需要做两件事。 First create a .pxd file AstBase 调用了 AstBase.pxd。这些行为有点像 C 头文件,用于在不同模块之间共享 Cython 声明。它应该包含

cdef class AstBase:
    cdef int length
    # any other cdef attributes

    cdef get_symbol_list(self, str function_name)
    # but not the implementation of get_symbol_list

您的 AstBase.pyx 文件看起来基本相同:

cdef class AstBase:
    def __init__(self, df):
        self.ast = df
        self.length = int(df.shape[0])
        self.childrens = {}

请注意,我已将 length 删除,因为它已在 pxd 中声明。请注意 - 目前 astchildrens 不是。

然后在 AstPreprocessor.pyx 中你需要 cimport 而不是 import AstBase

from AstBase cimport AstBase

# the rest stays the same

这确保 Cython 在编译时知道 class 的详细信息(包括它是 cdef class 的事实)。通常,如果 Cython 不知道对象的详细信息,它会假定它是一个在运行时可用的常规 Python 对象,这有时会导致令人困惑的错误消息。