如何检查PyObject是否是列表?

2024-05-26 11:11:17 发布

您现在位置:Python中文网/ 问答频道 /正文

我是Python/capi的新手,虽然我有一些基本的函数可以工作,但我正在努力解决这个问题。在

PyObject* sum_elements(PyObject*, PyObject *o) 
{
    Py_ssize_t n = PyList_Size(o);
    long total = 0;
    if (n < 0)
    {
        return PyLong_FromLong(total);
    }
    PyObject* item;
    for (int i = 0; i < n; i++) 
    {
        item = PyList_GetItem(o, i);
        if (!PyLong_Check(item)) continue;
        total += PyLong_AsLong(item);
    }
    return PyLong_FromLong(total);
}

基本上这是doc页面上介绍的功能。它应该接收一个python列表并返回所有元素的总和。如果我传递了一个列表,如果我传递了其他东西,但是我得到了错误消息,那么这个函数工作得很好

^{pr2}$

这种情况应该由if (n<0)语句处理,如果传递的对象不是列表,则n是-1。在

我用以下方式绑定函数:

static PyMethodDef example_module_methods[] = {
    { "sum_list", (PyCFunction)sum_elements, METH_O, nullptr},
    { nullptr, nullptr, 0, nullptr }
};

谢谢。在


Tags: 函数列表returnifelementsitemtotalpyobject
1条回答
网友
1楼 · 发布于 2024-05-26 11:11:17

错误

SystemError: c:\_work\5\s\objects\listobject.c:187: bad argument to internal function

实际发生在

^{pr2}$

因为PyList_Size有一个额外的检查来查看对象是否为list类型,如果不是,它将调用PyErr_BadInternalCallAPI来引发{}。请参见^{}PyList_Size的实现

PyList_Size(PyObject *op)
{
    if (!PyList_Check(op)) {
        PyErr_BadInternalCall();
        return -1;
    }
    else
        return Py_SIZE(op);
}

PyErr_BadInternalCallPyErr_SetString(PyExc_SystemError, message)的简写,其中message指示使用非法参数调用了内部操作(例如Python/capi函数)。在

您应该使用PyList_CheckAPI来检查对象是否属于list类型。根据文档,如果对象是列表对象或列表类型的子类型的实例,则返回true。

PyObject* sum_elements(PyObject*, PyObject *o) 
{    
    // Check if `o` is of `list` type, if not raise `TypeError`.
    if (!PyList_Check(o)) {
         PyErr_Format(PyExc_TypeError, "The argument must be of list or subtype of list");
         return NULL;
    }
    // The argument is list type, perform the remaining calculations.
    Py_ssize_t n = PyList_Size(o);
    long total = 0;
    if (n < 0)
    {
        return PyLong_FromLong(total);
    }
    PyObject* item;
    for (int i = 0; i < n; i++) 
    {
        item = PyList_GetItem(o, i);
        if (!PyLong_Check(item)) continue;
        total += PyLong_AsLong(item);
    }
    return PyLong_FromLong(total);
}

一旦添加了这个额外的检查,函数调用将引发

TypeError: The argument must be of list or sub type of list

当提供list类型以外的参数时。在

相关问题 更多 >