CDBr

Sua fonte de informação em Ciência de Dados

Python: Para que servem os Parâmetros Especiais?

lustração dos Parâmetros Especiais em Python: Aprofunde-se no seu uso e funcionalidades.

Introdução: Para que servem os Parâmetros Especiais de Asterisco e Barra no Python?

Quando você pensa no operador asterisco (*) do Python, provavelmente associa à multiplicação ou à exponenciação. De maneira semelhante, você provavelmente relaciona o operador barra (/) com a divisão. Mas você também pode usar o asterisco e a barra simples como parâmetros especiais nos cabeçalhos de funções. Eles fazem algo completamente diferente da matemática.

Ao definir funções, você frequentemente incluirá uma lista de parâmetros separados por vírgulas para definir quais tipos de argumentos o usuário pode passar para sua função. O uso dos símbolos asterisco e barra como parâmetros especiais no cabeçalho da sua função pode parecer estranho no início:

 
def funcao_esquisita(*, x, y):
    ...

def outra_funcao_esquisita(a, b, /, c, *, d):
    ...

Ambas essas definições de função podem parecer um pouco estranhas, mas os parâmetros de função delas são perfeitamente válidos. Então, o que exatamente um asterisco simples e uma barra significam em uma definição de função Python?

Imagem representando a importância da mentoria em ciência de dados para alcançar o sucesso profissional

O Controle do Asterisco e da Barra no Python

O asterisco (*) e a barra (/) definem se você pode passar argumentos posicionais ou por palavra-chave para suas funções.

Você usa um asterisco simples para definir um limite entre argumentos que você pode passar tanto por posição quanto por palavra-chave daqueles que você deve passar por palavra-chave. Você usa a barra para definir um limite entre os argumentos que você deve passar por posição daqueles que você pode passar tanto por posição quanto por palavra-chave. Aqui está uma representação visual que resume como usar esses símbolos:

Lado EsquerdoDivisorLado Direito
Argumentos apenas posicionais/Argumentos posicionais ou por palavra-chave
Argumentos posicionais ou por palavra-chave*Argumentos apenas por palavra-chave

Você também pode usar ambos os símbolos juntos. Você aprenderá mais sobre esse último ponto mais tarde, mas por enquanto dê uma olhada nos usos de ambos os símbolos individualmente.

Exemplos de Uso

Suponha que você escreva uma função uso_do_asterisco() com um asterisco como um de seus parâmetros. Em seguida, você a chama:

 
def uso_do_asterisco(either, *, keyword_only):
    print(either, keyword_only)

uso_do_asterisco(either="Frank", keyword_only="Dean")
uso_do_asterisco("Frank", keyword_only="Dean")
uso_do_asterisco("Frank", "Dean")

Você define o parâmetro either da sua função antes do asterisco, o que significa que você pode passar argumentos a ele por palavra-chave ou posição. O parâmetro keyword_only da sua função pode aceitar argumentos apenas por palavra-chave porque você o definiu após o asterisco. As duas primeiras chamadas da função têm sucesso porque você passa o segundo argumento por palavra-chave. Note que passar o primeiro argumento por palavra-chave ou posição funciona muito bem.

A terceira chamada da função falha porque você tentou passar o segundo argumento por posição. A mensagem de erro informa que você usou argumentos posicionais demais.

Observação: Se você decidir usar o asterisco, não pode usá-lo como o último parâmetro em sua função. O asterisco é projetado para forçá-lo a passar todos os parâmetros subsequentes por palavra-chave. Se você o colocar por último, não pode haver parâmetros subsequentes.

E se você escrever uma função uso_da_barra() com uma barra como parte do seu cabeçalho:

 
def uso_da_barra(positional_only, /, either):
    print(positional_only, either)

