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
=======================

Nuevo en la versión 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.

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)

* *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*, use
     "PyVectorcall_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

   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 de
   "args[-1]" antes de regresar.

   Para "PyObject_VectorcallMethod()", este flag significa en cambio
   que "args[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.

   Nuevo en la versión 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)

   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.

   Nuevo en la versión 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".

   Nuevo en la versión 3.9.

PyObject *PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *dict)

   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 of "tp_call". It does not
   check the "Py_TPFLAGS_HAVE_VECTORCALL" flag and it does not fall
   back to "tp_call".

   Nuevo en la versión 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          |
|============================================|====================|======================|=================|
| "PyObject_Call()"                          | "PyObject *"       | tupla                | dict/"NULL"     |
+--------------------------------------------+--------------------+----------------------+-----------------+
| "PyObject_CallNoArgs()"                    | "PyObject *"       | ---                  | ---             |
+--------------------------------------------+--------------------+----------------------+-----------------+
| "PyObject_CallOneArg()"                    | "PyObject *"       | 1 objeto             | ---             |
+--------------------------------------------+--------------------+----------------------+-----------------+
| "PyObject_CallObject()"                    | "PyObject *"       | tuple/"NULL"         | ---             |
+--------------------------------------------+--------------------+----------------------+-----------------+
| "PyObject_CallFunction()"                  | "PyObject *"       | formato              | ---             |
+--------------------------------------------+--------------------+----------------------+-----------------+
| "PyObject_CallMethod()"                    | obj + "char*"      | formato              | ---             |
+--------------------------------------------+--------------------+----------------------+-----------------+
| "PyObject_CallFunctionObjArgs()"           | "PyObject *"       | variadica            | ---             |
+--------------------------------------------+--------------------+----------------------+-----------------+
| "PyObject_CallMethodObjArgs()"             | obj + nombre       | variadica            | ---             |
+--------------------------------------------+--------------------+----------------------+-----------------+
| "PyObject_CallMethodNoArgs()"              | obj + nombre       | ---                  | ---             |
+--------------------------------------------+--------------------+----------------------+-----------------+
| "PyObject_CallMethodOneArg()"              | obj + nombre       | 1 objeto             | ---             |
+--------------------------------------------+--------------------+----------------------+-----------------+
| "PyObject_Vectorcall()"                    | "PyObject *"       | vectorcall           | vectorcall      |
+--------------------------------------------+--------------------+----------------------+-----------------+
| "PyObject_VectorcallDict()"                | "PyObject *"       | vectorcall           | dict/"NULL"     |
+--------------------------------------------+--------------------+----------------------+-----------------+
| "PyObject_VectorcallMethod()"              | 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.

   Nuevo en la versión 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.

   Nuevo en la versión 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.

   Nuevo en la versión 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.

   Nuevo en la versión 3.9.

PyObject *PyObject_Vectorcall(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)

   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.

   Nuevo en la versión 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.

   Nuevo en la versión 3.9.

PyObject *PyObject_VectorcallMethod(PyObject *name, PyObject *const *args, size_t nargsf, PyObject *kwnames)

   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 of "args[0]" may
   temporarily be changed. Keyword arguments can be passed just like
   in "PyObject_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.

   Nuevo en la versión 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 y "0" en caso contrario. Esta función siempre finaliza
   con éxito.
