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

To call an object, use "PyObject_Call()" or another call API.


O protocolo vectorcall
======================

Novo 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 invocá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 invocá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.

Uma classe não deve implementar chamadas de vetores 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 chamada de vetor.

Classes podem implementar o protocolo de chamada de vetor ativando a
flag "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:

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

* *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-chave;
     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-chave, então
     *kwnames* deve então ser *NULL*.

PY_VECTORCALL_ARGUMENTS_OFFSET

   Se essa flag é definida em um argumento de chamada de vetor
   *nargsf*, 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.

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 recursion:CPython usar "Py_EnterRecursiveCall`e
:c:func:`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)

   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.

   This function is not part of the limited API.

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

   This function is not part of the limited API.

   Novo na versão 3.8.

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

   Chame 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 checa
   a flag "Py_TPFLAGS_HAVE_VECTORCALL" e não retorna para "tp_call".

   This function is not part of the limited API.

   Novo na versão 3.8.


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

A tabela a seguir sumariza 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)
    *Return value: New reference.*

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

   Retorne o resultado da chamada em sucesso, ou levante uma exceção e
   retorne *NULL* em caso de falha.

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

PyObject* PyObject_CallNoArgs(PyObject *callable)

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

   Retorne o resultado da chamada em sucesso, ou levante uma exceção e
   retorne *NULL* em caso de falha.

   Novo na versão 3.9.

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

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

   Retorne o resultado da chamada em sucesso, ou levante uma exceção e
   retorne *NULL* em caso de falha.

   This function is not part of the limited API.

   Novo na versão 3.9.

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

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

   Retorne o resultado da chamada em sucesso, ou levante uma exceção e
   retorne *NULL* em caso de falha.

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

PyObject* PyObject_CallFunction(PyObject *callable, const char *format, ...)
    *Return value: New reference.*

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

   Retorne o resultado da chamada em sucesso, ou levante uma exceção e
   retorne *NULL* em caso de falha.

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

   Note that if you only pass "PyObject *" args,
   "PyObject_CallFunctionObjArgs()" is a faster alternative.

   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, ...)
    *Return value: New reference.*

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

   Retorne o resultado da chamada em sucesso, ou levante uma exceção e
   retorne *NULL* em caso de falha.

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

   Note that if you only pass "PyObject *" args,
   "PyObject_CallMethodObjArgs()" is a faster alternative.

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

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

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

   Retorne o resultado da chamada em sucesso, ou levante uma exceção e
   retorne *NULL* em caso de falha.

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

PyObject* PyObject_CallMethodObjArgs(PyObject *obj, PyObject *name, ...)
    *Return value: New reference.*

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

   Retorne o resultado da chamada em sucesso, ou levante uma exceção e
   retorne *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*.

   Retorne o resultado da chamada em sucesso, ou levante uma exceção e
   retorne *NULL* em caso de falha.

   This function is not part of the limited API.

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

   Retorne o resultado da chamada em sucesso, ou levante uma exceção e
   retorne *NULL* em caso de falha.

   This function is not part of the limited API.

   Novo na versão 3.9.

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

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

   Retorne o resultado da chamada em sucesso, ou levante uma exceção e
   retorne *NULL* em caso de falha.

   This function is not part of the limited API.

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

   This function is not part of the limited API.

   Novo na versão 3.9.

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

   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 a feature "Py_TPFLAGS_METHOD_DESCRIPTOR", isso irá
   chamar o objeto de método não vinculado com o vetor *args* inteiro
   como argumentos.

   Retorne o resultado da chamada em sucesso, ou levante uma exceção e
   retorne *NULL* em caso de falha.

   This function is not part of the limited API.

   Novo na versão 3.9.


API de suporte a chamadas
=========================

int PyCallable_Check(PyObject *o)

   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.
