Python C-API: использование `PySequence_Length` со словарями - PullRequest
2 голосов
/ 26 марта 2012

Я пытаюсь использовать PySequence_Length, чтобы получить длину словаря Python на C. Я понимаю, что могу использовать PyDict_Size, но мне интересно использовать более общую функцию в определенных контекстах.

PyObject* d = PyDict_New();
Py_ssize_t res = PySequence_Length(d);

printf("Result : %ld\n", res);
if (res == -1) PyErr_Print();

Это не удается, и печатается ошибка:

TypeError: объект типа 'dict' не имеет len ()

Мой вопрос: почему это не удается? Хотя объекты словаря Python не поддерживают протокол Sequence, документация для PySequence_Length гласит:

Py_ssize_t PySequence_Length (PyObject * o)

Возвращает количество объектов в последовательности o в случае успеха и -1 в случае успеха. отказ. Для объектов, которые не предоставляют протокол последовательности, это эквивалентно выражению Python len (o).

Так как тип словаря действительно имеет атрибут __len__, а выражение len(d) (где d - словарь) правильно возвращает длину в Python, я не понимаю, почему PySequence_Length должен потерпеть неудачу в C.

Есть объяснения? Документация здесь неверна?

1 Ответ

4 голосов
/ 27 марта 2012

Документация вводит в заблуждение, да.Диктовка не является последовательностью, даже если она реализует некоторые части протокола последовательности (для тестов на содержание, которые являются частью протокола последовательности.) Это особое различие в API типов Python / C вызывает сожаление, но это артефактВыбор дизайна сделан десятилетия назад.Документация отражает это различие, хотя и столь же неловко.Он пытается сказать, что для классов Python это то же самое, что и len(o), независимо от того, какой класс Python притворяется.Для типов C, если тип не реализует версию последовательности sizefunc, PySequence_Length() вызовет исключение, даже не учитывая, имеет ли тип отображающуюся версию sizefunc.

Если вы не совсем увереныесть ли у вас последовательность или нет, вы должны использовать PyObject_Size() вместо.На самом деле, очень мало причин для звонка PySequence_Length();обычно вы либо знаете тип (потому что вы только что создали его, и вы можете вызвать функцию длины или макрос определенного типа, например PyList_GET_SIZE()), либо вы даже не знаете, будет ли это последовательность.

...