当前位置:首页 > 科技 >

Cython初窥

发布时间:2017-09-11 11:17:15

Cython初窥

这篇关于Cython的文章主要是用来阐述什么是Cython,Cython的主要用途是什么。对于Cython的具体用法基本不涉及,因为我觉得了解它的主要用途以及它的优缺点,那么等到有使用场景的时候再来学习一下它的document就可以了。
1. Python的扩展模块(extention module)
我们知道可以用c、c++来扩展Python,这样做的目的就是为了把一些关键功能用更快、更高效的语言(c、c++)来实现,以提高Python程序的运行效率。
下面是一个示例:

#include static PyObject *fun(PyObject *self, PyObject *args) { int n, i, t = 12; if(!PyArg_ParseTuple(args, "i", &n)) { return NULL; } for(i = 0; i < n; i++) { t = t + i; } return Py_BuildValue("i", t); } static PyMethodDef ForAddMethods[] = { {"fun", fun, METH_VARARGS, "For loop add."}, {NULL, NULL, 0, NULL} /* Sentinel */ }; PyMODINIT_FUNC initforadd(void) { (void) Py_InitModule("foradd", ForAddMethods); }

这个扩展的函数非常简单,当然这个函数最后能比用Python来实现会快多少也难说,如果输入的n很大的话这个c语言版本可能会比纯Python版本要快不少了。
在用c语言作为Python的扩展的时候需要按照固定的格式来编写,还有我认为在用c扩展Python的时候更需要注意的是Python的引用计数问题,一旦对Python/C API不熟悉那么就很有可能会出现内存泄露的情况。在c代码中得程序自己来负责对象的引用管理,比如你调用PyInt_FromLong(12)创建了一个PyObject,那么你就需要记住在什么时候调用Py_XINCREF、Py_DECREF来管理对象的引用。
2. 用Cython来生成Python的扩展
Cython是一个用来快速生成Python扩展模块(extention module)的工具,它的语法是Python语言语法和c语言语法的混血。
下面是一个用Python写的foradd功能:

def fun(n): t = 12 i = 0 while i < n: t = t + i i += 1 return t

接着用cython -a test_foradd.pyx命令来生成一个.c和.html文件, 关于Cython的使用大家自行阅读文档吧,在本文中基本就只会用到这一条命令。
生成的test_foradd.c文件就是Cython把test_foradd.pyx”翻译”成的c语言版本,test_foradd.html是一个py代码和c代码对照的页面,可以在页面中看到每条py语句”翻译”成了哪几条c语句。也就是说你可以用Python来写一个需要c语言来实现的扩展模块,然后用Cython可以自动把Python”翻译”成c语言,这样你就无需关注前面我们自己动手用c语言来写Python扩展遇到的问题了。
生成的test_foradd.c的文件内容太多,我把关键的代码摘录如下:

static PyObject *__pyx_int_0; static PyObject *__pyx_int_12; static int __Pyx_InitGlobals(void) { __pyx_int_0 = PyInt_FromLong(0); __pyx_int_12 = PyInt_FromLong(12); return 0; } /* Python wrapper */ static PyMethodDef __pyx_mdef_11test_foradd_1fun = {"fun", (PyCFunction)__pyx_pf_11test_foradd_fun, METH_O, 0}; PyMODINIT_FUNC PyInit_test_foradd(void) { if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error) __pyx_m = Py_InitModule4("test_foradd", __pyx_methods, 0, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m); } static PyObject *__pyx_pf_11test_foradd_fun(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_n) { PyObject *__pyx_v_t = NULL; PyObject *__pyx_v_i = NULL; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations PyObject *__pyx_t_1 = NULL; int __pyx_t_2; __Pyx_RefNannySetupContext("fun", 0); /* "test_foradd.pyx":15 * * def fun(n): * t = 12 # <<<<<<<<<<<<<< * i = 0 * while i < n: */ __Pyx_INCREF(__pyx_int_12); __pyx_v_t = __pyx_int_12; /* "test_foradd.pyx":16 * def fun(n): * t = 12 * i = 0 # <<<<<<<<<<<<<< * while i < n: * t = t + i */ __Pyx_INCREF(__pyx_int_0); __pyx_v_i = __pyx_int_0; /* "test_foradd.pyx":17 * t = 12 * i = 0 * while i < n: # <<<<<<<<<<<<<< * t = t + i * i += 1 */ while (1) { __pyx_t_1 = PyObject_RichCompare(__pyx_v_i, __pyx_v_n, Py_LT); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 17, __pyx_L1_error) __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 17, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; if (!__pyx_t_2) break; /* "test_foradd.pyx":18 * i = 0 * while i < n: * t = t + i # <<<<<<<<<<<<<< * i += 1 * return t */ __pyx_t_1 = PyNumber_Add(__pyx_v_t, __pyx_v_i); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 18, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF_SET(__pyx_v_t, __pyx_t_1); __pyx_t_1 = 0; /* "test_foradd.pyx":19 * while i < n: * t = t + i * i += 1 # <<<<<<<<<<<<<< * return t */ __pyx_t_1 = __Pyx_PyInt_AddObjC(__pyx_v_i, __pyx_int_1, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 19, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF_SET(__pyx_v_i, __pyx_t_1); __pyx_t_1 = 0; } /* "test_foradd.pyx":20 * t = t + i * i += 1 * return t # <<<<<<<<<<<<<< */ __Pyx_XDECREF(__pyx_r); __Pyx_INCREF(__pyx_v_t); __pyx_r = __pyx_v_t; goto __pyx_L0; /* "test_foradd.pyx":14 * # ChangeLog: * * def fun(n): # <<<<<<<<<<<<<< * t = 12 * i = 0 */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("test_foradd.fun", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XDECREF(__pyx_v_t); __Pyx_XDECREF(__pyx_v_i); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; }

企业建站2800元起,携手武汉肥猫科技,做一个有见地的颜值派!更多优惠请戳:武汉做网站公司 https://www.feimao666.com

上一篇:PHP有关问题(急)
下一篇:最后一页