python-3.x - Python C 扩展中的真 *args 和 **kwargs

标签 python-3.x python-c-api python-c-extension

我正在开发 Python 3 C 扩展。

我可以获得等效的或任意的位置或关键字参数吗?

例如,在 Python 中,我可以这样写:

def fun(name, parent, *args, **kwargs):
    # do something with name and parent
    # do something with args and kwargs
    pass

但是我在 C 中找不到简单的等价物。虽然我们可以用 PyObject* args 完美地编写函数和 PyObject* kwargs ,我不能轻易地从它来的任何一个(args/kwargs)中“解析出”名字和父级。

拿:

static PyObject* myFunction(PyObject* self, PyObject* args, PyObject* kwargs) {
    char* kwds[] = {"parent", "name", NULL};
    PyObject* name = NULL;
    PyObject* parent = NULL;
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO", kwds, &parent, &name)) {
        goto errorParseTupleAndKeywords;
    }
    /* Do something with name and parent */
    /* parent and name maybe have appeared either in args or kwargs */
    /* But I don't have any extra positional (*args) or keyword (**kwargs) here */    
}

我能想到的“手动”方法大致如下:

static PyObject* myFunction(PyObject* self, PyObject* args, PyObject* kwargs) {
    PyObject* name = NULL;
    PyObject* parent = NULL;
    int inKwargs = 0;
    // Pretend to do something with parent
    if (PyDict_GetItemString(kwargs, "parent")) {
        inKwargs++;
        PyDict_DelItemString(kwargs, "parent");
    }
    // Pretend to do something with name
    if (PyDict_GetItemString(kwargs, "name")) {
        inKwargs++;
        PyDict_DelItemString(kwargs, "name");
    }
    // Not sure if -1 works here
    PyObject* newArgs = PyTuple_GetSlice(args, inKwargs, -1); // this is *args
    // the remaining kwargs can be used as **kwargs
}

最佳答案

在 C API 中,PyObject* args确实是一个 Python 元组,而且 PyObject* kwargs真的是一本 Python 字典。至少是这样 PyArg_ParseTupleAndKeywords internally要求:

int PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *keywords, const char *format, char **kwlist, ...)
{
    // …
    if ((args == NULL || !PyTuple_Check(args)) ||
        (keywords != NULL && !PyDict_Check(keywords)) ||
        format == NULL ||
        kwlist == NULL)
    {
        PyErr_BadInternalCall();
        return 0;
    }

    // …
}

该函数在 vgetargskeywords 中的实际实现也再次断言这一点,所以你应该可以更换你的 PyArg_ParseTupleAndKeywords从对象中手动提取调用。

这意味着您可以同时使用 tupledict API,或使用 iterator protocol迭代这些对象中的项目。

关于python-3.x - Python C 扩展中的真 *args 和 **kwargs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35820661/

相关文章:

c++ - 在 C++ 程序中调用 Python 函数

Python:返回多个值的 C++ 扩展

python - 带有 __init__.pyx : Possible? 的 Cython 包

Python C 扩展 : Extract parameter from the engine

python - Flask Restful 解析 POST 数据

python - 如何将 Pandas DataFrame 转换为三层嵌套字典?

python - 通过字典理解创建具有列表值的字典?

python - 填充作为参数传递给 C 函数的 Python 列表

Python CExtension 给出 ModuleNotFoundError

python - 为什么我得到的是生成器对象而不是整数?