Cython的特点与作用

1.Cython

源于Pyrex,Cython项目借助于源代码编译器将Python代码转换为同等的C语言,这是在CPython(主Python运行环境主要是CPython,由C语言编写而成。)运行环境下完成的,但 具有C语言的编译速度及直接调用C库的能力;同时它也保留了Python源代码的接口,这使得Cython可直接被Python代码使用。

以上可以推出Cython的两个用途:(1)以快速的二进制模块扩展CPython解释器;(2)为Python提供使用C扩展库的接口。

那么Cython中是如何将Python代码转换为C语言的呢?

其中一点是Cython分配C语义给部分代码,使之可以翻译为高效的C代码。Cython中的类型声明用于两个目的:将代码段从动态的Python语义移动到静态且快速的C语义;直接操作外部库定义的类型。

2.Python与C语言在%上的区别

在Python中,%为取模,而C中,%为取余;

取模与取余的公式相同:例如求解a%b,令c=a//b(a对b取整,即求整数商),a%b=a-c*b。

不同在于取整之时,取模运算中取整是向负无穷取整,而取余运算中取整是向0取整。

故同样对于-1%5的运算:

Python中,-1//5=-1(向负无穷),而C中int/int的取整运算为-1/5=0(向0);

故Python的-1%5输出为4,C的-1%5输出为-1.

而对于Cython中,%与C语言一致?(我也不明白)

3.Cython中扩展类型的特殊方法

具体可参考http://docs.cython.org/en/latest/src/userguide/special_methods.html#special-methods

特殊方法说明:

(1)所说的特殊方法只能应用于cdef class声明的扩展类型中,而不能应用于普通Python的class声明中。

(2)特殊方法必须由def定义,而不能用cdef定义;这样不会影响其性能,因为Python会使用不同的调用协议去引用它们(??什么调用协议)

  • 初始化方法__cinit__和__init__(注意:所有传入构造函数的参数都是以Python对象的形式传入,故那些不可转换的C类型如pointer不能直接传入constructor)

       __cinit__是对象执行基础的C级初始化的地方,包括分类C类型数据结构。在调用这个方法之前,对象还不是完全有效的Python类型,因此需要小心的引用任何涉及这些对象的Python操作。

       __init__:如果任何在__cinit__不能安全初始化的对象,应该在__init__中去完成。在__init__()被调用之前,对象将是一个完全有效的Python对象并且全部操作是安全的。

任何传递给构造函数的参数将传递给__cinit__方法和__init__方法。如果你希望在Python中子类化你的扩展类型,那么你应该给__cinit__() *和**参数,这样它便能接受和忽略额外的参数。

  • 终结方法__dealloc__

     __dealloc__方法执行与__cinit__相反操作,任何在__cinit__中显示地分配内存的C数据将被释放。在你的__dealloc__()方法被调用之前,就Python而言对象可能已经被部分损坏且不是一个有效的状态,所以需要避免在此方法中对object的Python操作。在__dealloc_()方法中最好只解除分配C数据。同时对象的Python属性会在__dealloc__()返回时释放分配。

     另外,在你子类化扩展类型时,父类的__dealloc__()将被调用,即使这个方法被重写。这与Python的类继承机制不同(必须显示地调用父类的方法)。

4.def, cdef, cpdef的区别

  • def定义函数的函数返回值类型为Python对象
  • cdef在C语言层面定义函数,其函数返回值类型及参数变量都会转化为C类型,cdef定义的函数无法直接被Python调用,但可以在Python函数内调用,但注意若cdef定义指针类型的返回值,则不能被调用。(cdef class 是可以被Python调用)
  • cpdef定义的函数将会生成C函数接口与Python函数接口,即定义的函数既能被C调用也能被Python直接调用;但随之性能也将降低(但仍比纯Python代码快)。它还安装了允许python方法覆盖该方法的逻辑,即使在从cython内部调用时也是如此。

猜你喜欢

转载自blog.csdn.net/hhu_luqi/article/details/86690260