uso_da_barra("Frank", either="Dean")
uso_da_barra(positional_only="Frank", either="Dean")
uso_da_barra("Frank", "Dean"

Desta vez, você usou a barra para garantir que deve passar todos os argumentos precedentes por posição. Quando você passa o argumento positional_only por posição, a chamada funciona. No entanto, quando você passa o mesmo argumento por palavra-chave, a chamada falha. A chamada final da função mostra que você pode passar o argumento either tanto por posição quanto por palavra-chave.

Nota: A documentação do Python se refere a * e / como símbolos e parâmetros especiais. Neste tutorial, você verá ambos os termos quando apropriado. O termo “operadores” só se referirá ao uso deles em multiplicação e divisão. Além disso, o termo “argumentos” se referirá aos dados que você está passando para uma função, enquanto “parâmetros” se referirá aos espaços reservados do cabeçalho da função que os estão recebendo.

PEP 3102 – Argumentos Apenas por Palavra-Chave define o uso do asterisco em termos de um argumento, enquanto PEP 570 – Parâmetros Apenas por Posição do Python define a barra em termos de um parâmetro, embora o símbolo também apareça brevemente em PEP 570. PEP 570 também usa as palavras “parâmetro” e “argumento” de forma intercambiável.

Como usar o Asterisco e a Barra ao Definir suas Próprias Funções

Agora que você já entende o conceito do asterisco e da barra, é hora de aplicá-los às suas próprias funções. Mas talvez você tenha algumas perguntas sobre que tipos de funções esses parâmetros especiais permitem que você escreva. Continue lendo para descobrir!

Funções que Aceitam Apenas Argumentos por Palavra-Chave

Anteriormente, você aprendeu que não pode incluir o asterisco como o último parâmetro ao definir sua função. No entanto, você pode ficar surpreso ao descobrir que ele pode ser o primeiro parâmetro. Nesse caso, você está especificando que sua função só aceitará argumentos por palavra-chave.

Em Python, um argumento por palavra-chave é aquele que você passa para uma função usando o nome de seu parâmetro – por exemplo, primeiro_nome="Dean". Passar seus argumentos por palavra-chave torna seu código mais legível e também torna o uso da função mais significativo para seus usuários. Você pode passar argumentos por palavra-chave em qualquer ordem, mas eles devem vir depois de argumentos posicionais, se aplicável.

Você já sabe que os parâmetros definidos após o asterisco só aceitam argumentos por palavra-chave. Para escrever uma função que aceita apenas argumentos por palavra-chave, você define o parâmetro especial asterisco primeiro:

 
def imprimir_tres_membros(*, membro1, membro2, membro3):
    print(f"membro1 é {membro1}")
    print(f"membro2 é {membro2}")
    print(f"membro3 é {membro3}")

Essa função imprimir_tres_membros() aceita apenas argumentos por palavra-chave. As duas primeiras chamadas passam todos os argumentos com sucesso por palavra-chave. Cada uma das duas chamadas finais resulta em um TypeError porque você passou argumentos por posição. Colocar o asterisco como o primeiro parâmetro significa que você deve fornecer todos os argumentos como argumentos por palavra-chave. As mensagens de erro indicam onde você errou.

Funções que Aceitam Apenas Argumentos por Posição

Em Python, qualquer argumento que não é passado por palavra-chave é passado por posição. Você deve passar argumentos posicionais na mesma ordem em que definiu seus parâmetros no cabeçalho da função. Sempre passe argumentos posicionais antes de argumentos por palavra-chave. Várias das funções internas do Python exigem que você passe todos os argumentos por posição. No Python 3.8 e posterior, você também pode impor isso em suas próprias funções.

Anteriormente, você viu como deve passar quaisquer argumentos para parâmetros definidos antes da barra por posição. Para escrever uma função que aceita apenas argumentos por posição, você define o parâmetro especial barra por último:

 
def imprimir_tres_membros(membro1, membro2, membro3, /):
    print(f"membro1 é {membro1}")
    print(f"membro2 é {membro2}")
    print(f"membro3 é {membro3}")

Neste exemplo, você só pode passar membro1, membro2 e membro3 por posição. A primeira chamada atende a esse critério e funciona, enquanto as outras falham porque você tentou usar argumentos por palavra-chave. Novamente, as mensagens de erro o mantêm no caminho certo.

*O Asterisco Simples Relacionado a args

Tanto o asterisco simples quanto *args indicam quais argumentos você deve passar por palavra-chave. O asterisco significa o mesmo nas duas utilizações. O componente args simplesmente fornece uma tupla para armazenar quaisquer argumentos posicionais adicionais que você passar.

Antes de continuar, você pode gostar de revisar o significado do parâmetro *args. Suponha que você escreva uma função obter_media() como mostrado abaixo:

 
pythonCopy code
def obter_media(*args):
    print(args)
    return sum(args) / len(args)

O parâmetro *args permite que você escreva uma função que pode aceitar um número variável de argumentos posicionais individuais em cada chamada. Seu código empacota todos esses argumentos em uma tupla chamada args.

Suponha que você chame sua função obter_media() duas vezes, primeiro com três argumentos e depois com cinco:

 
obter_media(1, 2, 3)
# Saída: (1, 2, 3)
# Saída: 2.0

obter_media(1, 3, 5, 7, 9)
# Saída: (1, 3, 5, 7, 9)
# Saída: 5.0

Quando você chama obter_media() pela primeira vez com três argumentos, pode ver que a tupla args contém três elementos. Ela contém cinco depois da sua segunda chamada. Desde que você passe um ou mais inteiros ou floats como argumentos, sua função calculará a média. Experimente com um ou mais valores numéricos e observe que a função sempre funcionará.

Como antes, se você tentar misturar os dois tipos antes de *args, os argumentos posicionais devem vir antes dos argumentos por palavra-chave. Se você tentar adicionar argumentos posicionais adicionais após alguns argumentos por palavra-chave, *args não poderá armazená-los.

Usando o Asterisco e a Barra Juntos

Agora você entende a mecânica do asterisco e da barra, e sabe como usá-los individualmente. Mas e quando você os usa juntos em uma definição de função?

Ao usar ambos os operadores juntos, a barra deve vir antes do asterisco. Se você trocar a ordem, o asterisco exigiria argumentos apenas por palavra-chave entre os dois símbolos, enquanto a barra exigiria argumentos apenas por posição nesse espaço. Você pode passar argumentos para qualquer parâmetro entre a barra e o asterisco tanto por posição quanto por palavra-chave.

Para ver isso em ação, suponha que você escreva uma função imprimir_quatro_membros() que inclui ambos a barra e o asterisco na ordem correta:

 
def imprimir_quatro_membros(membro1, membro2, /, membro3, *, membro4):
    print(f"membro1 é {membro1}")
    print(f"membro2 é {membro2}")
    print(f"membro3 é {membro3}")
    print(f"membro4 é {membro4}")

No exemplo acima, você deve passar os argumentos para membro1 e membro2 por posição devido à barra. Você pode passar o argumento membro3 por posição ou por palavra-chave, enquanto deve passar membro4 por palavra-chave. Vamos realizar alguns testes:

 
imprimir_quatro_membros("Frank", "Dean", membro3="Sammy", membro4="Joey")
# Saída:
# membro1 é Frank
# membro2 é Dean
# membro3 é Sammy
# membro4 é Joey

Como você pode ver, tudo funciona como esperado. Tente passar o argumento “Sammy” por posição e você obterá o mesmo resultado.

Agora tente definir a barra e o asterisco na ordem inversa. Você vai produzir um erro de sintaxe:

 
def imprimir_quatro_membros(membro1, membro2, *, /, membro3, membro4):
    ...

A definição da função acima é inválida porque o asterisco força você a passar todos os argumentos subsequentes apenas por palavra-chave, enquanto a barra força você a passar os argumentos anteriores apenas por posição. Há confusão sobre como você pretende passar membro3. Python também não sabe, então ele desiste! Como a mensagem de erro lembra, a barra deve vir antes do asterisco.

Ao colocar ambos os operadores especiais juntos na ordem correta, você pode forçar que tudo à esquerda da barra seja passado apenas por posição e tudo à direita do asterisco seja passado apenas por palavra-chave. Nada além disso é possível.

Usando o Asterisco Sem Outros Parâmetros

O asterisco é projetado para forçar você a passar todos os argumentos subsequentes apenas por palavra-chave. Se você usá-lo sozinho, não haverá parâmetros subsequentes para aceitar esses argumentos. Como você pode ver abaixo, você não passará da linha de definição da função:

 
def imprimir_tres_membros(*):
    ...

Se você tentar escrever uma função com apenas um asterisco, tudo o que você conseguirá será um erro de sintaxe. Desista disso!

O mesmo não é verdade para *args. Você pode usar isso sozinho, como você viu antes com a função obter_media(*args). O parâmetro args pode aceitar quantos argumentos posicionais adicionais você desejar. Naturalmente, você não pode passar argumentos por palavra-chave porque não há parâmetros nomeados definidos na função.

*Usando Tanto args Quanto o Asterisco Juntos

Lembre-se de que o parâmetro *args e o asterisco simples obrigam você a passar todos os argumentos subsequentes por palavra-chave. Se você tentar usar *args antes ou depois do asterisco simples, ocorrerá um erro de sintaxe:

 
def imprimir_tres_membros(membro1, membro2, *args, *, membro3):
    ...

O erro de sintaxe ocorre porque o Python não está satisfeito em ter que dizer a você para passar todos os argumentos subsequentes por palavra-chave duas vezes. A mensagem de erro lembra que você deve usar um único asterisco uma vez.

Por que Usar Parâmetros Especiais em Sua Função?

Existem várias razões pelas quais você pode precisar fazer isso: para compensar parâmetros mal nomeados, garantir a compatibilidade com versões anteriores e fornecer documentação interna.

Um benefício comum de forçar argumentos posicionais ocorre quando os nomes dos parâmetros da sua função não indicam claramente o seu propósito. Revelar esses nomes aos seus usuários para permitir a passagem de palavra-chave introduziria código ilegível e confundiria o usuário.

Suponha que você escreva uma função simples para produzir um nome de usuário, mas force-a a aceitar apenas argumentos posicionais:

 
def nome_usuario(nome, sobrenome, /):
    return sobrenome + nome[0]

Esta função nome_usuario() aceita apenas argumentos posicionais. As duas primeiras chamadas passam todos os argumentos com sucesso por posição. Cada uma das duas chamadas finais resulta em um TypeError porque você passou argumentos por palavra-chave. Colocar a barra como o último parâmetro significa que você deve fornecer todos os argumentos como argumentos posicionais. As mensagens de erro indicam onde você errou.

Mas mesmo que sua função tenha dois parâmetros mal nomeados, esses são sempre ocultados do usuário. Como leitor de Real Python que sabe que a legibilidade conta, você provavelmente aproveitaria a oportunidade para atualizá-los, mas isso pode envolver muitas atualizações dentro do corpo da função também. Isso, por si só, pode levar a problemas. O uso inteligente da barra evitou a necessidade disso.

Um segundo caso de uso comum é a compatibilidade com versões anteriores. Suponha que muito código use sua função original nome_usuario(), mas você decide aprimorá-la. Além dos nomes dos parâmetros vagos, agora você tem o problema de garantir que a nova versão seja compatível com a versão anterior. Suponha que você atualize sua função da seguinte forma:

 
def nome_usuario(nome, sobrenome, /, *, inicial_sobrenome=True):
    if inicial_sobrenome:
        return sobrenome + nome[0]
    else:
        return nome[0] + sobrenome

A versão atualizada de nome_usuario() ainda precisa de dois argumentos posicionais, mas agora oferece a opção de usar o argumento por palavra-chave inicial_sobrenome. Felizmente, inicial_sobrenome é um nome sensato, então os usuários não vão entender errado. Como inicial_sobrenome tem um valor padrão, esse parâmetro é opcional. No entanto, se você não quiser usar o valor padrão, False, então você deve passar seu argumento para ele por palavra-chave.

Primeiro, você decide testar a função para garantir que ela seja realmente compatível com a versão anterior:

 
nome_usuario("Frank", "Sinatra")
# Saída: 'SF'

nome_usuario("Frank", "Sinatra", inicial_sobrenome=False)
# Saída: 'FS'

Quando você decide testar a versão atualizada de nome_usuario() para se certificar de que a barra funciona como pretendido:

 
pythonCopy code
nome_usuario("Frank", sobrenome="Sinatra")
# Saída: 'FS

Isso funciona como esperado. A barra obriga você a passar sobrenome por posição e nome por palavra-chave. A barra também esconde o segundo nome vago. Além disso, você pode usar os argumentos apenas por posição como sempre pôde fazer.

Finalmente, você testa se a barra ainda impede que você use argumentos por palavra-chave para sobrenome:

 
nome_usuario(nome="Frank", sobrenome="Sinatra")
# TypeError: nome_usuario() got some positional-only arguments passed as keyword arguments: 'nome'

Essa mensagem de erro mostra que você só pode passar argumentos por posição para nome e por palavra-chave para sobrenome. Você tentou passar nome por palavra-chave, mas a barra o forçou a passar apenas por posição. Como a mensagem de erro sugere, você cometeu um erro. A barra está fazendo o trabalho dela corretamente.

Resumo

Você aprendeu que o asterisco e a barra podem ser usados como parâmetros especiais em definições de função. O asterisco força você a passar todos os argumentos subsequentes por palavra-chave, enquanto a barra força você a passar todos os argumentos precedentes apenas por posição. Você também viu que pode usar ambos os símbolos juntos para controlar se seus argumentos podem ser passados por posição, por palavra-chave ou ambos. Parâmetros como *args e parâmetros especiais obrigam você a passar todos os argumentos subsequentes por palavra-chave, enquanto a barra obriga você a passar todos os argumentos precedentes apenas por posição. A barra também obriga você a passar argumentos por posição entre a barra e o asterisco.

Com base nesses exemplos, você deve ter uma compreensão sólida dos casos de uso do asterisco e da barra. Use-os para deixar claro como seus usuários devem passar argumentos para suas funções. Use-os para forçar argumentos por posição e palavra-chave para simplificar a passagem de argumentos para suas funções. Use-os para corrigir os problemas de compatibilidade com versões anteriores. Use-os para garantir que os parâmetros mal nomeados não causem confusão. Use-os para tornar suas funções mais legíveis.

O asterisco e a barra são apenas uma das muitas maneiras de escrever funções em Python. Portanto, eles são apenas mais uma ferramenta na sua caixa de ferramentas. Use-os com sabedoria!

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Rolar para cima