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

call.md

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

1> **Источник:** https://python-all.ru/3.10/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.10/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.10/c-api/typeobj.html#c.PyTypeObject.tp_new) и [`tp_init`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_init) также передают аргументы таким образом.2223Для вызова объекта используйте [`PyObject_Call()`](https://python-all.ru/3.10/c-api/call.html#c.PyObject_Call) или другой [API вызова](https://python-all.ru/3.10/c-api/call.html#capi-call).2425## Протокол Vectorcall2627Новое в версии 3.9.2829Протокол vectorcall был представлен в [**PEP 590**](https://python-all.ru/3.10/c-api/call.html) как дополнительный протокол для повышения эффективности вызовов.3031Как правило, CPython предпочитает vectorcall для внутренних вызовов, если вызываемый объект его поддерживает. Однако это не жёсткое правило. Кроме того, некоторые сторонние расширения используют *tp\_call* напрямую (вместо [`PyObject_Call()`](https://python-all.ru/3.10/c-api/call.html#c.PyObject_Call)). Поэтому класс, поддерживающий vectorcall, должен также реализовывать [`tp_call`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_call). Более того, вызываемый объект должен вести себя одинаково независимо от используемого протокола. Рекомендуемый способ добиться этого – задать [`tp_call`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_call) равным [`PyVectorcall_Call()`](https://python-all.ru/3.10/c-api/call.html#c.PyVectorcall_Call). Это стоит повторить:3233> **Предупреждение**34>35> Класс, поддерживающий vectorcall, **должен** также реализовывать [`tp_call`](https://python-all.ru/3.10/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.10/c-api/typeobj.html#Py_TPFLAGS_HAVE_VECTORCALL) и задав [`tp_vectorcall_offset`](https://python-all.ru/3.10/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`. Чтобы получить фактическое количество позиционных аргументов из *nargsf*, используйте [`PyVectorcall_NARGS()`](https://python-all.ru/3.10/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.10/c-api/call.html#c.PyObject_VectorcallMethod) этот флаг, напротив, означает, что `args[0]` может быть изменён.5960Если это можно сделать дёшево (без дополнительных выделений памяти), вызывающим сторонам рекомендуется использовать `PY_VECTORCALL_ARGUMENTS_OFFSET`. Это позволит таким вызываемым объектам, как связанные методы, выполнять последующие вызовы (которые включают добавленный аргумент *self*) очень эффективно.6162Для вызова объекта, реализующего vectorcall, используйте функцию [call API](https://python-all.ru/3.10/c-api/call.html#capi-call), как и для любого другого вызываемого объекта. Обычно наиболее эффективным будет [`PyObject_Vectorcall()`](https://python-all.ru/3.10/c-api/call.html#c.PyObject_Vectorcall).6364> **Примечание**65>66> В 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`. Старые имена по-прежнему определены как псевдонимы новых имен без подчеркивания.6768### Управление рекурсией6970При использовании *tp\_call* вызываемым сторонам не нужно беспокоиться о [рекурсии](https://python-all.ru/3.10/c-api/exceptions.html#recursion): CPython использует [`Py_EnterRecursiveCall()`](https://python-all.ru/3.10/c-api/exceptions.html#c.Py_EnterRecursiveCall) и [`Py_LeaveRecursiveCall()`](https://python-all.ru/3.10/c-api/exceptions.html#c.Py_LeaveRecursiveCall) для вызовов, выполненных с помощью *tp\_call*.7172Для эффективности это не относится к вызовам, выполненным с помощью vectorcall: вызываемая сторона должна использовать *Py\_EnterRecursiveCall* и *Py\_LeaveRecursiveCall*, если это необходимо.7374### API поддержки Vectorcall7576#### `Py_ssize_t PyVectorcall_NARGS(size_t nargsf)`7778Получив аргумент vectorcall *nargsf*, возвращает фактическое количество аргументов. В настоящее время эквивалентно:7980```c81(Py_ssize_t)(nargsf & ~PY_VECTORCALL_ARGUMENTS_OFFSET)82```8384Однако следует использовать функцию `PyVectorcall_NARGS`, чтобы обеспечить возможность будущих расширений.8586Новое в версии 3.8.8788#### `vectorcallfunc PyVectorcall_Function(PyObject *op)`8990Если *op* не поддерживает протокол vectorcall (либо из-за того, что тип не поддерживает, либо конкретный экземпляр), возвращает *NULL*. В противном случае возвращает указатель на функцию vectorcall, сохранённый в *op*. Эта функция никогда не возбуждает исключения.9192Это в основном полезно для проверки, поддерживает ли *op* vectorcall, что можно сделать, проверив `PyVectorcall_Function(op) != NULL`.9394Новое в версии 3.8.9596#### `PyObject *PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *dict)`9798Вызывает [`vectorcallfunc`](https://python-all.ru/3.10/c-api/call.html#c.vectorcallfunc) объекта *callable* с позиционными и именованными аргументами, заданными в виде кортежа и словаря соответственно.99100Это специализированная функция, предназначенная для размещения в слоте [`tp_call`](https://python-all.ru/3.10/c-api/typeobj.html#c.PyTypeObject.tp_call) или использования в реализации `tp_call`. Она не проверяет флаг [`Py_TPFLAGS_HAVE_VECTORCALL`](https://python-all.ru/3.10/c-api/typeobj.html#Py_TPFLAGS_HAVE_VECTORCALL) и не обращается к `tp_call` в качестве запасного варианта.101102Новое в версии 3.8.103104## API вызова объектов105106Доступны различные функции для вызова объекта Python. Каждая преобразует свои аргументы в соглашение, поддерживаемое вызываемым объектом – *tp\_call* или vectorcall. Чтобы выполнить как можно меньше преобразований, выбирайте ту, которая лучше всего подходит под формат имеющихся у вас данных.107108В следующей таблице приведены доступные функции; подробнее см. в документации для каждой из них.109110| Функция | вызываемый | аргументы | именованные аргументы |111| --- | --- | --- | --- |112| [`PyObject_Call()`](https://python-all.ru/3.10/c-api/call.html#c.PyObject_Call) | `PyObject *` | кортеж | словарь/`NULL` |113| [`PyObject_CallNoArgs()`](https://python-all.ru/3.10/c-api/call.html#c.PyObject_CallNoArgs) | `PyObject *` | – | – |114| [`PyObject_CallOneArg()`](https://python-all.ru/3.10/c-api/call.html#c.PyObject_CallOneArg) | `PyObject *` | 1 объект | – |115| [`PyObject_CallObject()`](https://python-all.ru/3.10/c-api/call.html#c.PyObject_CallObject) | `PyObject *` | кортеж/`NULL` | – |116| [`PyObject_CallFunction()`](https://python-all.ru/3.10/c-api/call.html#c.PyObject_CallFunction) | `PyObject *` | формат | – |117| [`PyObject_CallMethod()`](https://python-all.ru/3.10/c-api/call.html#c.PyObject_CallMethod) | объект + `char*` | формат | – |118| [`PyObject_CallFunctionObjArgs()`](https://python-all.ru/3.10/c-api/call.html#c.PyObject_CallFunctionObjArgs) | `PyObject *` | вариативный | – |119| [`PyObject_CallMethodObjArgs()`](https://python-all.ru/3.10/c-api/call.html#c.PyObject_CallMethodObjArgs) | объект + имя | вариативный | – |120| [`PyObject_CallMethodNoArgs()`](https://python-all.ru/3.10/c-api/call.html#c.PyObject_CallMethodNoArgs) | объект + имя | – | – |121| [`PyObject_CallMethodOneArg()`](https://python-all.ru/3.10/c-api/call.html#c.PyObject_CallMethodOneArg) | объект + имя | 1 объект | – |122| [`PyObject_Vectorcall()`](https://python-all.ru/3.10/c-api/call.html#c.PyObject_Vectorcall) | `PyObject *` | vectorcall | vectorcall |123| [`PyObject_VectorcallDict()`](https://python-all.ru/3.10/c-api/call.html#c.PyObject_VectorcallDict) | `PyObject *` | vectorcall | словарь/`NULL` |124| [`PyObject_VectorcallMethod()`](https://python-all.ru/3.10/c-api/call.html#c.PyObject_VectorcallMethod) | аргумент + имя | vectorcall | vectorcall |125126#### `PyObject *PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)`127128*Возвращаемое значение: новая ссылка.*129130*Часть [Stable ABI](https://python-all.ru/3.10/c-api/stable.html#stable).*131132Вызывает вызываемый объект Python *callable* с аргументами, заданными кортежем *args*, и именованными аргументами, заданными словарём *kwargs*.133134*args* не должен быть *NULL*; используйте пустой кортеж, если аргументы не нужны. Если именованные аргументы не нужны, *kwargs* может быть *NULL*.135136Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.137138Это эквивалент выражения Python: `callable(*args, **kwargs)`.139140#### `PyObject *PyObject_CallNoArgs(PyObject *callable)`141142*Часть [Stable ABI](https://python-all.ru/3.10/c-api/stable.html#stable) начиная с версии 3.10.*143144Вызывает вызываемый объект Python *callable* без аргументов. Это самый эффективный способ вызова вызываемого объекта Python без аргументов.145146Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.147148Новое в версии 3.9.149150#### `PyObject *PyObject_CallOneArg(PyObject *callable, PyObject *arg)`151152Вызывает вызываемый объект Python *callable* ровно с одним позиционным аргументом *arg* и без именованных аргументов.153154Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.155156Новое в версии 3.9.157158#### `PyObject *PyObject_CallObject(PyObject *callable, PyObject *args)`159160*Возвращаемое значение: новая ссылка.*161162*Часть [Stable ABI](https://python-all.ru/3.10/c-api/stable.html#stable).*163164Вызывает вызываемый объект Python *callable* с аргументами, заданными кортежем *args*. Если аргументы не нужны, *args* может быть *NULL*.165166Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.167168Это эквивалент выражения Python: `callable(*args)`.169170#### `PyObject *PyObject_CallFunction(PyObject *callable, const char *format, ...)`171172*Возвращаемое значение: новая ссылка.*173174*Часть [Stable ABI](https://python-all.ru/3.10/c-api/stable.html#stable).*175176Вызывает вызываемый объект Python *callable* с переменным числом аргументов C. Аргументы C описываются строкой формата в стиле [`Py_BuildValue()`](https://python-all.ru/3.10/c-api/arg.html#c.Py_BuildValue). Формат может быть *NULL*, что означает, что аргументы не предоставлены.177178Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.179180Это эквивалент выражения Python: `callable(*args)`.181182Обратите внимание: если передаются только аргументы `PyObject*`, то [`PyObject_CallFunctionObjArgs()`](https://python-all.ru/3.10/c-api/call.html#c.PyObject_CallFunctionObjArgs) – более быстрая альтернатива.183184Изменено в версии 3.4: Тип *format* был изменён с `char *`.185186#### `PyObject *PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...)`187188*Возвращаемое значение: новая ссылка.*189190*Часть [Stable ABI](https://python-all.ru/3.10/c-api/stable.html#stable).*191192Вызывает метод с именем *name* объекта *obj* с переменным числом аргументов C. Аргументы C описываются строкой формата [`Py_BuildValue()`](https://python-all.ru/3.10/c-api/arg.html#c.Py_BuildValue), которая должна порождать кортеж.193194Формат может быть *NULL*, что означает, что аргументы не предоставлены.195196Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.197198Это эквивалент выражения Python: `obj.name(arg1, arg2, ...)`.199200Обратите внимание: если передаются только аргументы `PyObject*`, то [`PyObject_CallMethodObjArgs()`](https://python-all.ru/3.10/c-api/call.html#c.PyObject_CallMethodObjArgs) – более быстрая альтернатива.201202Изменено в версии 3.4: Типы *name* и *format* были изменены с `char *`.203204#### `PyObject *PyObject_CallFunctionObjArgs(PyObject *callable, ...)`205206*Возвращаемое значение: новая ссылка.*207208*Часть [Stable ABI](https://python-all.ru/3.10/c-api/stable.html#stable).*209210Вызов вызываемого объекта Python *callable* с переменным числом аргументов `PyObject*`. Аргументы передаются как переменное число параметров, после которых следует *NULL*.211212Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.213214Это эквивалент выражения Python: `callable(arg1, arg2, ...)`.215216#### `PyObject *PyObject_CallMethodObjArgs(PyObject *obj, PyObject *name, ...)`217218*Возвращаемое значение: новая ссылка.*219220*Часть [Stable ABI](https://python-all.ru/3.10/c-api/stable.html#stable).*221222Вызов метода объекта Python *obj*, где имя метода задаётся как объект строки Python в *name*. Метод вызывается с переменным числом аргументов `PyObject*`. Аргументы передаются как переменное число параметров, после которых следует *NULL*.223224Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.225226#### `PyObject *PyObject_CallMethodNoArgs(PyObject *obj, PyObject *name)`227228Вызывает метод объекта Python *obj* без аргументов, где имя метода задаётся как строковый объект Python в *name*.229230Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.231232Новое в версии 3.9.233234#### `PyObject *PyObject_CallMethodOneArg(PyObject *obj, PyObject *name, PyObject *arg)`235236Вызывает метод объекта Python *obj* с одним позиционным аргументом *arg*, где имя метода задаётся как строковый объект Python в *name*.237238Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.239240Новое в версии 3.9.241242#### `PyObject *PyObject_Vectorcall(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)`243244Вызывает вызываемый объект Python *callable*. Аргументы те же, что и для [`vectorcallfunc`](https://python-all.ru/3.10/c-api/call.html#c.vectorcallfunc). Если *callable* поддерживает [vectorcall](https://python-all.ru/3.10/c-api/call.html#vectorcall), то эта функция напрямую вызывает функцию vectorcall, хранящуюся в *callable*.245246Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.247248Новое в версии 3.9.249250#### `PyObject *PyObject_VectorcallDict(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwdict)`251252Вызывает *callable* с позиционными аргументами, передаваемыми точно так же, как в протоколе [vectorcall](https://python-all.ru/3.10/c-api/call.html#vectorcall), но с именованными аргументами, передаваемыми в виде словаря *kwdict*. Массив *args* содержит только позиционные аргументы.253254Независимо от того, какой протокол используется внутри, требуется выполнить преобразование аргументов. Поэтому эту функцию следует использовать только в том случае, если у вызывающего кода уже есть словарь, готовый для именованных аргументов, но нет кортежа для позиционных аргументов.255256Новое в версии 3.9.257258#### `PyObject *PyObject_VectorcallMethod(PyObject *name, PyObject *const *args, size_t nargsf, PyObject *kwnames)`259260Вызывает метод, используя соглашение о вызове vectorcall. Имя метода задаётся в виде строки Python *name*. Объект, чей метод вызывается – это *args\[0\]*, а массив *args*, начиная с *args\[1\]*, представляет аргументы вызова. Должен присутствовать хотя бы один позиционный аргумент. *nargsf* – это количество позиционных аргументов, включая *args\[0\]*, плюс `PY_VECTORCALL_ARGUMENTS_OFFSET`, если значение `args[0]` может временно изменяться. Именованные аргументы можно передавать так же, как в [`PyObject_Vectorcall()`](https://python-all.ru/3.10/c-api/call.html#c.PyObject_Vectorcall).261262Если объект обладает возможностью [`Py_TPFLAGS_METHOD_DESCRIPTOR`](https://python-all.ru/3.10/c-api/typeobj.html#Py_TPFLAGS_METHOD_DESCRIPTOR), то будет вызван непривязанный объект метода с полным вектором *args* в качестве аргументов.263264Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.265266Новое в версии 3.9.267268## API поддержки вызова269270#### `int PyCallable_Check(PyObject *o)`271272*Часть [Stable ABI](https://python-all.ru/3.10/c-api/stable.html#stable).*273274Определяет, является ли объект *o* вызываемым. Возвращает `1`, если объект вызываем, и `0` в противном случае. Эта функция всегда завершается успешно.275