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