我正在开发 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
从对象中手动提取调用。这意味着您可以同时使用 tuple和 dict API,或使用 iterator protocol迭代这些对象中的项目。
关于python-3.x - Python C 扩展中的真 *args 和 **kwargs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35820661/