Документация Python неофициальный перевод

call.md

281 строк · 26.3 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.11/c-api/call.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Протокол вызова89CPython поддерживает два протокола вызова: *tp\_call* и vectorcall.1011## *tp\_call*1213Экземпляры классов, в которых задан [`tp_call`](https://python-all.ru/3.11/c-api/typeobj.html#c.PyTypeObject.tp_call), являются вызываемыми. Сигнатура слота:1415```c16PyObject *tp_call(PyObject *callable, PyObject *args, PyObject *kwargs);17```1819Вызов производится с использованием кортежа для позиционных аргументов и словаря для именованных аргументов, аналогично `callable(*args, **kwargs)` в коде Python. *args* должно быть не NULL (используйте пустой кортеж, если аргументов нет), но *kwargs* может быть *NULL*, если именованные аргументы отсутствуют.2021Это соглашение используется не только в *tp\_call*: [`tp_new`](https://python-all.ru/3.11/c-api/typeobj.html#c.PyTypeObject.tp_new) и [`tp_init`](https://python-all.ru/3.11/c-api/typeobj.html#c.PyTypeObject.tp_init) также передают аргументы таким образом.2223Для вызова объекта используйте [`PyObject_Call()`](https://python-all.ru/3.11/c-api/call.html#c.PyObject_Call) или другой [API вызова](https://python-all.ru/3.11/c-api/call.html#capi-call).2425## Протокол Vectorcall2627Новое в версии 3.9.2829Протокол vectorcall был представлен в [**PEP 590**](https://python-all.ru/3.11/c-api/call.html) как дополнительный протокол для повышения эффективности вызовов.3031Как правило, CPython предпочитает vectorcall для внутренних вызовов, если вызываемый объект его поддерживает. Однако это не жёсткое правило. Кроме того, некоторые сторонние расширения используют *tp\_call* напрямую (вместо [`PyObject_Call()`](https://python-all.ru/3.11/c-api/call.html#c.PyObject_Call)). Поэтому класс, поддерживающий vectorcall, должен также реализовывать [`tp_call`](https://python-all.ru/3.11/c-api/typeobj.html#c.PyTypeObject.tp_call). Более того, вызываемый объект должен вести себя одинаково независимо от используемого протокола. Рекомендуемый способ добиться этого – задать [`tp_call`](https://python-all.ru/3.11/c-api/typeobj.html#c.PyTypeObject.tp_call) равным [`PyVectorcall_Call()`](https://python-all.ru/3.11/c-api/call.html#c.PyVectorcall_Call). Это стоит повторить:3233> **Предупреждение**34>35> Класс, поддерживающий vectorcall, **должен** также реализовывать [`tp_call`](https://python-all.ru/3.11/c-api/typeobj.html#c.PyTypeObject.tp_call) с той же семантикой.3637Класс не должен реализовывать vectorcall, если это будет медленнее, чем *tp\_call*. Например, если вызываемая сторона всё равно должна преобразовывать аргументы в кортеж args и словарь kwargs, то нет смысла реализовывать vectorcall.3839Классы могут реализовать протокол vectorcall, установив флаг [`Py_TPFLAGS_HAVE_VECTORCALL`](https://python-all.ru/3.11/c-api/typeobj.html#c.Py_TPFLAGS_HAVE_VECTORCALL) и задав [`tp_vectorcall_offset`](https://python-all.ru/3.11/c-api/typeobj.html#c.PyTypeObject.tp_vectorcall_offset) в качестве смещения внутри структуры объекта, где находится *vectorcallfunc*. Это указатель на функцию со следующей сигнатурой:4041#### `typedef PyObject *(*vectorcallfunc)(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)`4243- *callable* – это вызываемый объект.44- ***args* – это массив C, состоящий из позиционных аргументов, за которыми следуют**4546  значения именованных аргументов. Может быть *NULL*, если аргументов нет.47- ***nargsf* – это количество позиционных аргументов плюс, возможно,**4849  флаг [`PY_VECTORCALL_ARGUMENTS_OFFSET`](https://python-all.ru/3.11/c-api/call.html#c.PY_VECTORCALL_ARGUMENTS_OFFSET). Чтобы получить фактическое количество позиционных аргументов из *nargsf*, используйте [`PyVectorcall_NARGS()`](https://python-all.ru/3.11/c-api/call.html#c.PyVectorcall_NARGS).50- ***kwnames* – это кортеж, содержащий имена именованных аргументов;**5152  другими словами, ключи словаря kwargs. Эти имена должны быть строками (экземплярами `str` или подкласса) и они должны быть уникальными. Если именованных аргументов нет, то *kwnames* может быть *NULL*.5354#### `PY_VECTORCALL_ARGUMENTS_OFFSET`5556Если этот флаг установлен в аргументе vectorcall *nargsf*, вызываемой стороне разрешается временно изменить `args[-1]`. Иными словами, *args* указывает на аргумент 1 (а не 0) в выделенном векторе. Вызываемая сторона должна восстановить значение `args[-1]` перед возвратом.5758Для [`PyObject_VectorcallMethod()`](https://python-all.ru/3.11/c-api/call.html#c.PyObject_VectorcallMethod) этот флаг, напротив, означает, что `args[0]` может быть изменён.5960Если это можно сделать дёшево (без дополнительных выделений памяти), вызывающим сторонам рекомендуется использовать [`PY_VECTORCALL_ARGUMENTS_OFFSET`](https://python-all.ru/3.11/c-api/call.html#c.PY_VECTORCALL_ARGUMENTS_OFFSET). Это позволит таким вызываемым объектам, как связанные методы, выполнять последующие вызовы (которые включают добавленный аргумент *self*) очень эффективно.6162Новое в версии 3.8.6364Для вызова объекта, реализующего vectorcall, используйте функцию [call API](https://python-all.ru/3.11/c-api/call.html#capi-call), как и для любого другого вызываемого объекта. Обычно наиболее эффективным будет [`PyObject_Vectorcall()`](https://python-all.ru/3.11/c-api/call.html#c.PyObject_Vectorcall).6566> **Примечание**67>68> В CPython 3.8 API vectorcall и связанные функции были доступны временно под именами с ведущим подчеркиванием: `_PyObject_Vectorcall`, `_Py_TPFLAGS_HAVE_VECTORCALL`, `_PyObject_VectorcallMethod`, `_PyVectorcall_Function`, `_PyObject_CallOneArg`, `_PyObject_CallMethodNoArgs`, `_PyObject_CallMethodOneArg`. Кроме того, `PyObject_VectorcallDict` был доступен как `_PyObject_FastCallDict`. Старые имена по-прежнему определены как псевдонимы новых имен без подчеркивания.6970### Управление рекурсией7172При использовании *tp\_call* вызываемым сторонам не нужно беспокоиться о [рекурсии](https://python-all.ru/3.11/c-api/exceptions.html#recursion): CPython использует [`Py_EnterRecursiveCall()`](https://python-all.ru/3.11/c-api/exceptions.html#c.Py_EnterRecursiveCall) и [`Py_LeaveRecursiveCall()`](https://python-all.ru/3.11/c-api/exceptions.html#c.Py_LeaveRecursiveCall) для вызовов, выполненных с помощью *tp\_call*.7374Для эффективности это не относится к вызовам, выполненным с помощью vectorcall: вызываемая сторона должна использовать *Py\_EnterRecursiveCall* и *Py\_LeaveRecursiveCall*, если это необходимо.7576### API поддержки Vectorcall7778#### `Py_ssize_t PyVectorcall_NARGS(size_t nargsf)`7980Получив аргумент vectorcall *nargsf*, возвращает фактическое количество аргументов. В настоящее время эквивалентно:8182```c83(Py_ssize_t)(nargsf & ~PY_VECTORCALL_ARGUMENTS_OFFSET)84```8586Однако следует использовать функцию `PyVectorcall_NARGS`, чтобы обеспечить возможность будущих расширений.8788Новое в версии 3.8.8990#### `vectorcallfunc PyVectorcall_Function(PyObject *op)`9192Если *op* не поддерживает протокол vectorcall (либо из-за того, что тип не поддерживает, либо конкретный экземпляр), возвращает *NULL*. В противном случае возвращает указатель на функцию vectorcall, сохранённый в *op*. Эта функция никогда не возбуждает исключения.9394Это в основном полезно для проверки, поддерживает ли *op* vectorcall, что можно сделать, проверив `PyVectorcall_Function(op) != NULL`.9596Новое в версии 3.9.9798#### `PyObject *PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *dict)`99100Вызывает [`vectorcallfunc`](https://python-all.ru/3.11/c-api/call.html#c.vectorcallfunc) объекта *callable* с позиционными и именованными аргументами, заданными в виде кортежа и словаря соответственно.101102Это специализированная функция, предназначенная для размещения в слоте [`tp_call`](https://python-all.ru/3.11/c-api/typeobj.html#c.PyTypeObject.tp_call) или использования в реализации `tp_call`. Она не проверяет флаг [`Py_TPFLAGS_HAVE_VECTORCALL`](https://python-all.ru/3.11/c-api/typeobj.html#c.Py_TPFLAGS_HAVE_VECTORCALL) и не обращается к `tp_call` в качестве запасного варианта.103104Новое в версии 3.8.105106## API вызова объектов107108Доступны различные функции для вызова объекта Python. Каждая преобразует свои аргументы в соглашение, поддерживаемое вызываемым объектом – *tp\_call* или vectorcall. Чтобы выполнить как можно меньше преобразований, выбирайте ту, которая лучше всего подходит под формат имеющихся у вас данных.109110В следующей таблице приведены доступные функции; подробнее см. в документации для каждой из них.111112| Функция | вызываемый | аргументы | именованные аргументы |113| --- | --- | --- | --- |114| [`PyObject_Call()`](https://python-all.ru/3.11/c-api/call.html#c.PyObject_Call) | `PyObject *` | кортеж | словарь/`NULL` |115| [`PyObject_CallNoArgs()`](https://python-all.ru/3.11/c-api/call.html#c.PyObject_CallNoArgs) | `PyObject *` | – | – |116| [`PyObject_CallOneArg()`](https://python-all.ru/3.11/c-api/call.html#c.PyObject_CallOneArg) | `PyObject *` | 1 объект | – |117| [`PyObject_CallObject()`](https://python-all.ru/3.11/c-api/call.html#c.PyObject_CallObject) | `PyObject *` | кортеж/`NULL` | – |118| [`PyObject_CallFunction()`](https://python-all.ru/3.11/c-api/call.html#c.PyObject_CallFunction) | `PyObject *` | формат | – |119| [`PyObject_CallMethod()`](https://python-all.ru/3.11/c-api/call.html#c.PyObject_CallMethod) | объект + `char*` | формат | – |120| [`PyObject_CallFunctionObjArgs()`](https://python-all.ru/3.11/c-api/call.html#c.PyObject_CallFunctionObjArgs) | `PyObject *` | вариативный | – |121| [`PyObject_CallMethodObjArgs()`](https://python-all.ru/3.11/c-api/call.html#c.PyObject_CallMethodObjArgs) | объект + имя | вариативный | – |122| [`PyObject_CallMethodNoArgs()`](https://python-all.ru/3.11/c-api/call.html#c.PyObject_CallMethodNoArgs) | объект + имя | – | – |123| [`PyObject_CallMethodOneArg()`](https://python-all.ru/3.11/c-api/call.html#c.PyObject_CallMethodOneArg) | объект + имя | 1 объект | – |124| [`PyObject_Vectorcall()`](https://python-all.ru/3.11/c-api/call.html#c.PyObject_Vectorcall) | `PyObject *` | vectorcall | vectorcall |125| [`PyObject_VectorcallDict()`](https://python-all.ru/3.11/c-api/call.html#c.PyObject_VectorcallDict) | `PyObject *` | vectorcall | словарь/`NULL` |126| [`PyObject_VectorcallMethod()`](https://python-all.ru/3.11/c-api/call.html#c.PyObject_VectorcallMethod) | аргумент + имя | vectorcall | vectorcall |127128#### `PyObject *PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)`129130*Возвращаемое значение: новая ссылка.*131132*Часть [Stable ABI](https://python-all.ru/3.11/c-api/stable.html#stable).*133134Вызывает вызываемый объект Python *callable* с аргументами, заданными кортежем *args*, и именованными аргументами, заданными словарём *kwargs*.135136*args* не должен быть *NULL*; используйте пустой кортеж, если аргументы не нужны. Если именованные аргументы не нужны, *kwargs* может быть *NULL*.137138Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.139140Это эквивалент выражения Python: `callable(*args, **kwargs)`.141142#### `PyObject *PyObject_CallNoArgs(PyObject *callable)`143144*Возвращаемое значение: новая ссылка.*145146*Часть [Stable ABI](https://python-all.ru/3.11/c-api/stable.html#stable) начиная с версии 3.10.*147148Вызывает вызываемый объект Python *callable* без аргументов. Это самый эффективный способ вызова вызываемого объекта Python без аргументов.149150Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.151152Новое в версии 3.9.153154#### `PyObject *PyObject_CallOneArg(PyObject *callable, PyObject *arg)`155156*Возвращаемое значение: новая ссылка.*157158Вызывает вызываемый объект Python *callable* ровно с одним позиционным аргументом *arg* и без именованных аргументов.159160Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.161162Новое в версии 3.9.163164#### `PyObject *PyObject_CallObject(PyObject *callable, PyObject *args)`165166*Возвращаемое значение: новая ссылка.*167168*Часть [Stable ABI](https://python-all.ru/3.11/c-api/stable.html#stable).*169170Вызывает вызываемый объект Python *callable* с аргументами, заданными кортежем *args*. Если аргументы не нужны, *args* может быть *NULL*.171172Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.173174Это эквивалент выражения Python: `callable(*args)`.175176#### `PyObject *PyObject_CallFunction(PyObject *callable, const char *format, ...)`177178*Возвращаемое значение: новая ссылка.*179180*Часть [Stable ABI](https://python-all.ru/3.11/c-api/stable.html#stable).*181182Вызывает вызываемый объект Python *callable* с переменным числом аргументов C. Аргументы C описываются строкой формата в стиле [`Py_BuildValue()`](https://python-all.ru/3.11/c-api/arg.html#c.Py_BuildValue). Формат может быть *NULL*, что означает, что аргументы не предоставлены.183184Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.185186Это эквивалент выражения Python: `callable(*args)`.187188Обратите внимание, что если передавать только аргументы [PyObject](https://python-all.ru/3.11/c-api/structures.html#c.PyObject)\*, то [`PyObject_CallFunctionObjArgs()`](https://python-all.ru/3.11/c-api/call.html#c.PyObject_CallFunctionObjArgs) будет более быстрой альтернативой.189190Изменено в версии 3.4: Тип *format* был изменён с `char *`.191192#### `PyObject *PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...)`193194*Возвращаемое значение: новая ссылка.*195196*Часть [Stable ABI](https://python-all.ru/3.11/c-api/stable.html#stable).*197198Вызывает метод с именем *name* объекта *obj* с переменным числом аргументов C. Аргументы C описываются строкой формата [`Py_BuildValue()`](https://python-all.ru/3.11/c-api/arg.html#c.Py_BuildValue), которая должна порождать кортеж.199200Формат может быть *NULL*, что означает, что аргументы не предоставлены.201202Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.203204Это эквивалент выражения Python: `obj.name(arg1, arg2, ...)`.205206Обратите внимание, что если передавать только аргументы [PyObject](https://python-all.ru/3.11/c-api/structures.html#c.PyObject)\*, то [`PyObject_CallMethodObjArgs()`](https://python-all.ru/3.11/c-api/call.html#c.PyObject_CallMethodObjArgs) будет более быстрой альтернативой.207208Изменено в версии 3.4: Типы *name* и *format* были изменены с `char *`.209210#### `PyObject *PyObject_CallFunctionObjArgs(PyObject *callable, ...)`211212*Возвращаемое значение: новая ссылка.*213214*Часть [Stable ABI](https://python-all.ru/3.11/c-api/stable.html#stable).*215216Вызывает вызываемый объект Python *callable* с переменным числом аргументов [PyObject](https://python-all.ru/3.11/c-api/structures.html#c.PyObject)\*. Аргументы передаются как переменное число параметров, за которым следует *NULL*.217218Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.219220Это эквивалент выражения Python: `callable(arg1, arg2, ...)`.221222#### `PyObject *PyObject_CallMethodObjArgs(PyObject *obj, PyObject *name, ...)`223224*Возвращаемое значение: новая ссылка.*225226*Часть [Stable ABI](https://python-all.ru/3.11/c-api/stable.html#stable).*227228Вызывает метод объекта Python *obj*, где имя метода задаётся как строковый объект Python в *name*. Он вызывается с переменным числом аргументов [PyObject](https://python-all.ru/3.11/c-api/structures.html#c.PyObject)\*. Аргументы передаются как переменное число параметров, за которым следует *NULL*.229230Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.231232#### `PyObject *PyObject_CallMethodNoArgs(PyObject *obj, PyObject *name)`233234Вызывает метод объекта Python *obj* без аргументов, где имя метода задаётся как строковый объект Python в *name*.235236Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.237238Новое в версии 3.9.239240#### `PyObject *PyObject_CallMethodOneArg(PyObject *obj, PyObject *name, PyObject *arg)`241242Вызывает метод объекта Python *obj* с одним позиционным аргументом *arg*, где имя метода задаётся как строковый объект Python в *name*.243244Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.245246Новое в версии 3.9.247248#### `PyObject *PyObject_Vectorcall(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)`249250Вызывает вызываемый объект Python *callable*. Аргументы те же, что и для [`vectorcallfunc`](https://python-all.ru/3.11/c-api/call.html#c.vectorcallfunc). Если *callable* поддерживает [vectorcall](https://python-all.ru/3.11/c-api/call.html#vectorcall), то эта функция напрямую вызывает функцию vectorcall, хранящуюся в *callable*.251252Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.253254Новое в версии 3.9.255256#### `PyObject *PyObject_VectorcallDict(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwdict)`257258Вызывает *callable* с позиционными аргументами, передаваемыми точно так же, как в протоколе [vectorcall](https://python-all.ru/3.11/c-api/call.html#vectorcall), но с именованными аргументами, передаваемыми в виде словаря *kwdict*. Массив *args* содержит только позиционные аргументы.259260Независимо от того, какой протокол используется внутри, требуется выполнить преобразование аргументов. Поэтому эту функцию следует использовать только в том случае, если у вызывающего кода уже есть словарь, готовый для именованных аргументов, но нет кортежа для позиционных аргументов.261262Новое в версии 3.9.263264#### `PyObject *PyObject_VectorcallMethod(PyObject *name, PyObject *const *args, size_t nargsf, PyObject *kwnames)`265266Вызывает метод, используя соглашение о вызове vectorcall. Имя метода задаётся в виде строки Python *name*. Объект, чей метод вызывается – это *args\[0\]*, а массив *args*, начиная с *args\[1\]*, представляет аргументы вызова. Должен присутствовать хотя бы один позиционный аргумент. *nargsf* – это количество позиционных аргументов, включая *args\[0\]*, плюс [`PY_VECTORCALL_ARGUMENTS_OFFSET`](https://python-all.ru/3.11/c-api/call.html#c.PY_VECTORCALL_ARGUMENTS_OFFSET), если значение `args[0]` может временно изменяться. Именованные аргументы можно передавать так же, как в [`PyObject_Vectorcall()`](https://python-all.ru/3.11/c-api/call.html#c.PyObject_Vectorcall).267268Если объект обладает возможностью [`Py_TPFLAGS_METHOD_DESCRIPTOR`](https://python-all.ru/3.11/c-api/typeobj.html#c.Py_TPFLAGS_METHOD_DESCRIPTOR), то будет вызван непривязанный объект метода с полным вектором *args* в качестве аргументов.269270Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.271272Новое в версии 3.9.273274## API поддержки вызова275276#### `int PyCallable_Check(PyObject *o)`277278*Часть [Stable ABI](https://python-all.ru/3.11/c-api/stable.html#stable).*279280Определяет, является ли объект *o* вызываемым. Возвращает `1`, если объект вызываем, и `0` в противном случае. Эта функция всегда завершается успешно.281