Pregunta

I've been trying to learn how to write C-extensions for Python and want to be sure I understand how PyArg_ParseTupleAndKeywords works.

I believe that the first argument is a PyObject pointer that points to an array of the arguments being passed into the C-extension function in the order they were passed. The second argument is a list of keywords that were passed, the positions at which they were passed and, very likely, some sort of indicator flag telling at which position the keywords begin and position becomes irrelevant.

PyArg_ParseTupleAndKeywords then uses its list of keywords (4th argument) to map between arguments specified with a keyword and both the format string (3rd argument) and addresses of C variables (5th & + arguments) to which the appropriate values should be copied.

Is my understanding correct? When I read through the online documentation, all I see are references to "positional arguments and keyword arguments", which leave me feeling a little bit in the dark. Where is the file for the Python interpreter that handles PyArg_ParseTupleAndKeywords?

¿Fue útil?

Solución

Have you read through the opening explanation at http://docs.python.org/c-api/arg.html ? It does a pretty good job of explaining what's going on. Don't go right to the specific reference for PyArg_ParseTupleAndKeywords; it assumes you read the text above, and isn't very helpful by itself.

You've almost got it, though. The first argument is indeed a list of incoming positional arguments. The second is a map of incoming keyword arguments (mapping given keyword name to given value). The fourth argument is actually the list of keywords which your function is prepared to accept. Yes, the 3rd argument is the format string and the 5th and later are C pointers into which the values are copied.

You'll find PyArg_ParseTupleAndKeywords() under Python/getargs.c.

Otros consejos

To emulate the following in python:

def keywords(a, b, foo=None, bar=None, baz=None):
    pass

The following will work:

static PyObject *keywords(PyObject *self, PyObject *args, PyObject *kwargs)
{
    char *a;
    char *b;
    char *foo = NULL;
    char *bar = NULL;
    char *baz = NULL;

    // Note how "a" and "b" are included in this
    // even though they aren't supposed to be in kwargs like in python
    static char *kwlist[] = {"a", "b", "foo", "bar", "baz", NULL};

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|sss", kwlist, 
                                     &a, &b, &foo, &bar, &baz)) 
    {
        return NULL;
    }

    printf("a is %s\n", a);
    printf("b is %s\n", b);
    printf("foo is %s\n", foo);
    printf("bar is %s\n", bar);
    printf("baz is %s\n", baz);

    Py_RETURN_NONE;
}

// ...

static PyMethodDef SpamMethods[] = 
{
    // ...
    {"keywords", (PyCFunction) keywords, METH_VARARGS | METH_KEYWORDS, "practice kwargs"},
    {NULL, NULL, 0, NULL}
    // ...
}

And to use it:

from spam import keywords

keywords()         # Fails, require a and b
keywords('a')      # fails, requires b
keywords('a', 'b')
keywords('a', 'b', foo='foo', bar='bar', baz='baz') 
keywords('a', 'b','foo', 'bar', 'baz')
keywords(a='a', b='b', foo='foo', bar='bar', baz='baz')
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top