Как вернуть кортеж, содержащий значение None из C API?


Как правильно вернуть кортеж, содержащий значение None из расширения C в Python? Я знаю, что одно значение None может быть создано с помощью

result = Py_BuildValue("");

И что кортеж может быть создан с помощью чего-то вроде

result = Py_BuildValue("(ii)", 123, 456);
Но я не вижу способа объединить это, чтобы получить, например, кортеж, содержащий собственное целое число и значение None.
2 3

2 ответа:

В Python есть только один объект None, и вы всегда можете ссылаться на него в C как Py_None.

Код...

result = Py_BuildValue("");

...просто увеличивает количество ссылок Py_None и возвращает его указатель, так что это то же самое, что...

Py_INCREF(Py_None);
result = Py_None;

Если вы просто хотите вернуть None, то используйте...

Py_INCREF(Py_None);
return Py_None;

...или, начиная с Python 2.4, вы можете сделать то же самое с макросом...

Py_RETURN_NONE;

Если вы возвращаете его в кортеже, как это...

return Py_BuildValue("(O)", Py_None);

...нет необходимо увеличить количество ссылок - Py_BuildValue() делает это для тебя.

Но если вы вернете его в таком кортеже, как этот...
PyObject* tuple = PyTuple_New(1);
Py_INCREF(Py_None);
PyTuple_SetItem(tuple, 0, Py_None);
return tuple;

...затем вы должны увеличить количество ссылок, потому что PyTuple_SetItem() не делает этого для тебя.

result = Py_BuildValue("(isi)", 123, NULL, 456);

Ref.: http://docs.python.org/2/c-api/arg.html#Py_BuildValue