Python: Passando lista dinâmica de argumentos para um função.

Atualmente estou trabalhando em um projeto pessoal que consiste em fazer um bot para o Telegram utilizando Python. A API do Telegram é muito flexível e permite vários tipos de interação com o usuário do bot. O problema é que, dependendo do caso, vou precisa de um grupo X ou Y de argumentos para a função de enviar mensagem. Dependendo do caso, vou precisar disponibilizar para o usuário um  teclado personalizado, outra hora vou precisar enviar um  texto formatado.  Para resolver este problema, podemos utilizar a lógica abaixo para uma solução rápida e simples.

Antes de qualquer outra coisa, para fins de exemplo, vamos considerar a função abaixo como base para os próximos exemplos. Todos eles irão chamar esta função:

 

Como relembrar é viver, vamos revisar rapidamente algumas formas de se chamar esta função:

Primeira forma, informando os argumentos posicionalmente:

No exemplo acima, primeiro chamados a função get_food passando apenas o argumento obrigatório. Na segunda chamada, passamos todos os argumentos, mas de forma posicional, ou seja, na mesma ordem em que foram declarados na função.

A segunda forma é passar os argumentos nominalmente:

Neste segundo exemplo, fizemos igual ao anterior: Primeiro passamos apenas o argumento obrigatório e depois utilizamos todos os argumentos. A diferença é que os argumentos foram passados com os respectivos nomes. Sendo assim, ao contrário do exemplo anterior, não importa a ordem em que você fornece os argumentos. Sempre vai funcionar. Pessoalmente, acho mais organizado fazer desta forma.

Ok. Revisão feita. Vamos entrar no assunto deste post.

Para este exemplo, vamos criar mais 2 funções, mas estas vão atuar como wrapper da get_food, ou seja, elas vão encapsular a lógica e as regras envolvidas em chamar função get_food. Esta primeira função wrapper foi feita meramente para fins didáticos. Pelos poderes de grayskull! Não imagine que eu faria algo assim na vida real…

O que esta função está fazendo? Ela não possui argumentos obrigatórios, ou seja, você pode chama-la sem passar qualquer argumento e tudo funcionará. O pulo do gato deste tipo de função é que você pode controlar o fluxo de informações e como a função alvo (no caso, a get_food) vai ser chamada.

Neste caso, estou considerando 4 cenários:

  1. Nenhum argumento é passado: Chamará a função get_food, passando 42 no argumento quantidade;
  2. Passando apenas o argumento food (ou quantidade e food);
  3. Passando os argumentos food e express (podendo ou não existir o argumento quantidade);
  4. Passando todos os argumentos (podendo ou não existir o argumento quantidade);

Qualquer cenário que não se encaixe nestes 4 irá produzir um erro e para cada cenário, preciso repetir a chamada da função get_food. Péssimo, certo? Seria um pesadelo ter que conviver com um sistema cheio de funções deste tipo.

Veja o resultado da chamada desta função:

Se faltar um argumento, mesmo que opcional, ocorre um erro. Para nossa alegria, o Python provê uma maneira mais fácil de tratar este tipo de situação.

O segredo está em montar um dicionário com os argumentos que você quer passar e utiliza-lo na função, com o prefixo **. Veja abaixo o exemplo da segunda função wrapper, que utiliza este método:

Ela é menor que a anterior, mais fácil de ler e de implementar possíveis tratamentos futuros nas informações que precisam ser passadas para a função get_food. Outro ponto positivo desta abordagem é que ela abrange todas as possibilidades que a própria função alvo oferece.

Abaixo está o log de execução desta função, para os mesmos casos de uso da anterior:

 

Momento TL:DR: Ao invés de ficar agonizando na hora de definir como mandar X ou Y argumentos para uma função, crie um dicionário (nome_do_argumento:valor) e passe ele para a função, colocando ** antes do nome da variável. Exemplo: get_food(**dict_args)

Você também pode criar uma tuple ou um vetor e fazer a mesma coisa. A diferença é que, se os argumentos não estiverem com seus respectivos nomes, eles precisam estar na ordem em que foram declarados na função.

Fonte destes exemplos no GitHub: https://github.com/brenordv/python-snippets/tree/master/pass-dynamic-args-to-func

Espero ter ajudado.

The following two tabs change content below.
Breno RdV
Ex-Psicólogo, com quase uma década de experiência em Recursos Humanos e Gestão de Pessoas, atual desenvolvedor e Analista de Sistemas, trabalhando com PowerBuilder, C#, PowerShell e expandindo horizontes para Python, Xamarin, PHP, Angular e (por que não?) Unity.

Comments

comments

Posted in Dev, Python and tagged , , , , , , , .