问题
I am developing Python 3 C extension.
Can I get the equivalent or arbitrary positional or keyword arguments?
For instance, in Python, I can write:
def fun(name, parent, *args, **kwargs):
# do something with name and parent
# do something with args and kwargs
pass
But I cannot find of a simple equivalent in C. While we can perfectly write functions with PyObject* args
and PyObject* kwargs
, I cannot easily "parse out" name and parent from whichever (args/kwargs) it came.
Take:
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 */
}
A "manual" approach that I could think of looks roughly like:
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
}
回答1:
In the C API, PyObject* args
really is a Python tuple, and PyObject* kwargs
really is a Python dictionary. At least that is what PyArg_ParseTupleAndKeywords internally requires:
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;
}
// …
}
The actual implementation of that function in vgetargskeywords also asserts this again, so you should be fine with replacing your PyArg_ParseTupleAndKeywords
call with manual extraction from the objects.
This means that you can use both the tuple and dict APIs, or use the iterator protocol to iterate over the items in these objects.
来源:https://stackoverflow.com/questions/35820661/true-args-and-kwargs-in-python-c-extension