Как работает PyArg ParseTupleAndKeywords?
Я пытаюсь научиться писать C-расширения для Python и хочу быть уверенным, что понимаю, как работает PyArg_ParseTupleAndKeywords.
Я считаю, что первый аргумент-это указатель PyObject, который указывает на массив аргументов, передаваемых в функцию расширения C в том порядке, в котором они были переданы. Второй аргумент-это список ключевых слов, которые были переданы, позиции, в которых они были переданы, и, очень вероятно, какой-то флаг индикатора, указывающий, в какой позиции они были переданы. ключевые слова начинаются, и позиция становится неуместной.
PyArg_ParseTupleAndKeywords затем использует свой список ключевых слов (4-й аргумент) для сопоставления между аргументами, указанными с ключевым словом, и как строкой формата (3-й аргумент), так и адресами переменных C (5-й и + аргументы), в которые должны быть скопированы соответствующие значения.
Верно ли мое понимание? Когда я читаю онлайн-документацию, все, что я вижу, - это ссылки на "позиционные Аргументы и аргументы ключевых слов", которые оставь меня чувствовать себя немного в темноте. Где находится файл для интерпретатора Python, который обрабатывает PyArg_ParseTupleAndKeywords?
2 ответа:
Вы читали вступительное объяснение в http://docs.python.org/c-api/arg.html ? Это довольно хорошо объясняет, что происходит. Не переходите сразу к конкретной ссылке на
PyArg_ParseTupleAndKeywords
; она предполагает, что Вы читаете текст выше, и сама по себе не очень полезна.Впрочем, ты почти все понял. Первый аргумент-это действительно список входящих позиционных аргументов. Второй-это отображение входящих аргументов ключевого слова (сопоставление заданного имени ключевого слова с заданным значением). То четвертый аргумент-это фактически список ключевых слов, которые ваша функция готова принять. Да, 3-й аргумент-это строка формата, а 5-й и более поздние-это указатели C, в которые копируются значения.
Вы найдете
PyArg_ParseTupleAndKeywords()
подPython/getargs.c
.
Для эмуляции следующего в python:
def keywords(a, b, foo=None, bar=None, baz=None): pass
Будет работать следующее:
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}И использовать его:
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')