代码之家  ›  专栏  ›  技术社区  ›  Physicist

将python类转换为cython

  •  1
  • Physicist  · 技术社区  · 8 年前

    我在python中有以下代码:

    class DisjointSet:
        def __init__(self, n):
            self.parent = list(range(n))
            self.rank = [0 for x in range(n)]
    
        def find(self, v):
            if v != self.parent[v]:
                self.parent[v] = self.find(self.parent[v])
            return self.parent[v]
    

    其余代码在“代码复杂性”方面类似,此处不包括。

    所以我想把上面的代码翻译成Cython代码(我知道一点点C++,我设法把我所有的代码翻译成C++,但是我想试试Cython,看看它是如何与C++和Python相比较的)。我有点像:

    disjointset.pyx:

    # distutils: language=c++
    from libcpp.vector cimport vector
    
    cdef class DisjointSet:
        cpdef public vector[int] parent, rank
    
        def __init__(self, int n):
            for i in range(n):
                self.parent.push_back(i)
                self.rank.push_back(0)
    
        def find(self, int v):
            if v != self.parent[v]:
                self.parent[v] = self.find(self.parent[v])
            return self.parent[v]
    

    Stupp.Py:

    from distutils.core import setup
    from Cython.Build import cythonize
    
    setup(
        ext_modules = cythonize("cPercolation.pyx", annotate=True)
    )
    

    我跑 python setup.py build_ext --inplace 在Windows PowerShell中编译代码。但是,当我导入代码并在python中尝试时,它有时会出错(进程不返回0),当我调用find方法时,它有时会给出递归错误。那么,正确的翻译上述代码的方法是什么呢?我已经阅读了官方文件,但我仍然不确定 cdef , cpdef .

    编辑:我已经添加了for循环来解决这个问题,但是我仍然应该如何改进cython代码?当我查看生成的HTML文件时,仍然有很多黄色突出显示(Python交互)。具体来说,我想问一下我应该如何使用 CDEF , CPDEF 使类方法( DisjointSet.find )更像C++代码。

    1 回复  |  直到 8 年前
        1
  •  5
  •   georgexsh    8 年前

    C++ vector 操作人员 [] does not check bounds ,out-bound访问会给出一个随机值,这会导致后续的向量访问中出现段错误,您将注意到一个非零的退出代码。

    相反,使用 .at() which has bounds checking ,Cython会翻译 std::out_of_range 异常进入 IndexError :

     def find(self, int v):
         try:
             pv = self.parent.at(v)
         except IndexError:
             return None
         ...
    
    推荐文章