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 API de chamada.


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 ouro, CPython vai preferir o vectorcall para chamadas
internas se o chamável suportar. Entretanto, isso não é uma regra
rígida. Ademais, alguma extensões de terceiros usam *tp_call*
diretamente (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 é removido 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 vectorcall. 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.


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 *"       | formato              | ---             |
+--------------------------------------------+--------------------+----------------------+-----------------+
| "PyObject_CallMethod()"                    | obj + "char*"      | formato              | ---             |
+--------------------------------------------+--------------------+----------------------+-----------------+
| "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.8: como "_PyObject_Vectorcall"

   Alterado na versão 3.9: Renomeado para o nome atual, sem o
   sublinhado no início. O nome provisório antigo está *suavemente
   descontinuado*.

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.
