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.

Las clases pueden implementar el protocolo vectorcall habilitando el
indicador "Py_TPFLAGS_HAVE_VECTORCALL" y la configuración
"tp_vectorcall_offset" al desplazamiento dentro de la estructura del
objeto donde aparece un *vectorcallfunc*. Este es un puntero a una
función con la siguiente firma:

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
     flag "PY_VECTORCALL_ARGUMENTS_OFFSET". Para obtener el número
     real de argumentos posicionales de *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.

   Siempre que puedan hacerlo de forma económica (sin asignación
   adicional), se anima a las personas que llaman a utilizar
   "PY_VECTORCALL_ARGUMENTS_OFFSET". Si lo hace, permitirá que las
   personas que llaman, como los métodos enlazados, realicen sus
   llamadas posteriores (que incluyen un argumento *self* antepuesto)
   de manera muy eficiente.

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.

   Esta función no es parte de la API limitada.

   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".

   Esta función no es parte de la API limitada.

   Nuevo en la versión 3.8.

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.

   Esta es una función especializada, destinada a colocarse en el slot
   "tp_call" o usarse en una implementación de "tp_call". No comprueba
   el flag "Py_TPFLAGS_HAVE_VECTORCALL" y no vuelve a "tp_call".

   Esta función no es parte de la API limitada.

   Nuevo en la versión 3.8.


API para invocar objetos
========================

Various functions are available for calling a Python object. Each
converts its arguments to a convention supported by the called object
– either *tp_call* or vectorcall. In order to do as little conversion
as possible, pick one that best fits the format of data you have
available.

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.*

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

   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 genera una
   excepción y retorna *NULL* en caso de error.

   Nuevo en la versión 3.9.

PyObject* PyObject_CallOneArg(PyObject *callable, PyObject *arg)

   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 genera una
   excepción y retorna *NULL* en caso de error.

   Esta función no es parte de la API limitada.

   Nuevo en la versión 3.9.

PyObject* PyObject_CallObject(PyObject *callable, PyObject *args)
    *Return value: New reference.*

   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 genera 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.*

   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 genera una
   excepción y retorna *NULL* en caso de error.

   Este es el equivalente de la expresión de Python:
   "callable(*args)".

   Tenga en cuenta que si solo pasa "PyObject *" args,
   "PyObject_CallFunctionObjArgs()" es una alternativa más rápida.

   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.*

   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 genera una
   excepción y retorna *NULL* en caso de error.

   Este es el equivalente de la expresión de Python: "obj.name(arg1,
   arg2, ...)".

   Tenga en cuenta que si solo pasa "PyObject *" args,
   "PyObject_CallMethodObjArgs()" es una alternativa más rápida.

   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.*

   Llame a un objeto de Python invocable *callable*, con un número
   variable de argumentos "PyObject *". Los argumentos se proporcionan
   como un número variable de parámetros seguidos de *NULL*.

   Retorna el resultado de la llamada en caso de éxito o genera 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.*

   Llama a un método del objeto de Python *obj*, donde el nombre del
   método se proporciona como un objeto de cadena de caracteres de
   Python en *name*. Se llama con un número variable de argumentos
   "PyObject *". Los argumentos se proporcionan como un número
   variable de parámetros seguidos de *NULL*.

   Retorna el resultado de la llamada en caso de éxito o genera 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 genera una
   excepción y retorna *NULL* en caso de error.

   Esta función no es parte de la API limitada.

   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 genera una
   excepción y retorna *NULL* en caso de error.

   Esta función no es parte de la API limitada.

   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 genera una
   excepción y retorna *NULL* en caso de error.

   Esta función no es parte de la API limitada.

   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.

   Esta función no es parte de la API limitada.

   Nuevo en la versión 3.9.

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

   Llama a un método usando la convención de llamada vectorcall. El
   nombre del método se proporciona como una cadena de Python *name*.
   El objeto cuyo método se llama es *args[0]*, y el arreglo *args*
   que comienza en *args [1]* representa los argumentos de la llamada.
   Debe haber al menos un argumento posicional. *nargsf* es el número
   de argumentos posicionales que incluyen *args [0]*, más
   "PY_VECTORCALL_ARGUMENTS_OFFSET" si el valor de "args[0]" puede
   cambiarse temporalmente. Los argumentos de palabras clave se pueden
   pasar como en "PyObject_Vectorcall()".

   Si el objeto tiene la característica
   "Py_TPFLAGS_METHOD_DESCRIPTOR", esto llamará al objeto de método
   independiente con el vector *args* completo como argumentos.

   Retorna el resultado de la llamada en caso de éxito o genera una
   excepción y retorna *NULL* en caso de error.

   Esta función no es parte de la API limitada.

   Nuevo en la versión 3.9.


API de soporte de llamadas
==========================

int PyCallable_Check(PyObject *o)

   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.
