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

Протокол вызоваCall Protocol

CPython поддерживает два протокола вызова: tp_call и vectorcall.

tp_callThe tp_call Protocol

Экземпляры классов, в которых задан tp_call, являются вызываемыми. Сигнатура слота:

PyObject *tp_call(PyObject *callable, PyObject *args, PyObject *kwargs);

Вызов производится с использованием кортежа для позиционных аргументов и словаря для именованных аргументов, аналогично callable(*args, **kwargs) в коде Python. args должно быть не NULL (используйте пустой кортеж, если аргументов нет), но kwargs может быть NULL, если именованные аргументы отсутствуют.

Это соглашение используется не только в tp_call: tp_new и tp_init также передают аргументы таким образом.

Для вызова объекта используйте PyObject_Call() или другой API вызова.

Протокол VectorcallThe Vectorcall Protocol

Добавлено в версии 3.9.

Протокол vectorcall был представлен в PEP 590 как дополнительный протокол для повышения эффективности вызовов.

Как правило, CPython предпочитает vectorcall для внутренних вызовов, если вызываемый объект его поддерживает. Однако это не жёсткое правило. Кроме того, некоторые сторонние расширения используют tp_call напрямую (вместо PyObject_Call()). Поэтому класс, поддерживающий vectorcall, должен также реализовывать tp_call. Более того, вызываемый объект должен вести себя одинаково независимо от используемого протокола. Рекомендуемый способ добиться этого – задать tp_call равным PyVectorcall_Call(). Это стоит повторить:

Предупреждение

Класс, поддерживающий vectorcall, должен также реализовывать tp_call с той же семантикой.

Изменено в версии 3.12: Флаг Py_TPFLAGS_HAVE_VECTORCALL теперь удаляется из класса, когда метод __call__() класса переопределяется. (При этом внутренне устанавливается только tp_call, что может привести к поведению, отличному от функции vectorcall). В более ранних версиях Python vectorcall следует использовать только с immutable или статическими типами.

Класс не должен реализовывать vectorcall, если это будет медленнее, чем tp_call. Например, если вызываемая сторона всё равно должна преобразовывать аргументы в кортеж args и словарь kwargs, то нет смысла реализовывать vectorcall.

Классы могут реализовать протокол vectorcall, установив флаг Py_TPFLAGS_HAVE_VECTORCALL и задав tp_vectorcall_offset в качестве смещения внутри структуры объекта, где находится vectorcallfunc. Это указатель на функцию со следующей сигнатурой:

typedef PyObject *(*vectorcallfunc)(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)
Часть Stable ABI начиная с версии 3.12.
  • callable – это вызываемый объект.

  • args – это массив C, состоящий из позиционных аргументов, за которыми следуют

    значения именованных аргументов. Может быть NULL, если аргументов нет.

  • nargsf – это количество позиционных аргументов плюс, возможно,

    флаг PY_VECTORCALL_ARGUMENTS_OFFSET. Чтобы получить фактическое количество позиционных аргументов из nargsf, используйте PyVectorcall_NARGS().

  • kwnames – это кортеж, содержащий имена именованных аргументов;

    другими словами, ключи словаря kwargs. Эти имена должны быть строками (экземплярами str или подкласса) и они должны быть уникальными. Если именованных аргументов нет, то kwnames может быть NULL.

PY_VECTORCALL_ARGUMENTS_OFFSET
Часть Stable ABI начиная с версии 3.12.

Если этот флаг установлен в аргументе vectorcall nargsf, вызываемой стороне разрешается временно изменить args[-1]. Иными словами, args указывает на аргумент 1 (а не 0) в выделенном векторе. Вызываемая сторона должна восстановить значение args[-1] перед возвратом.

Для PyObject_VectorcallMethod() этот флаг, напротив, означает, что args[0] может быть изменён.

Если это можно сделать дёшево (без дополнительных выделений памяти), вызывающим сторонам рекомендуется использовать PY_VECTORCALL_ARGUMENTS_OFFSET. Это позволит таким вызываемым объектам, как связанные методы, выполнять последующие вызовы (которые включают добавленный аргумент self) очень эффективно.

Добавлено в версии 3.8.

Для вызова объекта, реализующего vectorcall, используйте функцию call API, как и для любого другого вызываемого объекта. Обычно наиболее эффективным будет PyObject_Vectorcall().

Примечание

В 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. Старые имена по-прежнему определены как псевдонимы новых имен без подчеркивания.

Управление рекурсиейRecursion Control

При использовании tp_call вызываемым сторонам не нужно беспокоиться о рекурсии: CPython использует Py_EnterRecursiveCall() и Py_LeaveRecursiveCall() для вызовов, выполненных с помощью tp_call.

Для эффективности это не относится к вызовам, выполненным с помощью vectorcall: вызываемая сторона должна использовать Py_EnterRecursiveCall и Py_LeaveRecursiveCall, если это необходимо.

API поддержки VectorcallVectorcall Support API

