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

call.md

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

1> **Источник:** https://python-all.ru/3.9/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.9/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.9/c-api/typeobj.html#c.PyTypeObject.tp_new) и [`tp_init`](https://python-all.ru/3.9/c-api/typeobj.html#c.PyTypeObject.tp_init) также передают аргументы таким образом.2223Для вызова объекта используйте [`PyObject_Call()`](https://python-all.ru/3.9/c-api/call.html#c.PyObject_Call) или другой [API вызова](https://python-all.ru/3.9/c-api/call.html#capi-call).2425## Протокол Vectorcall2627Новое в версии 3.9.2829Протокол vectorcall был представлен в [**PEP 590**](https://python-all.ru/3.9/c-api/call.html) как дополнительный протокол для повышения эффективности вызовов.3031Как правило, CPython предпочитает vectorcall для внутренних вызовов, если вызываемый объект его поддерживает. Однако это не жёсткое правило. Кроме того, некоторые сторонние расширения используют *tp\_call* напрямую (вместо [`PyObject_Call()`](https://python-all.ru/3.9/c-api/call.html#c.PyObject_Call)). Поэтому класс, поддерживающий vectorcall, должен также реализовывать [`tp_call`](https://python-all.ru/3.9/c-api/typeobj.html#c.PyTypeObject.tp_call). Более того, вызываемый объект должен вести себя одинаково независимо от используемого протокола. Рекомендуемый способ добиться этого – задать [`tp_call`](https://python-all.ru/3.9/c-api/typeobj.html#c.PyTypeObject.tp_call) равным [`PyVectorcall_Call()`](https://python-all.ru/3.9/c-api/call.html#c.PyVectorcall_Call). Это стоит повторить:3233> **Предупреждение**34>35> Класс, поддерживающий vectorcall, **должен** также реализовывать [`tp_call`](https://python-all.ru/3.9/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.9/c-api/typeobj.html#Py_TPFLAGS_HAVE_VECTORCALL) и задав [`tp_vectorcall_offset`](https://python-all.ru/3.9/c-api/typeobj.html#c.PyTypeObject.tp_vectorcall_offset) в качестве смещения внутри структуры объекта, где находится *vectorcallfunc*. Это указатель на функцию со следующей сигнатурой:4041**[PyObject](https://python-all.ru/3.9/c-api/structures.html#c.PyObject) \*`(*vectorcallfunc)`([PyObject](https://python-all.ru/3.9/c-api/structures.html#c.PyObject) *\*callable*, [PyObject](https://python-all.ru/3.9/c-api/structures.html#c.PyObject) \*const *\*args*, size\_t *nargsf*, [PyObject](https://python-all.ru/3.9/c-api/structures.html#c.PyObject) *\*kwnames*)**4243- *callable* – это вызываемый объект.44- ***args* – это массив C, состоящий из позиционных аргументов, за которыми следуют**4546  значения именованных аргументов. Может быть *NULL*, если аргументов нет.47- ***nargsf* – это количество позиционных аргументов плюс, возможно,**4849  флаг `PY_VECTORCALL_ARGUMENTS_OFFSET`. Чтобы получить фактическое количество позиционных аргументов из *nargsf*, используйте [`PyVectorcall_NARGS()`](https://python-all.ru/3.9/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.9/c-api/call.html#c.PyObject_VectorcallMethod) этот флаг, напротив, означает, что `args[0]` может быть изменён.5960Если это можно сделать дёшево (без дополнительных выделений памяти), вызывающим сторонам рекомендуется использовать `PY_VECTORCALL_ARGUMENTS_OFFSET`. Это позволит таким вызываемым объектам, как связанные методы, выполнять последующие вызовы (которые включают добавленный аргумент *self*) очень эффективно.6162Для вызова объекта, реализующего vectorcall, используйте функцию [call API](https://python-all.ru/3.9/c-api/call.html#capi-call), как и для любого другого вызываемого объекта. Обычно наиболее эффективным будет [`PyObject_Vectorcall()`](https://python-all.ru/3.9/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.9/c-api/exceptions.html#recursion): CPython использует [`Py_EnterRecursiveCall()`](https://python-all.ru/3.9/c-api/exceptions.html#c.Py_EnterRecursiveCall) и [`Py_LeaveRecursiveCall()`](https://python-all.ru/3.9/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Эта функция не является частью [ограниченного API](https://python-all.ru/3.9/c-api/stable.html#stable).8788Новое в версии 3.8.8990#### `vectorcallfunc PyVectorcall_Function(PyObject *op)`9192Если *op* не поддерживает протокол vectorcall (либо из-за того, что тип не поддерживает, либо конкретный экземпляр), возвращает *NULL*. В противном случае возвращает указатель на функцию vectorcall, сохранённый в *op*. Эта функция никогда не возбуждает исключения.9394Это в основном полезно для проверки, поддерживает ли *op* vectorcall, что можно сделать, проверив `PyVectorcall_Function(op) != NULL`.9596Эта функция не является частью [ограниченного API](https://python-all.ru/3.9/c-api/stable.html#stable).9798Новое в версии 3.8.99100#### `PyObject* PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *dict)`101102Вызывает [`vectorcallfunc`](https://python-all.ru/3.9/c-api/call.html#c.vectorcallfunc) объекта *callable* с позиционными и именованными аргументами, заданными в виде кортежа и словаря соответственно.103104Это специализированная функция, предназначенная для размещения в слоте [`tp_call`](https://python-all.ru/3.9/c-api/typeobj.html#c.PyTypeObject.tp_call) или использования в реализации `tp_call`. Она не проверяет флаг [`Py_TPFLAGS_HAVE_VECTORCALL`](https://python-all.ru/3.9/c-api/typeobj.html#Py_TPFLAGS_HAVE_VECTORCALL) и не обращается к `tp_call` в качестве запасного варианта.105106Эта функция не является частью [ограниченного API](https://python-all.ru/3.9/c-api/stable.html#stable).107108Новое в версии 3.8.109110## API вызова объектов111112Доступны различные функции для вызова объекта Python. Каждая преобразует свои аргументы в соглашение, поддерживаемое вызываемым объектом – *tp\_call* или vectorcall. Чтобы выполнить как можно меньше преобразований, выбирайте ту, которая лучше всего подходит под формат имеющихся у вас данных.113114В следующей таблице приведены доступные функции; подробнее см. в документации для каждой из них.115116| Функция | вызываемый | аргументы | именованные аргументы |117| --- | --- | --- | --- |118| [`PyObject_Call()`](https://python-all.ru/3.9/c-api/call.html#c.PyObject_Call) | `PyObject *` | кортеж | словарь/`NULL` |119| [`PyObject_CallNoArgs()`](https://python-all.ru/3.9/c-api/call.html#c.PyObject_CallNoArgs) | `PyObject *` | – | – |120| [`PyObject_CallOneArg()`](https://python-all.ru/3.9/c-api/call.html#c.PyObject_CallOneArg) | `PyObject *` | 1 объект | – |121| [`PyObject_CallObject()`](https://python-all.ru/3.9/c-api/call.html#c.PyObject_CallObject) | `PyObject *` | кортеж/`NULL` | – |122| [`PyObject_CallFunction()`](https://python-all.ru/3.9/c-api/call.html#c.PyObject_CallFunction) | `PyObject *` | формат | – |123| [`PyObject_CallMethod()`](https://python-all.ru/3.9/c-api/call.html#c.PyObject_CallMethod) | объект + `char*` | формат | – |124| [`PyObject_CallFunctionObjArgs()`](https://python-all.ru/3.9/c-api/call.html#c.PyObject_CallFunctionObjArgs) | `PyObject *` | вариативный | – |125| [`PyObject_CallMethodObjArgs()`](https://python-all.ru/3.9/c-api/call.html#c.PyObject_CallMethodObjArgs) | объект + имя | вариативный | – |126| [`PyObject_CallMethodNoArgs()`](https://python-all.ru/3.9/c-api/call.html#c.PyObject_CallMethodNoArgs) | объект + имя | – | – |127| [`PyObject_CallMethodOneArg()`](https://python-all.ru/3.9/c-api/call.html#c.PyObject_CallMethodOneArg) | объект + имя | 1 объект | – |128| [`PyObject_Vectorcall()`](https://python-all.ru/3.9/c-api/call.html#c.PyObject_Vectorcall) | `PyObject *` | vectorcall | vectorcall |129| [`PyObject_VectorcallDict()`](https://python-all.ru/3.9/c-api/call.html#c.PyObject_VectorcallDict) | `PyObject *` | vectorcall | словарь/`NULL` |130| [`PyObject_VectorcallMethod()`](https://python-all.ru/3.9/c-api/call.html#c.PyObject_VectorcallMethod) | аргумент + имя | vectorcall | vectorcall |131132#### `PyObject* PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)`133134*Возвращаемое значение: новая ссылка.*135136Вызывает вызываемый объект Python *callable* с аргументами, заданными кортежем *args*, и именованными аргументами, заданными словарём *kwargs*.137138*args* не должен быть *NULL*; используйте пустой кортеж, если аргументы не нужны. Если именованные аргументы не нужны, *kwargs* может быть *NULL*.139140Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.141142Это эквивалент выражения Python: `callable(*args, **kwargs)`.143144#### `PyObject* PyObject_CallNoArgs(PyObject *callable)`145146Вызывает вызываемый объект Python *callable* без аргументов. Это самый эффективный способ вызова вызываемого объекта Python без аргументов.147148Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.149150Новое в версии 3.9.151152#### `PyObject* PyObject_CallOneArg(PyObject *callable, PyObject *arg)`153154Вызывает вызываемый объект Python *callable* ровно с одним позиционным аргументом *arg* и без именованных аргументов.155156Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.157158Эта функция не является частью [ограниченного API](https://python-all.ru/3.9/c-api/stable.html#stable).159160Новое в версии 3.9.161162#### `PyObject* PyObject_CallObject(PyObject *callable, PyObject *args)`163164*Возвращаемое значение: новая ссылка.*165166Вызывает вызываемый объект Python *callable* с аргументами, заданными кортежем *args*. Если аргументы не нужны, *args* может быть *NULL*.167168Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.169170Это эквивалент выражения Python: `callable(*args)`.171172#### `PyObject* PyObject_CallFunction(PyObject *callable, const char *format, ...)`173174*Возвращаемое значение: новая ссылка.*175176Вызывает вызываемый объект Python *callable* с переменным числом аргументов C. Аргументы C описываются строкой формата в стиле [`Py_BuildValue()`](https://python-all.ru/3.9/c-api/arg.html#c.Py_BuildValue). Формат может быть *NULL*, что означает, что аргументы не предоставлены.177178Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.179180Это эквивалент выражения Python: `callable(*args)`.181182Обратите внимание: если передаются только аргументы [`PyObject *`](https://python-all.ru/3.9/c-api/structures.html#c.PyObject), то [`PyObject_CallFunctionObjArgs()`](https://python-all.ru/3.9/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Вызывает метод с именем *name* объекта *obj* с переменным числом аргументов C. Аргументы C описываются строкой формата [`Py_BuildValue()`](https://python-all.ru/3.9/c-api/arg.html#c.Py_BuildValue), которая должна порождать кортеж.191192Формат может быть *NULL*, что означает, что аргументы не предоставлены.193194Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.195196Это эквивалент выражения Python: `obj.name(arg1, arg2, ...)`.197198Обратите внимание: если передаются только аргументы [`PyObject *`](https://python-all.ru/3.9/c-api/structures.html#c.PyObject), то [`PyObject_CallMethodObjArgs()`](https://python-all.ru/3.9/c-api/call.html#c.PyObject_CallMethodObjArgs) – более быстрая альтернатива.199200Изменено в версии 3.4: Типы *name* и *format* были изменены с `char *`.201202#### `PyObject* PyObject_CallFunctionObjArgs(PyObject *callable, ...)`203204*Возвращаемое значение: новая ссылка.*205206Вызов вызываемого объекта Python *callable* с переменным числом аргументов [`PyObject *`](https://python-all.ru/3.9/c-api/structures.html#c.PyObject). Аргументы передаются как переменное число параметров, после которых следует *NULL*.207208Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.209210Это эквивалент выражения Python: `callable(arg1, arg2, ...)`.211212#### `PyObject* PyObject_CallMethodObjArgs(PyObject *obj, PyObject *name, ...)`213214*Возвращаемое значение: новая ссылка.*215216Вызов метода объекта Python *obj*, где имя метода задаётся как объект строки Python в *name*. Метод вызывается с переменным числом аргументов [`PyObject *`](https://python-all.ru/3.9/c-api/structures.html#c.PyObject). Аргументы передаются как переменное число параметров, после которых следует *NULL*.217218Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.219220#### `PyObject* PyObject_CallMethodNoArgs(PyObject *obj, PyObject *name)`221222Вызывает метод объекта Python *obj* без аргументов, где имя метода задаётся как строковый объект Python в *name*.223224Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.225226Эта функция не является частью [ограниченного API](https://python-all.ru/3.9/c-api/stable.html#stable).227228Новое в версии 3.9.229230#### `PyObject* PyObject_CallMethodOneArg(PyObject *obj, PyObject *name, PyObject *arg)`231232Вызывает метод объекта Python *obj* с одним позиционным аргументом *arg*, где имя метода задаётся как строковый объект Python в *name*.233234Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.235236Эта функция не является частью [ограниченного API](https://python-all.ru/3.9/c-api/stable.html#stable).237238Новое в версии 3.9.239240#### `PyObject* PyObject_Vectorcall(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)`241242Вызывает вызываемый объект Python *callable*. Аргументы те же, что и для [`vectorcallfunc`](https://python-all.ru/3.9/c-api/call.html#c.vectorcallfunc). Если *callable* поддерживает [vectorcall](https://python-all.ru/3.9/c-api/call.html#vectorcall), то эта функция напрямую вызывает функцию vectorcall, хранящуюся в *callable*.243244Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.245246Эта функция не является частью [ограниченного API](https://python-all.ru/3.9/c-api/stable.html#stable).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.9/c-api/call.html#vectorcall), но с именованными аргументами, передаваемыми в виде словаря *kwdict*. Массив *args* содержит только позиционные аргументы.253254Независимо от того, какой протокол используется внутри, требуется выполнить преобразование аргументов. Поэтому эту функцию следует использовать только в том случае, если у вызывающего кода уже есть словарь, готовый для именованных аргументов, но нет кортежа для позиционных аргументов.255256Эта функция не является частью [ограниченного API](https://python-all.ru/3.9/c-api/stable.html#stable).257258Новое в версии 3.9.259260#### `PyObject* PyObject_VectorcallMethod(PyObject *name, PyObject *const *args, size_t nargsf, PyObject *kwnames)`261262Вызывает метод, используя соглашение о вызове vectorcall. Имя метода задаётся в виде строки Python *name*. Объект, чей метод вызывается – это *args\[0\]*, а массив *args*, начиная с *args\[1\]*, представляет аргументы вызова. Должен присутствовать хотя бы один позиционный аргумент. *nargsf* – это количество позиционных аргументов, включая *args\[0\]*, плюс `PY_VECTORCALL_ARGUMENTS_OFFSET`, если значение `args[0]` может временно изменяться. Именованные аргументы можно передавать так же, как в [`PyObject_Vectorcall()`](https://python-all.ru/3.9/c-api/call.html#c.PyObject_Vectorcall).263264Если объект обладает возможностью [`Py_TPFLAGS_METHOD_DESCRIPTOR`](https://python-all.ru/3.9/c-api/typeobj.html#Py_TPFLAGS_METHOD_DESCRIPTOR), то будет вызван непривязанный объект метода с полным вектором *args* в качестве аргументов.265266Возвращает результат вызова при успехе или возбуждает исключение и возвращает *NULL* при неудаче.267268Эта функция не является частью [ограниченного API](https://python-all.ru/3.9/c-api/stable.html#stable).269270Новое в версии 3.9.271272## API поддержки вызова273274#### `int PyCallable_Check(PyObject *o)`275276Определяет, является ли объект *o* вызываемым. Возвращает `1`, если объект вызываем, и `0` в противном случае. Эта функция всегда завершается успешно.277