使用cython早期输入类属性 [英] Using cython to early type class attributes

查看:155
本文介绍了使用cython早期输入类属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个python类,我想使用cython早期输入来加快执行速度。

我收到了错误 C变量声明中的语法错误 当我尝试cython编译以下内容时:

I'm writing a python class and I would like to accelerate the execution using cython early typing.
I get the error "Syntax error in C variable declaration" when I try to cython compile the following:

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 <的最后一行的语法/ code>。我不允许直接键入类属性吗?我是否总是必须将其分为两个步骤,例如,

The error concerns the syntax of the last line involving self.var1. Am I not allowed to type class attributes directly? Do I always have to break this up into two steps such as,

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 类型。特别是您的代码应如下所示:

What you want is to define an extension type. In particular your code should look like:

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

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

Note that you cannot impose the type of instance attributes in a normal class, because python allow people to change them and their types. If you try to put a cdef at class level in a normal python class you'll receive a compiler error by Cython.

编译上面的代码会引发以下错误:

Compiling the above code raises the following error:

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 行,则文件将正确编译:

Now, this is not a syntax error. The syntax is fine. The problem is that you simply cannot have an instance attribute with np.ndarray as type. It is a limitation of cython. In fact if you comment the cdef np.ndarray[double, ndim=1] Redges line the file is compiled correctly:

代码:

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 没有输出,表示文件已成功编译。

Note: no output from cython which means the file was compiled succesfully.

此限制在上面链接的文档中,属性

this limitation is explained in the documentation I linked above, at the section Attributes:


扩展类型的属性直接存储在对象的C
struct 中/ em>。 [omissis]

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

注意您只能公开简单的C类型,例如int,float和字符串,用于Python访问。您还可以公开Python值的
属性。

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数据类型是因为属性是 struct 的成员。允许像 np.ndarray 这样的缓冲区需要具有可变大小 struct s。

The fact that you can only expose simple C data-types is because the attributes are members of the struct. Allowing a buffer like an np.ndarray would require to have variable size structs.

如果想要类型为 np.ndarray 的实例属性,则最好的办法是定义一个通用类型为<$ c的属性。 $ c>对象并为其分配数组:

If you want an instance attribute of type np.ndarray the best you can do is to define an attribute with a generic type of object and assign the array to it:

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

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

However now everytime you access self.Redges you lose the speed up of cython. If you access it many times you can assign it to a local variable with the correct type. Here's what I mean:

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]

code> do_stuff 函数,您可以使用 ar 获得cython的所有速度。

In this way inside the do_stuff function you can have all the speed of cython using ar.

这篇关于使用cython早期输入类属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