Py_ssize_t PyVectorcall_NARGS(size_t nargsf)
Часть Stable ABI начиная с версии 3.12.

Получив аргумент vectorcall nargsf, возвращает фактическое количество аргументов. В настоящее время эквивалентно:

(Py_ssize_t)(nargsf & ~PY_VECTORCALL_ARGUMENTS_OFFSET)

Однако следует использовать функцию PyVectorcall_NARGS, чтобы обеспечить возможность будущих расширений.

Добавлено в версии 3.8.

vectorcallfunc PyVectorcall_Function(PyObject *op)

Если op не поддерживает протокол vectorcall (либо из-за того, что тип не поддерживает, либо конкретный экземпляр), возвращает NULL. В противном случае возвращает указатель на функцию vectorcall, сохранённый в op. Эта функция никогда не возбуждает исключения.

Это в основном полезно для проверки, поддерживает ли op vectorcall, что можно сделать, проверив PyVectorcall_Function(op) != NULL.

Добавлено в версии 3.9.

PyObject *PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *dict)
Часть Stable ABI начиная с версии 3.12.

Вызывает vectorcallfunc объекта callable с позиционными и именованными аргументами, заданными в виде кортежа и словаря соответственно.

Это специализированная функция, предназначенная для размещения в слоте tp_call или использования в реализации tp_call. Она не проверяет флаг Py_TPFLAGS_HAVE_VECTORCALL и не обращается к tp_call в качестве запасного варианта.

Добавлено в версии 3.8.

API вызова объектовObject Calling API

Доступны различные функции для вызова объекта Python. Каждая преобразует свои аргументы в соглашение, поддерживаемое вызываемым объектом – tp_call или vectorcall. Чтобы выполнить как можно меньше преобразований, выбирайте ту, которая лучше всего подходит под формат имеющихся у вас данных.

В следующей таблице приведены доступные функции; подробнее см. в документации для каждой из них.

Функция

вызываемый

аргументы

именованные аргументы

PyObject_Call()

PyObject *

кортеж

словарь/NULL

PyObject_CallNoArgs()

PyObject *

PyObject_CallOneArg()

PyObject *

1 объект

PyObject_CallObject()

PyObject *

кортеж/NULL

PyObject_CallFunction()

PyObject *

формат

PyObject_CallMethod()

объект + char*

формат

PyObject_CallFunctionObjArgs()

PyObject *

вариативный

PyObject_CallMethodObjArgs()

объект + имя

вариативный

PyObject_CallMethodNoArgs()

объект + имя

PyObject_CallMethodOneArg()

объект + имя

1 объект

PyObject_Vectorcall()

PyObject *

vectorcall

vectorcall

PyObject_VectorcallDict()

PyObject *

vectorcall

словарь/NULL

PyObject_VectorcallMethod()

аргумент + имя

vectorcall

vectorcall

PyObject *PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
Возвращаемое значение: новая ссылка. Часть Stable ABI.

Вызывает вызываемый объект Python callable с аргументами, заданными кортежем args, и именованными аргументами, заданными словарём kwargs.

args не должен быть NULL; используйте пустой кортеж, если аргументы не нужны. Если именованные аргументы не нужны, kwargs может быть NULL.

Возвращает результат вызова при успехе или возбуждает исключение и возвращает NULL при неудаче.

Это эквивалент выражения Python: callable(*args, **kwargs).

PyObject *PyObject_CallNoArgs(PyObject *callable)
Возвращаемое значение: новая ссылка. Часть Stable ABI начиная с версии 3.10.

Вызывает вызываемый объект Python callable без аргументов. Это самый эффективный способ вызова вызываемого объекта Python без аргументов.

Возвращает результат вызова при успехе или возбуждает исключение и возвращает NULL при неудаче.

Добавлено в версии 3.9.

PyObject *PyObject_CallOneArg(PyObject *callable, PyObject *arg)
Возвращаемое значение: новая ссылка.

Вызывает вызываемый объект Python callable ровно с одним позиционным аргументом arg и без именованных аргументов.

Возвращает результат вызова при успехе или возбуждает исключение и возвращает NULL при неудаче.

Добавлено в версии 3.9.

PyObject *PyObject_CallObject(PyObject *callable, PyObject *args)
Возвращаемое значение: новая ссылка. Часть Stable ABI.

Вызывает вызываемый объект Python callable с аргументами, заданными кортежем args. Если аргументы не нужны, args может быть NULL.

Возвращает результат вызова при успехе или возбуждает исключение и возвращает NULL при неудаче.

Это эквивалент выражения Python: callable(*args).

PyObject *PyObject_CallFunction(PyObject *callable, const char *format, ...)
Возвращаемое значение: новая ссылка. Часть Stable ABI.

Вызывает вызываемый объект Python callable с переменным числом аргументов C. Аргументы C описываются строкой формата в стиле Py_BuildValue(). Формат может быть NULL, что означает, что аргументы не предоставлены.

