Python C扩展实现标准差

1 投票
6 回答
849 浏览
提问于 2025-04-16 02:16

我正在写一个C语言扩展,用来计算标准差。因为要处理的数据量很大,所以性能非常重要。我在从列表中获取项目后,搞不清楚怎么得到pyobject的值。这是我第一次为Python写C语言扩展,任何帮助都非常感谢。显然,我不知道怎么正确使用代码示例按钮 :(

这是我目前的进展:

    #include <Python.h>
static PyObject*
func(PyObject *self, PyObject *args)
{
  PyObject *list, *item;
  Py_ssize_t i, len;
  if (!PyArg_UnpackTuple(args, "func", 1, 1, &list)){
    return NULL;
  }
  printf("hello world\n");
  Py_INCREF(list);
  len = PyList_GET_SIZE(list);
  for (i=0;i<len;i++){
    item = PyList_GET_ITEM(list, i);
    PyObject_Print(item,stdout,0);
  }
  return list;
}

static char func_doc[] = "This function calculates standard deviation.";

static PyMethodDef std_methods[] = {
  {"func", func, METH_VARARGS, func_doc},
  {NULL, NULL}
};

PyMODINIT_FUNC
initstd(void)
{
  Py_InitModule3("std", std_methods, "This is a sample docstring.");
}

6 个回答

1

你有没有想过用 cython 来写你的扩展功能?它非常适合这种情况。

1

一旦你有了 item,你可以通过 PyNumber_Float 来获取它的浮点值:

PyObject* floatitem = PyNumber_Float(item);

接下来,你需要检查是否有错误并在出错时退出(if(!floatitem) return 0 -- 或者用 goto 跳转到一个地方,那里可以减少你在代码前面部分可能增加的引用计数,比如在你的例子中是 list)。如果没有错误,PyFloat_AsDouble 会给你所需的 double 值,以便在你后面的 C 代码循环中使用:

double ditem = PyFloat_AsDouble(floatitem);

之后你可以减少 floatitem 的引用计数,然后继续你的工作。不要太担心 PyNumber_Float 的转换开销 -- 如果你一开始传入的是浮点数列表,那就不会有任何开销;-)。如果你还是担心(如果有人传入非浮点数需要转换时宁愿报错),你可以使用 PyFloat_Check,但我建议至少对 intlong 类型做特殊处理,否则会让用户感到困惑和不满;-)。同样,我也强烈建议你学习并使用 PySequence_Fast 及其相关函数,而不是让用户惊讶于你特别要求列表而不是其他类型的序列!-)

4

你可能在重复造轮子。对于Python,有几个科学计算的库,比如SciPyNumpy,它们主要是对C语言库的封装,提供像标准差这样的功能。

撰写回答