25 de outubro de 2012

Função com lista variável de argumentos

Se existe uma coisa que volta e meia precisamos, é de uma função que possa aceitar uma quantidade diferente de argumentos, dependendo da chamada que fazemos. Me diga se você nunca precisou disso!

Python tem algumas formas inteligentes de resolver essa questão.

A primeira alternativa é usando *args como argumento da função. Vamos a um exemplo, que você vai entender:
>>> def f(*args):
...     print args
... 
>>> f(10, 'joao', True)
(10, 'joao', True)
>>> 
>>> f('programador', 1000.50)
('programador', 1000.50)
>>> 

Já entendeu, né? Os parâmetros passados à função foram recebidos como uma tupla.

Na verdade, o nome args não tem nenhuma importância, pois é apenas uma convenção que significa "arguments" (assim como self nos métodos das classes significa "eu mesmo" -- em tradução livre). O que importa é o asterisco antes do nome.

Só que, dependendo do que você for implementar, fica melhor se os parâmetros forem nomeados. Aí temos a segunda alternativa, que é usar **kwargs. Veja nosso exemplo, agora:
>>> def g(**kwargs):
...     print kwargs
...
>>> g(nota=10, nome='joao', aprovado=True)
{'aprovado': True, 'nota': 10, 'nome': 'joao'}
>>> 

Viu? Ao invés de uma tupla, dessa vez recebemos um dicionário. Isso significa que não podemos confiar que os parâmetros estarão na mesma ordem que foram enviados. Mas como eles estão nomeados, qual a importância disso, né?

Novamente, o nome kwargs, que significa "keyword arguments", não importa. O que determina esse comportamento são os 2 asteriscos antes dele.

NOTA: apesar de args e kwargs serem apenas convenções, eu sugiro que você não use outros nomes. Isso facilitará, e muito, a vida de quem for mexer no seu programa.

Explorando um pouquinho mais as opções acima, também podemos fazer assim:
>>> a = [17, '25/10/2012']
>>> f(*a)
(17, '25/10/2012')
>>>
>>> d = dict(nome='maria', filhos=['pedrinho', 'zezinho'])
>>> g(**d)
{'filhos': ['pedrinho', 'zezinho'], 'nome': 'maria'}
>>> 

Percebeu o poder disso? ;-)

Tá, mas se você quiser deixar explícito quais são os argumentos da sua função? Bem, aí existe uma terceira alternativa, que é o recurso clássico de parâmetros nomeados. Assim:
>>> def h(x=None, y=None, z=None):
...     print x, y, z
...
>>> h(5, z=20)
5 None 20
>>>
>>> h(z=20, x=7, y=2)
7 2 20
>>> 

Dessa forma se você não informar o nome dos argumentos, eles serão considerados posicionais. Se informar, podem ir em qualquer sequência.

Também, é possível informar os parâmetros em uma lista ou em um dicionário ao invés de passá-los um a um:
>>> def h(x=None, y=None, z=None):
...     print x, y, z
...
>>> params = [5, 10]
>>> h(*params)
5 10 None
>>>
>>> params_nomeados = {'x':5, 'z':20}
>>> h(**params_nomeados)
5 None 20
>>> 

Eu sou Vinicius Assef, um programador do século passado que gosta de Python, pratica Lean Development e acredita em Deus. Você pode me contactar por email ou twitter.

Um comentário:

  1. Valeu por esta publicando esse tutorial sobre funções em python,são pessoas assim que merecem os parabéns por
    estarem contribuindo para que todos aprendam sobre programação,excelente tutorial,se você como programado mim desse umas dicas de como devo prosseguir programando ficaria muito grato.Eu já arranho alguns programas simples em python e também já crio aplicações simples para web utilizando o framework django,só que não tenho muito dinheiro para investir e não consigo encontrar material sobre python e django mais avançados para continuar meu aprendizado sera que esta na hora de partir para outras linguagens de programação,meu email para contato e maldisneimartins@gmai.com,constaria muito de receber uma opinião de um programador desde já agradeço e value.

    ResponderExcluir

Marcadores