Возвращает результат вызова при успехе или возбуждает исключение и возвращает NULL при неудаче.

Это эквивалент выражения Python: callable(*args).

Обратите внимание, что если передавать только аргументы PyObject*, то PyObject_CallFunctionObjArgs() будет более быстрой альтернативой.

Изменено в версии 3.4: Тип format был изменён с char *.

PyObject *PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...)
Возвращаемое значение: новая ссылка. Часть Stable ABI.

Вызывает метод с именем name объекта obj с переменным числом аргументов C. Аргументы C описываются строкой формата Py_BuildValue(), которая должна порождать кортеж.

Формат может быть NULL, что означает, что аргументы не предоставлены.

Возвращает результат вызова при успехе или возбуждает исключение и возвращает NULL при неудаче.

Это эквивалент выражения Python: obj.name(arg1, arg2, ...).

Обратите внимание, что если передавать только аргументы PyObject*, то PyObject_CallMethodObjArgs() будет более быстрой альтернативой.

Изменено в версии 3.4: Типы name и format были изменены с char *.

PyObject *PyObject_CallFunctionObjArgs(PyObject *callable, ...)
Возвращаемое значение: новая ссылка. Часть Stable ABI.

Вызывает вызываемый объект Python callable с переменным числом аргументов PyObject*. Аргументы передаются как переменное число параметров, за которым следует NULL.

Возвращает результат вызова при успехе или возбуждает исключение и возвращает NULL при неудаче.

Это эквивалент выражения Python: callable(arg1, arg2, ...).

PyObject *PyObject_CallMethodObjArgs(PyObject *obj, PyObject *name, ...)
Возвращаемое значение: новая ссылка. Часть Stable ABI.

Вызывает метод объекта Python obj, где имя метода задаётся как строковый объект Python в name. Он вызывается с переменным числом аргументов PyObject*. Аргументы передаются как переменное число параметров, за которым следует NULL.

Возвращает результат вызова при успехе или возбуждает исключение и возвращает NULL при неудаче.

PyObject *PyObject_CallMethodNoArgs(PyObject *obj, PyObject *name)

Вызывает метод объекта Python obj без аргументов, где имя метода задаётся как строковый объект Python в name.

Возвращает результат вызова при успехе или возбуждает исключение и возвращает NULL при неудаче.

Добавлено в версии 3.9.

PyObject *PyObject_CallMethodOneArg(PyObject *obj, PyObject *name, PyObject *arg)

Вызывает метод объекта Python obj с одним позиционным аргументом arg, где имя метода задаётся как строковый объект Python в name.

Возвращает результат вызова при успехе или возбуждает исключение и возвращает NULL при неудаче.

Добавлено в версии 3.9.

PyObject *PyObject_Vectorcall(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)
Часть Stable ABI начиная с версии 3.12.

Вызывает вызываемый объект Python callable. Аргументы те же, что и для vectorcallfunc. Если callable поддерживает vectorcall, то эта функция напрямую вызывает функцию vectorcall, хранящуюся в callable.

Возвращает результат вызова при успехе или возбуждает исключение и возвращает NULL при неудаче.

Добавлено в версии 3.9.

PyObject *PyObject_VectorcallDict(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwdict)

Вызывает callable с позиционными аргументами, передаваемыми точно так же, как в протоколе vectorcall, но с именованными аргументами, передаваемыми в виде словаря kwdict. Массив args содержит только позиционные аргументы.

Независимо от того, какой протокол используется внутри, требуется выполнить преобразование аргументов. Поэтому эту функцию следует использовать только в том случае, если у вызывающего кода уже есть словарь, готовый для именованных аргументов, но нет кортежа для позиционных аргументов.

Добавлено в версии 3.9.

PyObject *PyObject_VectorcallMethod(PyObject *name, PyObject *const *args, size_t nargsf, PyObject *kwnames)
Часть Stable ABI начиная с версии 3.12.

Вызывает метод, используя соглашение о вызове vectorcall. Имя метода задаётся в виде строки Python name. Объект, чей метод вызывается – это args[0], а массив args, начиная с args[1], представляет аргументы вызова. Должен присутствовать хотя бы один позиционный аргумент. nargsf – это количество позиционных аргументов, включая args[0], плюс PY_VECTORCALL_ARGUMENTS_OFFSET, если значение args[0] может временно изменяться. Именованные аргументы можно передавать так же, как в PyObject_Vectorcall().

Если объект обладает возможностью Py_TPFLAGS_METHOD_DESCRIPTOR, то будет вызван непривязанный объект метода с полным вектором args в качестве аргументов.

Возвращает результат вызова при успехе или возбуждает исключение и возвращает NULL при неудаче.

Добавлено в версии 3.9.

API поддержки вызоваCall Support API

int PyCallable_Check(PyObject *o)
Часть Stable ABI.

Определяет, является ли объект o вызываемым. Возвращает 1, если объект вызываем, и 0 в противном случае. Эта функция всегда завершается успешно.