# Protocolo de chamada

O CPython permite dois protocolos de chamada: tp_call e vectorcall.

## O protocolo tp_call

Instâncias de classe que definem `tp_call` são chamáveis. A assinatura do slot é:

    PyObject *tp_call(PyObject *callable, PyObject *args, PyObject *kwargs);

Uma chamada é feita usando uma tupla para os argumentos posicionais e um dicionário para os argumentos nomeados, similar a `callable(*args, **kwargs)` no Python. args não pode ser nulo (utilize uma tupla vazia se não houver argumentos), mas kwargs pode ser NULL se não houver argumentos nomeados.

Esta convenção não é somente usada por tp_call: `tp_new` e `tp_init` também passam argumento dessa forma.

Para chamar um objeto, use `PyObject_Call()` ou outra call API.

## O protocolo vectorcall

Adicionado na versão 3.9.

O protocolo vectorcall foi introduzido pela PEP 590 como um protocolo adicional para tornar invocações mais eficientes.

Como regra de bolso. CPython vai preferir o vectorcall para invocações internas se o chamável suportar. Entretanto, isso não é uma regra rígida. Ademais, alguma extensões de terceiros usam diretamente tp_call (em vez de utilizar `PyObject_Call()`). Portanto, uma classe que suporta vectorcall precisa também implementar `tp_call`. Além disso, o chamável precisa se comportar da mesma forma independe de qual protocolo é utilizado. A forma recomendada de alcançar isso é definindo `tp_call` para `PyVectorcall_Call()`. Vale a pena repetir:

Aviso

Uma classe que suporte vectorcall também precisa implementar `tp_call` com a mesma semântica.

