2013-07-14 3 views
2

API Python/C имеет ряд связанных функций, которые выполняют аналогичные операции, где обычно используется для общего использования, а другое - как-то более эффективно или удобно для конкретной ситуации.Разница между PyInt_FromLong и Py_BuildValue

Например, PyDict_SetItem и PyDict_SetItemString те же, но последний специализирован для строки C в качестве ключа. Для PyList_SetItem и PyList_SET_ITEM второй не имеет проверки ошибок и не уменьшает существующий элемент (explained here).

Но в чем причина наличия специальных конверсий, таких как PyInt_FromLong, когда всегда есть Py_BuildValue? Оба возвращают новую ссылку на объект Python и, похоже, делают то же самое. Этот же вопрос относится к таким функциям, как PyInt_FromSsize_t, PyTuple_Pack и т. Д. (Все по сравнению с Py_BuildValue с соответствующей строкой формата).

Когда вы должны использовать один над другим?

+1

Вы можете увидеть 'Py_BuildValue' в результате [фасадного рисунка] (http://en.wikipedia.org/wiki/Facade_pattern). Это вызов высокого уровня, который объединяет множество вызовов низкого уровня. Это не требуется, но полезно. Очевидно, что с одной функцией «Py_BuildValue» без низкоуровневого API вы получите монстра сотен или более строк кода для поддержки, поэтому вы должны * делать все наоборот: иметь API-интерфейсы низкого уровня и фасадную функцию для доступа на высоком уровне, которая намного короче и удобна в обслуживании. – Bakuriu

ответ

4

Для меня это компромисс между производительностью и простотой. Для кода, который я написал, я предпочитаю использовать Py_BuildValue, когда мне не важно время выполнения (т. Е. Возврат набора значений, которые не будут меняться, или время работы настолько велико, что дополнительные накладные расходы не имеют значения .) Для критически важных функций, особенно тех, которые могут быть на самом внутреннем уровне цикла, я буду использовать API API самого низкого уровня, который я могу использовать.

Стоит ли это или нет, это другой вопрос. Я никогда не откажусь от времени, потраченного на достижение максимальной производительности, но я знаю, что другие приложения, которые используют мой код, значительно быстрее.

+0

Почему 'Py_BuildValue' проще? Для этого требуется еще несколько нажатий клавиш. И если 'PyInt_FromLong' работает быстрее, почему' Py_BuildValue' просто вызывает это напрямую? – Jared

+2

Я использую 'Py_BuildValue', когда хочу создать кортеж, обычно как возвращаемое значение функции, но также при вызове других функций C API. При возврате кортежа из критической функции производительности я фактически создаю пустой кортеж, а затем задаю значения кортежа. Это быстрее, чем вызов 'Py_BuildValue (" (NN) ", ...)', но требует больше строк кода. Когда вы создаете только одно значение, я всегда использую функцию низкого уровня напрямую. 'Py_BuildValue' действительно вызывает' PyInt_FromLong', но сначала он должен разбирать строку, проверять, сколько значений необходимо и т. Д. Это немного медленнее. – casevh

+0

Спасибо. Ваш комментарий, наряду с Бакуриу, был настоящим ответом, который я искал, но я по-прежнему буду отмечать это как правильный ответ. – Jared