Asteriscos em chamadas de funções

Diga aí, o que o código abaixo irá produzir?

def func(a, b, c, d):
    return (a + b) / (c + d)

lista_de_argumentos = [4, 6, 2, 3]
print func(*lista_de_argumentos)

Se você sabe a resposta (que é 2), provavelmente já conhece esse uso do * (asterisco ou estrela).
Caso não tenha entendido muito bem, leia o resto do texto.

A estrela (asterisco) na chamada de funções

A função func listada acima deve receber 4 parâmetros (a, b, c e d). Quando passamos um argumento precedido de um asterisco, esse argumento (se for uma lista ou tupla) será desempacotado e cada um dos elementos será passado como um dos argumentos posicionais da função. No exemplo acima, o primeiro elemento de lista_de_argumentos será passado ao argumento a, o segundo ao elemento b, e assim por diante. No exemplo acima, a chamada de função func(*lista_de_argumentos) dá no mesmo que func(4, 6, 2, 3), pois o desempacotamento é automático. A imagem abaixo ilustra o que acontece:

Exemplo de passagem de parâmetros

Se lista_de_argumentos tivesse uma quantidade de elementos diferente da quantidade de argumentos exigidos por func, uma exceção seria disparada. Veja:

>>> lista = [4, 6, 2, 3, 10]
>>> print func(*lista)
------------------------------------------------------------------
TypeError                        Traceback (most recent call last)
 in ()
----> 1 print func(*lista)
TypeError: func() takes exactly 4 arguments (5 given)

A estrela-dupla na chamada de funções

De forma semelhante, podemos também desempacotar dicionários em chamadas de funções. Nesses dicionários, as chaves deverão ser os nomes dos argumentos e os valores serão os valores que queremos passar como argumentos. Seguindo com o exemplo da função func, poderíamos passar um dicionário com os nossos parâmetros nomeados, precedido de **:

>>> argumentos = {'d': 3, 'c': 2, 'b': 6, 'a': 4}
>>> print func(**argumentos)
2

Assim, os valores armazenados no dicionário serão desempacotados direitinho como argumentos para a função, de acordo com as chaves correspondentes a eles. Assim, 4 será o argumento a, 6 será passado como argumento para b e assim por diante.

Quando usar isso?

Esse açúcar sintático oferecido por Python é bem útil quando temos uma lista contendo os valores que deverão ser passados para uma função. Por exemplo, ao invés de fazer:

>>> lista = [6, 4, 2, 3]
>>> func(lista[0], lista[1], lista[2], lista[3])

podemos fazer:

>>> lista = [6, 4, 2, 3]
>>> func(*lista)

O uso vai surgir da necessidade. Às vezes temos uma função que retorna uma tupla de n valores e queremos passar esses valores diretamente como argumentos para outra função, que exige n parâmetros. É aí que entra o *.

Anúncios

4 comentários sobre “Asteriscos em chamadas de funções

  1. Só faltou o exemplo do zip com *, que faiz o contrário do zip normal:

    >>> tup1 = (1, 2, 3)
    >>> tup2 = (4, 5, 6)
    >>> zipped_tups = zip(tup1, tup2)
    >>> zipped_tups
    [(1, 4), (2, 5), (3, 6)]
    >>> tupA, tupB = zip(*zipped_tups)
    >>> assert tup1 == tupA and tup2 == tupB
    
    
    
  2. Pingback: each_cons — percorrendo sequências em N elementos por vez | Python Help

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s