Protocolo de llamada¶
CPython admite dos protocolos de llamada diferentes: tp_call y vectorcall.
El protocolo tp_call¶
Las instancias de clases que establecen tp_call
son invocables. La firma del slot es:
PyObject *tp_call(PyObject *callable, PyObject *args, PyObject *kwargs);
Se realiza una llamada usando una tupla para los argumentos posicionales y un dict para los argumentos de palabras clave, de manera similar a callable(*args, **kwargs)
en el código Python. args debe ser no NULL (use una tupla vacía si no hay argumentos) pero kwargs puede ser NULL si no hay argumentos de palabra clave.
Esta convención no solo es utilizada por tp_call: tp_new
y tp_init
también pasan argumentos de esta manera.
To call an object, use PyObject_Call()
or another
call API.
El protocolo vectorcall¶
Added in version 3.9.
El protocolo vectorcall se introdujo en PEP 590 como un protocolo adicional para hacer que las llamadas sean más eficientes.
Como regla general, CPython preferirá el vectorcall para llamadas internas si el invocable lo admite. Sin embargo, esta no es una regla estricta. Además, algunas extensiones de terceros usan tp_call directamente (en lugar de usar PyObject_Call()
). Por lo tanto, una clase que admita vectorcall también debe implementar tp_call
. Además, el invocable debe comportarse de la misma manera independientemente del protocolo que se utilice. La forma recomendada de lograr esto es configurando tp_call
en PyVectorcall_Call()
. Vale la pena repetirlo:
Advertencia
Una clase que admita vectorcall debe también implementar tp_call
con la misma semántica.
Distinto en la versión 3.12: The Py_TPFLAGS_HAVE_VECTORCALL
flag is now removed from a class
when the class’s __call__()
method is reassigned.
(This internally sets tp_call
only, and thus
may make it behave differently than the vectorcall function.)
In earlier Python versions, vectorcall should only be used with
immutable
or static types.
Una clase no debería implementar vectorcall si eso fuera más lento que tp_call. Por ejemplo, si el destinatario de la llamada necesita convertir los argumentos a una tupla args y un dict kwargs de todos modos, entonces no tiene sentido implementar vectorcall.
Classes can implement the vectorcall protocol by enabling the
Py_TPFLAGS_HAVE_VECTORCALL
flag and setting
tp_vectorcall_offset
to the offset inside the
object structure where a vectorcallfunc appears.
This is a pointer to a function with the following signature:
-
typedef PyObject *(*vectorcallfunc)(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)¶
- Part of the Stable ABI since version 3.12.
callable es el objeto siendo invocado.
- args es un arreglo en C que consta de los argumentos posicionales seguidos por el
valores de los argumentos de la palabra clave. Puede ser NULL si no hay argumentos.
- nargsf es el número de argumentos posicionales más posiblemente el
PY_VECTORCALL_ARGUMENTS_OFFSET
flag. To get the actual number of positional arguments from nargsf, usePyVectorcall_NARGS()
.
- kwnames es una tupla que contiene los nombres de los argumentos de la palabra clave;
en otras palabras, las claves del diccionario kwargs. Estos nombres deben ser cadenas (instancias de
str
o una subclase) y deben ser únicos. Si no hay argumentos de palabras clave, entonces kwnames puede ser NULL.
-
PY_VECTORCALL_ARGUMENTS_OFFSET¶
- Part of the Stable ABI since version 3.12.
Si este flag se establece en un argumento vectorcall nargsf, el destinatario de la llamada puede cambiar temporalmente
args[-1]
. En otras palabras, args apunta al argumento 1 (no 0) en el vector asignado. El destinatario de la llamada debe restaurar el valor deargs[-1]
antes de regresar.Para
PyObject_VectorcallMethod()
, este flag significa en cambio queargs[0]
puede cambiarse.Whenever they can do so cheaply (without additional allocation), callers are encouraged to use
PY_VECTORCALL_ARGUMENTS_OFFSET
. Doing so will allow callables such as bound methods to make their onward calls (which include a prepended self argument) very efficiently.Added in version 3.8.
Para llamar a un objeto que implementa vectorcall, use una función call API como con cualquier otro invocable. PyObject_Vectorcall()
normalmente será más eficiente.
Nota
En CPython 3.8, la API de vectorcall y las funciones relacionadas estaban disponibles provisionalmente bajo nombres con un guión bajo inicial: _PyObject_Vectorcall
, _Py_TPFLAGS_HAVE_VECTORCALL
, _PyObject_VectorcallMethod
, _PyVectorcall_Function
, _PyObject_CallMethodNoArgs
, _PyObject_CallMethodOneArg
. Además, PyObject_VectorcallDict
estaba disponible como _PyObject_FastCallDict
. Los nombres antiguos todavía se definen como alias de los nuevos nombres no subrayados.
Control de recursión¶
Cuando se usa tp_call, los destinatarios no necesitan preocuparse por recursividad: CPython usa Py_EnterRecursiveCall()
y Py_LeaveRecursiveCall()
para llamadas realizadas usando tp_call.
Por eficiencia, este no es el caso de las llamadas realizadas mediante vectorcall: el destinatario de la llamada debe utilizar Py_EnterRecursiveCall y Py_LeaveRecursiveCall si es necesario.
API de soporte para vectorcall¶
-
Py_ssize_t PyVectorcall_NARGS(size_t nargsf)¶
- Part of the Stable ABI since version 3.12.
Dado un argumento vectorcall nargsf, retorna el número real de argumentos. Actualmente equivalente a:
(Py_ssize_t)(nargsf & ~PY_VECTORCALL_ARGUMENTS_OFFSET)
Sin embargo, la función
PyVectorcall_NARGS
debe usarse para permitir futuras extensiones.Added in version 3.8.
-
vectorcallfunc PyVectorcall_Function(PyObject *op)¶
Si op no admite el protocolo vectorcall (ya sea porque el tipo no lo hace o porque la instancia específica no lo hace), retorna NULL. De lo contrario, retorna el puntero de la función vectorcall almacenado en op. Esta función nunca lanza una excepción.
Esto es principalmente útil para verificar si op admite vectorcall, lo cual se puede hacer marcando
PyVectorcall_Function(op) != NULL
.Added in version 3.9.
-
PyObject *PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *dict)¶
- Part of the Stable ABI since version 3.12.
Llama a la
vectorcallfunc
de callable con argumentos posicionales y de palabras clave dados en una tupla y dict, respectivamente.This is a specialized function, intended to be put in the
tp_call
slot or be used in an implementation oftp_call
. It does not check thePy_TPFLAGS_HAVE_VECTORCALL
flag and it does not fall back totp_call
.Added in version 3.8.
API para invocar objetos¶
Hay varias funciones disponibles para llamar a un objeto Python. Cada una convierte sus argumentos a una convención respaldada por el objeto llamado, ya sea tp_call o vectorcall. Para realizar la menor conversión posible, elija la que mejor se adapte al formato de datos que tiene disponible.
La siguiente tabla resume las funciones disponibles; consulte la documentación individual para obtener más detalles.
Función |
invocable |
args |
kwargs |
---|---|---|---|
|
tupla |
dict/ |
|
|
— |
— |
|
|
1 objeto |
— |
|
|
tuple/ |
— |
|
|
formato |
— |
|
obj + |
formato |
— |
|
|
variadica |
— |
|
obj + nombre |
variadica |
— |
|
obj + nombre |
— |
— |
|
obj + nombre |
1 objeto |
— |
|
|
vectorcall |
vectorcall |
|
|
vectorcall |
dict/ |
|
arg + nombre |
vectorcall |
vectorcall |
-
PyObject *PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)¶
- Return value: New reference. Part of the Stable ABI.
Llama a un objeto de Python invocable callable, con argumentos dados por la tupla args, y argumentos con nombre dados por el diccionario kwargs.
args no debe ser NULL; use una tupla vacía si no se necesitan argumentos. Si no se necesitan argumentos con nombre, kwargs puede ser NULL.
Retorna el resultado de la llamada en caso de éxito o lanza una excepción y retorna NULL en caso de error.
Este es el equivalente de la expresión de Python:
callable(*args, **kwargs)
.
-
PyObject *PyObject_CallNoArgs(PyObject *callable)¶
- Return value: New reference. Part of the Stable ABI since version 3.10.
Llama a un objeto de Python invocable callable sin ningún argumento. Es la forma más eficiente de llamar a un objeto Python invocable sin ningún argumento.
Retorna el resultado de la llamada en caso de éxito o lanza una excepción y retorna NULL en caso de error.
Added in version 3.9.
-
PyObject *PyObject_CallOneArg(PyObject *callable, PyObject *arg)¶
- Return value: New reference.
Llama a un objeto de Python invocable callable con exactamente 1 argumento posicional arg y sin argumentos de palabra clave.
Retorna el resultado de la llamada en caso de éxito o lanza una excepción y retorna NULL en caso de error.
Added in version 3.9.
-
PyObject *PyObject_CallObject(PyObject *callable, PyObject *args)¶
- Return value: New reference. Part of the Stable ABI.
Llama a un objeto de Python invocable callable, con argumentos dados por la tupla args. Si no se necesitan argumentos, entonces args puede ser NULL.
Retorna el resultado de la llamada en caso de éxito o lanza una excepción y retorna NULL en caso de error.
Este es el equivalente de la expresión de Python:
callable(*args)
.
-
PyObject *PyObject_CallFunction(PyObject *callable, const char *format, ...)¶
- Return value: New reference. Part of the Stable ABI.
Llama a un objeto de Python invocable callable, con un número variable de argumentos C. Los argumentos de C se describen usando una cadena de caracteres de formato de estilo
Py_BuildValue()
. El formato puede ser NULL, lo que indica que no se proporcionan argumentos.Retorna el resultado de la llamada en caso de éxito o lanza una excepción y retorna NULL en caso de error.
Este es el equivalente de la expresión de Python:
callable(*args)
.Note that if you only pass PyObject* args,
PyObject_CallFunctionObjArgs()
is a faster alternative.Distinto en la versión 3.4: El tipo de format se cambió desde
char *
.
-
PyObject *PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...)¶
- Return value: New reference. Part of the Stable ABI.
Llama al método llamado name del objeto obj con un número variable de argumentos en C. Los argumentos de C se describen mediante una cadena de formato
Py_BuildValue()
que debería producir una tupla.El formato puede ser NULL, lo que indica que no se proporcionan argumentos.
Retorna el resultado de la llamada en caso de éxito o lanza una excepción y retorna NULL en caso de error.
Este es el equivalente de la expresión de Python:
obj.name(arg1, arg2, ...)
.Note that if you only pass PyObject* args,
PyObject_CallMethodObjArgs()
is a faster alternative.Distinto en la versión 3.4: Los tipos de name y format se cambiaron desde
char *
.
-
PyObject *PyObject_CallFunctionObjArgs(PyObject *callable, ...)¶
- Return value: New reference. Part of the Stable ABI.
Call a callable Python object callable, with a variable number of PyObject* arguments. The arguments are provided as a variable number of parameters followed by NULL.
Retorna el resultado de la llamada en caso de éxito o lanza una excepción y retorna NULL en caso de error.
Este es el equivalente de la expresión de Python:
callable(arg1, arg2, ...)
.
-
PyObject *PyObject_CallMethodObjArgs(PyObject *obj, PyObject *name, ...)¶
- Return value: New reference. Part of the Stable ABI.
Call a method of the Python object obj, where the name of the method is given as a Python string object in name. It is called with a variable number of PyObject* arguments. The arguments are provided as a variable number of parameters followed by NULL.
Retorna el resultado de la llamada en caso de éxito o lanza una excepción y retorna NULL en caso de error.
-
PyObject *PyObject_CallMethodNoArgs(PyObject *obj, PyObject *name)¶
Llama a un método del objeto de Python obj sin argumentos, donde el nombre del método se da como un objeto de cadena de caracteres de Python en name.
Retorna el resultado de la llamada en caso de éxito o lanza una excepción y retorna NULL en caso de error.
Added in version 3.9.
-
PyObject *PyObject_CallMethodOneArg(PyObject *obj, PyObject *name, PyObject *arg)¶
Llame a un método del objeto de Python obj con un único argumento posicional arg, donde el nombre del método se proporciona como un objeto de cadena de caracteres de Python en name.
Retorna el resultado de la llamada en caso de éxito o lanza una excepción y retorna NULL en caso de error.
Added in version 3.9.
-
PyObject *PyObject_Vectorcall(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)¶
- Part of the Stable ABI since version 3.12.
Llama a un objeto de Python invocable callable. Los argumentos son los mismos que para
vectorcallfunc
. Si callable admite vectorcall, esto llama directamente a la función vectorcall almacenada en callable.Retorna el resultado de la llamada en caso de éxito o lanza una excepción y retorna NULL en caso de error.
Added in version 3.9.
-
PyObject *PyObject_VectorcallDict(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwdict)¶
Llamada invocable con argumentos posicionales pasados exactamente como en el protocolo vectorcall, pero con argumentos de palabras clave pasados como un diccionario kwdict. El arreglo args contiene solo los argumentos posicionales.
Independientemente del protocolo que se utilice internamente, es necesario realizar una conversión de argumentos. Por lo tanto, esta función solo debe usarse si la persona que llama ya tiene un diccionario listo para usar para los argumentos de palabras clave, pero no una tupla para los argumentos posicionales.
Added in version 3.9.
-
PyObject *PyObject_VectorcallMethod(PyObject *name, PyObject *const *args, size_t nargsf, PyObject *kwnames)¶
- Part of the Stable ABI since version 3.12.
Call a method using the vectorcall calling convention. The name of the method is given as a Python string name. The object whose method is called is args[0], and the args array starting at args[1] represents the arguments of the call. There must be at least one positional argument. nargsf is the number of positional arguments including args[0], plus
PY_VECTORCALL_ARGUMENTS_OFFSET
if the value ofargs[0]
may temporarily be changed. Keyword arguments can be passed just like inPyObject_Vectorcall()
.If the object has the
Py_TPFLAGS_METHOD_DESCRIPTOR
feature, this will call the unbound method object with the full args vector as arguments.Retorna el resultado de la llamada en caso de éxito o lanza una excepción y retorna NULL en caso de error.
Added in version 3.9.
API de soporte de llamadas¶
-
int PyCallable_Check(PyObject *o)¶
- Part of the Stable ABI.
Determina si el objeto o es invocable. Retorna
1
si el objeto es invocable y0
en caso contrario. Esta función siempre finaliza con éxito.