我正在编写一个 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/