编写您自己的ufunc

创建一个新的ufunc

在阅读本文之前,通过阅读/略读扩展和嵌入Python解释器的

第1部分中的教程以及如何扩展NumPy,可以帮助您熟悉Python的C扩展基础知识。

umath模块是一个计算机生成的C模块,可以创建许多ufunc。它提供了许多如何创建通用函数的示例。使用ufunc机制创建自己的ufunc也不困难。假设您有一个函数,您想要在其输入上逐个元素地操作。通过创建一个新的ufunc,您将获得一个处理的函数

  • 广播
  • N维循环
  • 自动类型转换,内存使用量最少
  • 可选的输出数组

创建自己的ufunc并不困难。所需要的只是您想要支持的每种数据类型的1-d循环。每个1-d循环必须具有特定签名,并且只能使用固定大小数据类型的ufunc。下面给出了用于创建新的ufunc以处理内置数据类型的函数调用。使用不同的机制为用户定义的数据类型注册ufunc。

在接下来的几节中,我们提供了可以轻松修改的示例代码,以创建自己的ufunc。这些示例是logit函数的连续更完整或复杂版本,这是统计建模中的常见功能。Logit也很有趣,因为由于IEEE标准(特别是IEEE 754)的神奇之处,下面创建的所有logit函数都自动具有以下行为。

>>> logit(0)-inf>>> logit(1)inf>>> logit(2)nan>>> logit(-2)nan

这很好,因为函数编写器不必手动传播infs或nans。

示例非ufunc扩展名

为了比较和阅读器的一般启发,我们提供了一个简单的logit C扩展实现,它没有使用numpy。

为此,我们需要两个文件。第一个是包含实际代码的C文件,第二个是用于创建模块的setup.py文件。

#include #include /* * spammodule.c * This is the C code for a non-numpy Python extension to * define the logit function, where logit(p) = log(p/(1-p)). * This function will not work on numpy arrays automatically. * numpy.vectorize must be called in python to generate * a numpy-friendly function. * * Details explaining the Python-C API can be found under * 'Extending and Embedding' and 'Python/C API' at * docs.python.org . *//* This declares the logit function */static PyObject* spam_logit(PyObject *self, PyObject *args);/* * This tells Python what methods this module has. * See the Python-C API for more information. */static PyMethodDef SpamMethods[] = {    {"logit",        spam_logit,        METH_VARARGS, "compute logit"},    {NULL, NULL, 0, NULL}};/* * This actually defines the logit function for * input args from Python. */static PyObject* spam_logit(PyObject *self, PyObject *args){    double p;    /* This parses the Python argument into a double */    if(!PyArg_ParseTuple(args, "d", &p)) {        return NULL;    }    /* THE ACTUAL LOGIT FUNCTION */    p = p/(1-p);    p = log(p);    /*This builds the answer back into a python object */    return Py_BuildValue("d", p);}/* This initiates the module using the above definitions. */#if PY_VERSION_HEX >= 0x03000000static struct PyModuleDef moduledef = {    PyModuleDef_HEAD_INIT,    "spam",    NULL,    -1,    SpamMethods,    NULL,    NULL,    NULL,    NULL};PyMODINIT_FUNC PyInit_spam(void){    PyObject *m;    m = PyModule_Create(&moduledef);    if (!m) {        return NULL;    }    return m;}#elsePyMODINIT_FUNC initspam(void){    PyObject *m;    m = Py_InitModule("spam", SpamMethods);    if (m == NULL) {        return;    }}#endif

要使用setup.py文件,请将setup.py和spammodule.c放在同一文件夹中。然后python setup.py build将构建要导入的模块,或者setup.py install将模块安装到您的site-packages目录。

。。。。。。。。。。。。。

作者:柯广

篇幅有限更多请见扩展链接:http://www.mark-to-win.com/tutorial/52201.html

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章