python - 使用cython来早期类型化类属性

标签 python class cython

我正在编写一个 python 类,我想使用 cython 早期键入来加速执行。
当我尝试用 cython 编译以下内容时,出现错误 “C 变量声明中的语法错误”:

import numpy as np
cimport numpy as np

class MyClass:
    def __init__( self, np.ndarray[double, ndim=1] Redges ):
        self.Redges = Redges
        cdef double self.var1

错误涉及涉及 self.var1 的最后一行的语法。我不能直接输入类属性吗?我是否总是必须将其分为两步,例如,

cdef double var1
self.var1 = var1

完整的错误回溯是,

test.pyx:7:24:  
Syntax error in C variable declaration  
Traceback (most recent call last):  
File "setup.py", line 9, in <module>  
        ext_modules = cythonize('test.pyx'), # accepts a glob pattern  
      File "/usr/lib/python2.7/dist-packages/Cython/Build/Dependencies.py", line 713, in cythonize
        cythonize_one(*args[1:])  
      File "/usr/lib/python2.7/dist-packages/Cython/Build/Dependencies.py", line 780, in cythonize_one  
        raise CompileError(None, pyx_file)  
  Cython.Compiler.Errors.CompileError: calc_iliev_sphere.pyx

最佳答案

你想要的是定义一个extension type .特别是您的代码应该如下所示:

import numpy as np
cimport numpy as np

cdef class MyClass:
    cdef double var1
    cdef np.ndarray[double, ndim=1] Redges

    def __init__( self, np.ndarray[double, ndim=1] Redges ):
        self.Redges = Redges

请注意,您不能在普通中强加实例属性的类型,因为python 允许人们更改它们及其类型。如果您尝试将 cdef 放在普通 python 类中的类级别,您将收到 Cython 的编译器错误。


编译上述代码会出现以下错误:

Error compiling Cython file:
------------------------------------------------------------                       
...                                                                                
import numpy as np                                                                 
cimport numpy as np                                                                

cdef class MyClass:                                                                
    cdef double var1                                                               
    cdef np.ndarray[double, ndim=1] Redges                                         
                                   ^                                               
------------------------------------------------------------                       

test_cython.pyx:6:36: Buffer types only allowed as function local variables

现在,这不是语法错误。语法很好。问题是您只是不能具有类型为np.ndarray 的实例属性。这是cython的一个限制。事实上,如果您评论 cdef np.ndarray[double, ndim=1] Redges 行,文件将被正确编译:

代码:

import numpy as np
cimport numpy as np

cdef class MyClass:
    cdef double var1
    #cdef np.ndarray[double, ndim=1] Redges

    def __init__( self, np.ndarray[double, ndim=1] Redges ):
        self.Redges = Redges

输出:

$cython test_cython.pyx 
$

注意:cython 没有输出,这意味着文件已成功编译。

此限制在我上面链接的文档中的 Attributes 部分进行了解释:

Attributes of an extension type are stored directly in the object’s C struct. [omissis]

Note: You can only expose simple C types, such as ints, floats, and strings, for Python access. You can also expose Python-valued attributes.

您只能公开简单 C 数据类型的事实是因为属性是结构 的成员。允许像 np.ndarray 这样的缓冲区需要具有可变大小的 struct

如果你想要一个 np.ndarray 类型的实例属性,你能做的最好的事情就是用 object 的通用类型定义一个属性并将数组分配给它:

import numpy as np
cimport numpy as np

cdef class MyClass:
    cdef double var1
    cdef object Redges

    def __init__( self, np.ndarray[double, ndim=1] Redges ):
        self.Redges = Redges

但是现在每次您访问 self.Redges 时,您都会失去 cython 的加速。如果您多次访问它,您可以将它分配给具有正确类型的局部变量。 这就是我的意思:

import numpy as np
cimport numpy as np

cdef class MyClass:
    cdef double var1
    cdef object Redges

    def __init__( self, np.ndarray[double, ndim=1] Redges ):
        self.Redges = Redges

    def do_stuff(self):
        cdef np.ndarray[double, ndim=1] ar
        ar = self.Redges
        ar[0] += 1
        return ar[0]

通过这种方式,在 do_stuff 函数中,您可以使用 ar 获得 cython 的所有速度。

关于python - 使用cython来早期类型化类属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21131884/

相关文章:

python - 使用 splrep 平滑轨迹

python - 如何避免python类方法中的无限递归

java - 为什么我从类里面获取的值(value)观会被结合在一起?

C++,头文件中的对象声明

python - 跟踪由 Cython 包装的 C++ 中分配的内存使用情况

python - 如何在 python 中出现异常时重复某些内容?

python - 如何获取加载图像的坐标而不是显示屏上的坐标

python - Django 异步处理

python - 通过使用位数组而不是 int 来节省 dict 的内存?

python - 使用 pandas 列表中的项目名称