创建一个新的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 <Python.h>
#include <math.h>
/*
* 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.
*/