Cython 扩展模块类方法不可见/命名 提及时出错

Posted

技术标签:

【中文标题】Cython 扩展模块类方法不可见/命名 提及时出错【英文标题】:Cython's Extension module's class's methods not visible/give a name Error when mentioned 【发布时间】:2017-07-16 19:16:03 【问题描述】:

我尝试根据我正在处理的项目为 Python 制作一个修改后的列表类,并决定尝试使用 Cython 加速它

在我第一次使用时,该类的大部分功能(特殊功能除外)都不可见且无法访问

我尝试从 cdef、cpdef 和 def 中查找方法和类声明的名称,并尝试使用谷歌搜索查看我是否有正确的语法以及查看其他人是否有类似的问题

这是我的代码:

class list_2:

        cpdef append(self , object item):
            self._lst = array(self + [item])

        cpdef pop(self,int index = -1):
            temp_lst = array(range(len(self) -1 ))

            if index > len(self)-1 and index >= 0 or index*(-1) > len(len) and index < 0:
                raise IndexError
            else:
                if index <0:
                    index = index*(-1)-1
                for x in range(len(self)):
                    if x!= index:
                        temp_lst[i] = self[x]
                        i+=1
                self._lst = temp_lst

【问题讨论】:

看起来您将您的班级声明为class list_2。您应该将其声明为 cdef class list_2 ,以使其成为 cython 扩展类型。否则,cython 将其视为常规 python 类。文档中的This link 可能有助于了解 cython 类。 另外,我不确定尝试重新实现列表类是否一定会给您带来预期的性能优势。如果您的数据都是单一类型,您可能还需要考虑使用 cython 的类型化内存视图或使用 C 数组和指针。了解您为什么对修改列表类感兴趣可能会有所帮助。 @CodeSurgeon 好吧,正如我想我提到的,我已经尝试过 cdefcpdefdef 的类声明,它们都给了我相同的结果将这些功能包含在课程中 老实说,我只是想让这个课程在 Cython 和 Python 中进行练习 您是否也为您的.pyx 文件编写了.pxd 文件(基本上相当于c 头文件)?如果是这样,请将其添加到问题中。编译 cython 代码或运行它时是否出现错误?你能告诉我们这些吗?您为数组类使用了哪些导入? 对于这类问题,在问题中实际包含错误消息非常有帮助,而不是在 6 cmets 后发布一个模糊的摘要。幸运的是,没有它,你已经得到了一个很好的答案。 【参考方案1】:

这是一个简单的示例,可帮助您开始使用 cython 类。首先,我创建了我的setup.py 文件,通过调用python setup.py build_ext --inplace 来编译我的cython .pyx 文件。

from distutils.core import setup
from Cython.Build import cythonize
from distutils.core import Extension

extensions = [
    Extension("mylist", sources=["mylist.pyx"], libraries=[], extra_compile_args=["-w"]),
]
setup(
    ext_modules = cythonize(extensions)
)

接下来,我将编写一个.pxd 文件。就像我在 cmets 中提到的那样,这基本上是一个头文件,它定义了您想要访问的所有“c 端”类属性和方法,这些属性和方法是用 cdefcpdef 定义的。 mylist.pxd 的示例如下所示:

cdef class MyList:
    cdef public list _base_list
    cpdef append(self, object item)
    cpdef pop(self, int index=*)#Note: * is used in place of default values
    cpdef get_data(self)

现在我们已经准备好创建我们的mylist.pyx 文件来实际完成这项工作。为了简单起见,我将使用 python 列表来实现我们的 cython 列表(这在性能方面非常荒谬,但可以避免深入研究数组,这有点棘手)。代码可能如下所示:

cdef class MyList:

    def __cinit__(self):#__cinit__ is preferred for cdef class constructors
        self._base_list = []

    cpdef append(self, object item):
        self._base_list = self._base_list + [item]

    cpdef pop(self, int index=-1):
        self._base_list.pop(index)

    cpdef get_data(self):
        return self._base_list

编译完成后,您可以在 python 中使用这个愚蠢的MyList 类。这是MyListmain.py 文件中的作用:

from mylist import MyList

a = MyList()
a.append("apple")
a.append("banana")
a.append("tomato")
a.append("pear")
a.pop(2)#one of these fruit is not like the others...
print a.get_data() 

如果您在编译或运行此示例时遇到问题,请告诉我。我使用 Python 2.7 和最新的 Cython master(版本 0.26b0)在我的笔记本电脑上对此进行了测试。

【讨论】:

谢谢!我看了你的例子,我得到了它的工作! :) 还有一个问题。有些人对我的帖子投了反对票,你能告诉我哪里出了问题/我能做些什么来改进它吗?再次感谢! @Ali Abbas 我个人没有投反对票,最大的改进就是在您的问题中添加确切的错误消息。否则我们都只能猜测出什么问题了!此外,鉴于您正在尝试使用 cython 加速代码,重新实现 python 的列表类将无济于事。使用listobjectdict 等键入 cdef 变量并没有多大帮助,因为这些容器实际上可以容纳任何对象,因此无法推断出真正的类型信息。此外,cython 的文档很棒,可能会消除您对 cdef、cpdef 和 def 的困惑。 感谢您的反馈 @CodeSurgeon 这是天才。谢谢!

以上是关于Cython 扩展模块类方法不可见/命名 提及时出错的主要内容,如果未能解决你的问题,请参考以下文章

将多个子模块折叠成一个 Cython 扩展

《Cython系列》4. Cython中的扩展类

初用Cython编写扩展模块

在 Cython 中使用 move 方法时出现编译错误

Cython初窥

如何在 cython 模块中使用外部包装类?