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