Alterado na versão 3.12: O sinalizador `Py_TPFLAGS_HAVE_VECTORCALL` agora é removida da classe quando o método `__call__()` está reatribuído. (Internamente, isso apenas define `tp_call`, e portanto, pode fazê-lo comportar-se de forma diferente da função vetorcall. Em versões anteriores do Python, vectorcall só deve ser usado com tipos `imutáveis` ou estáticos.

Uma classe não deve implementar vectorcall se for mais lento que tp_call. Por exemplo, se o chamador precisa converter os argumentos para uma tupla args e um dicionário kwargs de qualquer forma, então não é necessário implementar vectorcall.

Classes podem implementar o protocolo vectorcall ativando o sinalizador `Py_TPFLAGS_HAVE_VECTORCALL` e configurando `tp_vectorcall_offset` para o offset dentro da estrutura do objeto onde uma vectorcallfunc aparece. Este é um ponteiro para uma função com a seguinte assinatura:

typedef PyObject *(*vectorcallfunc)( PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)
  Parte da ABI Estável desde a versão 3.12.

- callable é o objeto sendo chamado.

- args é um array C formado pelos argumentos posicionais seguidos de

    valores dos argumentos nomeados. Este pode ser NULL se não existirem argumentos.

- nargsf é o número de argumentos posicionais somado á possível

    Sinalizador `PY_VECTORCALL_ARGUMENTS_OFFSET`. Para obter o número real de argumentos posicionais de nargsf, use `PyVectorcall_NARGS()`.

- kwnames é uma tupla contendo os nomes dos argumentos nomeados;

    em outras palavras, as chaves do dicionário kwargs. Estes nomes devem ser strings (instâncias de `str` ou uma subclasse) e eles devem ser únicos. Se não existem argumentos nomeados, então kwnames deve então ser NULL.

PY_VECTORCALL_ARGUMENTS_OFFSET
  Parte da ABI Estável desde a versão 3.12.

  Se esse sinalizador é definido em um argumento nargsf do vectorcall, deve ser permitido ao chamado temporariamente mudar `args[-1]`. Em outras palavras, args aponta para o argumento 1 (não 0) no vetor alocado. O chamado deve restaurar o valor de `args[-1]` antes de retornar.

  Para `PyObject_VectorcallMethod()`, este sinalizador significa que `args[0]` pode ser alterado.

  Sempre que podem realizar a um custo tão baixo (sem alocações adicionais), invocadores são encorajados a usar `PY_VECTORCALL_ARGUMENTS_OFFSET`. Isso permitirá invocados como métodos vinculados a instâncias fazerem suas próprias invocações (o que inclui um argumento self) muito eficientemente.

  Adicionado na versão 3.8.

Para invocar um objeto que implementa vectorcall, utilize a função call API como qualquer outra invocável. `PyObject_Vectorcall()` será normalmente mais eficiente.

Nota

No CPython 3.8, a API vectorcall e funções relacionadas estavam disponíveis provisoriamente sob nomes com um sublinhado inicial: `_PyObject_Vectorcall`, `_Py_TPFLAGS_HAVE_VECTORCALL`, `_PyObject_VectorcallMethod`, `_PyVectorcall_Function`, `_PyObject_CallOneArg`, `_PyObject_CallMethodNoArgs`, `_PyObject_CallMethodOneArg`. Além disso, `PyObject_VectorcallDict` estava disponível como `_PyObject_FastCallDict`. Os nomes antigos ainda estão definidos como apelidos para os novos nomes sem o sublinhado.

### Controle de recursão

Quando utilizando tp_call, invocadores não precisam se preocupar sobre recursão: CPython usa `Py_EnterRecursiveCall()` e `Py_LeaveRecursiveCall()` para chamadas utilizando tp_call.

Por questão de eficiência, este não é o caso de chamadas utilizando o vectorcall: o que chama deve utilizar Py_EnterRecursiveCall e Py_LeaveRecursiveCall se necessário.

### API de suporte à chamada de vetores

Py_ssize_t PyVectorcall_NARGS(size_t nargsf)
  Parte da ABI Estável desde a versão 3.12.

  Dado um argumento de chamada de vetor nargsf, retorna o número real de argumentos. Atualmente equivalente a:

      (Py_ssize_t)(nargsf & ~PY_VECTORCALL_ARGUMENTS_OFFSET)

  Entretanto, a função `PyVectorcall_NARGS` deve ser usada para permitir para futuras extensões.

  Adicionado na versão 3.8.

vectorcallfunc PyVectorcall_Function( PyObject *op)

  Se op não suporta o protocolo de chamada de vetor (seja porque o tipo ou a instância específica não suportam), retorne NULL. Se não, retorne o ponteiro da função chamada de vetor armazenado em op. Esta função nunca levanta uma exceção.

  É mais útil checar se op suporta ou não chamada de vetor, o que pode ser feito checando `PyVectorcall_Function(op) != NULL`.

  Adicionado na versão 3.9.

PyObject *PyVectorcall_Call( PyObject *callable, PyObject *tuple, PyObject *dict)
  Parte da ABI Estável desde a versão 3.12.

  Chama o `vectorcallfunc` de callable com argumentos posicionais e nomeados dados em uma tupla e dicionário, respectivamente.

  Esta é uma função especializada, feita para ser colocada no slot `tp_call` ou usada em uma implementação de `tp_call`. Ela não verifica o sinalizador `Py_TPFLAGS_HAVE_VECTORCALL` e não retorna para `tp_call`.

  Adicionado na versão 3.8.

## API de chamada de objetos

Várias funções estão disponíveis para chamar um objeto Python. Cada uma converte seus argumentos para uma convenção suportada pelo objeto chamado – seja tp_call ou chamada de vetor. Para fazer o mínimo possível de conversões, escolha um que melhor se adapte ao formato de dados que você tem disponível.

A tabela a seguir resume as funções disponíveis; por favor, veja a documentação individual para detalhes.

Função | chamável | args | kwargs
--- | --- | --- | ---
`PyObject_Call()` | `PyObject *` | tupla | dict/`NULL`
`PyObject_CallNoArgs()` | `PyObject *` | — | —
`PyObject_CallOneArg()` | `PyObject *` | 1 objeto | —
`PyObject_CallObject()` | `PyObject *` | tupla/`NULL` | —
`PyObject_CallFunction()` | `PyObject *` | format | —
`PyObject_CallMethod()` | obj + `char*` | format | —
`PyObject_CallFunctionObjArgs()` | `PyObject *` | variádica | —
`PyObject_CallMethodObjArgs()` | obj + nome | variádica | —
`PyObject_CallMethodNoArgs()` | obj + nome | — | —
`PyObject_CallMethodOneArg()` | obj + nome | 1 objeto | —
`PyObject_Vectorcall()` | `PyObject *` | vectorcall | vectorcall
`PyObject_VectorcallDict()` | `PyObject *` | vectorcall | dict/`NULL`
`PyObject_VectorcallMethod()` | arg + nome | vectorcall | vectorcall

PyObject *PyObject_Call( PyObject *callable, PyObject *args, PyObject *kwargs)
  Retorna valor: Nova referência. Parte da ABI Estável.

  Chama um objeto Python chamável de callable, com argumentos dados pela tupla args, e argumentos nomeados dados pelo dicionário kwargs.

  args não deve ser NULL; use uma tupla vazia se não precisar de argumentos. Se nenhum argumento nomeado é necessário, kwargs pode ser NULL.

  Retorna o resultado da chamada em sucesso, ou levanta uma exceção e retorna NULL em caso de falha.

  Esse é o equivalente da expressão Python: `callable(*args, **kwargs)`.

PyObject *PyObject_CallNoArgs( PyObject *callable)
  Retorna valor: Nova referência. Parte da ABI Estável desde a versão 3.10.

  Chama um objeto Python chamável de callable sem nenhum argumento. É o jeito mais eficiente de chamar um objeto Python sem nenhum argumento.

  Retorna o resultado da chamada em sucesso, ou levanta uma exceção e retorna NULL em caso de falha.

  Adicionado na versão 3.9.

PyObject *PyObject_CallOneArg( PyObject *callable, PyObject *arg)
  Retorna valor: Nova referência.

  Chama um objeto Python chamável de callable com exatamente 1 argumento posicional arg e nenhum argumento nomeado.

  Retorna o resultado da chamada em sucesso, ou levanta uma exceção e retorna NULL em caso de falha.

  Adicionado na versão 3.9.

PyObject *PyObject_CallObject( PyObject *callable, PyObject *args)
  Retorna valor: Nova referência. Parte da ABI Estável.

  Chama um objeto Python chamável de callable com argumentos dados pela tupla args. Se nenhum argumento é necessário, args pode ser NULL.

  Retorna o resultado da chamada em sucesso, ou levanta uma exceção e retorna NULL em caso de falha.

  Este é o equivalente da expressão Python: `callable(*args)`.

PyObject *PyObject_CallFunction( PyObject *callable, const char *format, ...)
  Retorna valor: Nova referência. Parte da ABI Estável.

  Chama um objeto Python chamável de callable, com um número variável de argumentos C. Os argumentos C são descritos usando uma string de estilo no formato `Py_BuildValue()`. O formato pode ser NULL, indicando que nenhum argumento foi provido.

  Retorna o resultado da chamada em sucesso, ou levanta uma exceção e retorna NULL em caso de falha.

  Este é o equivalente da expressão Python: `callable(*args)`.

  Note que se você apenas passa argumentos PyObject *, `PyObject_CallFunctionObjArgs()` é uma alternativa mais rápida.

  Alterado na versão 3.4: O tipo de format foi mudado de `char *`.

PyObject *PyObject_CallMethod( PyObject *obj, const char *name, const char *format, ...)
  Retorna valor: Nova referência. Parte da ABI Estável.

  Chama o método chamado name do objeto obj com um número variável de argumentos C. Os argumentos C são descritos com uma string de formato `Py_BuildValue()` que deve produzir uma tupla.

  O formato pode ser NULL, indicado que nenhum argumento foi provido.

  Retorna o resultado da chamada em sucesso, ou levanta uma exceção e retorna NULL em caso de falha.

  Este é o equivalente da expressão Python: `obj.name(arg1, arg2, ...)`.

  Note que se você apenas passa argumentos PyObject *, `PyObject_CallMethodObjArgs()` é uma alternativa mais rápida.

  Alterado na versão 3.4: Os tipos de name e format foram mudados de `char *`.

PyObject *PyObject_CallFunctionObjArgs( PyObject *callable, ...)
  Retorna valor: Nova referência. Parte da ABI Estável.

  Chama um objeto Python chamável de callable, com um número variável de argumentos PyObject *. Os argumentos são providos como um número variável de parâmetros seguidos por um NULL.

  Retorna o resultado da chamada em sucesso, ou levanta uma exceção e retorna NULL em caso de falha.

  Este é o equivalente da expressão Python: `callable(arg1, arg2, ...)`.

PyObject *PyObject_CallMethodObjArgs( PyObject *obj, PyObject *name, ...)
  Retorna valor: Nova referência. Parte da ABI Estável.

  Chama um método do objeto Python obj, onde o nome do método é dado como um objeto string Python em name. É chamado com um número variável de argumentos PyObject *. Os argumentos são providos como um número variável de parâmetros seguidos por um NULL.

  Retorna o resultado da chamada em sucesso, ou levanta uma exceção e retorna NULL em caso de falha.

PyObject *PyObject_CallMethodNoArgs( PyObject *obj, PyObject *name)

  Chama um método do objeto Python obj sem argumentos, onde o nome do método é fornecido como um objeto string do Python em name.

  Retorna o resultado da chamada em sucesso, ou levanta uma exceção e retorna NULL em caso de falha.

  Adicionado na versão 3.9.

PyObject *PyObject_CallMethodOneArg( PyObject *obj, PyObject *name, PyObject *arg)

  Chama um método do objeto Python obj com um argumento posicional arg, onde o nome do método é fornecido como um objeto string do Python em name.

  Retorna o resultado da chamada em sucesso, ou levanta uma exceção e retorna NULL em caso de falha.

  Adicionado na versão 3.9.

PyObject *PyObject_Vectorcall( PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)
  Parte da ABI Estável desde a versão 3.12.

  Chama um objeto Python chamável callable. Os argumentos são os mesmos de `vectorcallfunc`. Se callable tiver suporte a vectorcall, isso chamará diretamente a função vectorcall armazenada em callable.

  Retorna o resultado da chamada em sucesso, ou levanta uma exceção e retorna NULL em caso de falha.

  Adicionado na versão 3.9.

PyObject *PyObject_VectorcallDict( PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwdict)

  Chama callable com argumentos posicionais passados exatamente como no protocolo vectorcall, mas com argumentos nomeados passados como um dicionário kwdict. O array args contém apenas os argumentos posicionais.

  Independentemente de qual protocolo é usado internamente, uma conversão de argumentos precisa ser feita. Portanto, esta função só deve ser usada se o chamador já tiver um dicionário pronto para usar para os argumentos nomeados, mas não uma tupla para os argumentos posicionais.

  Adicionado na versão 3.9.

PyObject *PyObject_VectorcallMethod( PyObject *name, PyObject *const *args, size_t nargsf, PyObject *kwnames)
  Parte da ABI Estável desde a versão 3.12.

  Chama um método usando a convenção de chamada vectorcall. O nome do método é dado como uma string Python name. O objeto cujo método é chamado é args[0], e o array args começando em args[1] representa os argumentos da chamada. Deve haver pelo menos um argumento posicional. nargsf é o número de argumentos posicionais incluindo args[0], mais `PY_VECTORCALL_ARGUMENTS_OFFSET` se o valor de `args[0]` puder ser alterado temporariamente. Argumentos nomeados podem ser passados como em `PyObject_Vectorcall()`.

  Se o objeto tem o recurso `Py_TPFLAGS_METHOD_DESCRIPTOR`, isso irá chamar o objeto de método não vinculado com o vetor args inteiro como argumentos.

  Retorna o resultado da chamada em sucesso, ou levanta uma exceção e retorna NULL em caso de falha.

  Adicionado na versão 3.9.

## API de suporte a chamadas

int PyCallable_Check( PyObject *o)
  Parte da ABI Estável.

  Determine se o objeto o é chamável. Devolva `1` se o objeto é chamável e `0` caso contrário. Esta função sempre tem êxito.