Spec-Zone.ru › Python 3.11

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

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 с теми же семантиками.

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

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

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

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

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

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

PY_VECTORCALL_ARGUMENTS_OFFSET

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

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

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

Введено в версии 3.8.

Для вызова объекта, реализующего vectorcall, используйте функцию 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. Старые имена по-прежнему определены как псевдонимы новых имён без подчёркивания.

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

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

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

API поддержки Vectorcall

Py_ssize_t PyVectorcall_NARGS(size_t nargsf)

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

(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)

Вызвать 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 с ровно 1 позиционным аргументом 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.

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

END_OF_DOCUMENT_MARKER
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)

Вызов вызываемого объекта 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)

Вызов метода с использованием соглашения о вызове 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–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.11/c-api/call.html

Spec-Zone.ru

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