Spec-Zone.ru › Python 3.13

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

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

Протокол tp_call

Экземпляры классов, в которых задан 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 вызовов.

Протокол Vectorcall

Добавлено в версии 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)
Входит в стабильный ABI начиная с версии 3.12.
  • callable — вызываемый объект.
  • args — массив C, состоящий из позиционных аргументов, за которыми следуют

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

  • nargsf — количество позиционных аргументов, к которому, возможно, добавлен флаг

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

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

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

PY_VECTORCALL_ARGUMENTS_OFFSET
Входит в стабильный ABI начиная с версии 3.12.

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

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

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

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

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

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

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

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

API поддержки Vectorcall

Py_ssize_t PyVectorcall_NARGS(size_t nargsf)
Входит в стабильный 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)
Входит в стабильный ABI начиная с версии 3.12.

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

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

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

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)
Возвращаемое значение: новая ссылка.Входит в стабильный ABI.

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

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

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

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

PyObject *PyObject_CallNoArgs(PyObject *callable)
Возвращаемое значение: новая ссылка.Входит в стабильный 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)
Возвращаемое значение: новая ссылка.Входит в стабильный ABI.

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

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

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

PyObject *PyObject_CallFunction(PyObject *callable, const char *format, ...)
Возвращаемое значение: новая ссылка.Входит в стабильный 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, ...)
Возвращаемое значение: новая ссылка.Входит в стабильный ABI.

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

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

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

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

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

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

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

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

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

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

PyObject *PyObject_CallMethodObjArgs(PyObject *obj, PyObject *name, ...)
Возвращаемое значение: новая ссылка.Входит в стабильный 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)
Входит в стабильный 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)
Входит в стабильный 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 поддержки вызовов

int PyCallable_Check(PyObject *o)
Входит в стабильный ABI.

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

© 2001–2025 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.13/c-api/call.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API