Tuple unpacking, ou em bom português, desempacotamento de tupla. Tá aí algo que usamos pra caramba, mas sobre o qual pouco ouvimos falar. Desempacotar uma tupla pode ser explicado como o ato de atribuir os elementos dela individualmente a outros objetos. Veja um exemplo de desempacotamento de tupla:
>>> t = (1, 2, 3, 4) >>> a, b, c, d = t # "desempacotando" uma tupla >>> print b * c 6
No exemplo acima, o primeiro elemento da tupla t é atribuído para o nome a. O segundo elemento de t é atribuído para b, e assim por diante. É óbvio que, para desempacotar uma tupla, é necessário que tenhamos no lado esquerdo da expressão a quantidade necessária de variáveis para receber os valores. Veja uma situação que gera um erro por tentarmos desempacotar uma tupla de 4 elementos para 3 variáveis:
>>> t = (1, 2, 3, 4) >>> a, b, c = t Traceback (most recent call last): File "", line 1, in ValueError: too many values to unpack
"ValueError: too many values to unpack", que significa “valores demais para desempacotar".
Mas isso é útil para quê?
Já viu uma função retornando mais de um valor em um único return em Python?
def f(x):
return x, x*2, x*3
valor, dobro, triplo = f(2)
Isso é algo bastante comum em código Python. O código da segunda linha (return x, x*2, x*3) na realidade retorna apenas um valor, que é uma tupla. A expressão x, x*2, x*3 cria uma tupla de 3 elementos, apesar de não estar envolta em parênteses. Assim sendo, a chamada de função f(2) retorna uma tupla de 3 valores, que são então desempacotados para as variáveis valor, dobro e triplo, respectivamente.
Percorrendo listas de tuplas
Quando temos uma lista contendo tuplas, podemos percorrê-la assim como qualquer outra lista. Veja:
>>> lista = [(1, 2, 3), (2, 4, 6), (4, 8, 12), (8, 16, 24)] >>> for tupla in lista: ... print tupla ... (1, 2, 3) (2, 4, 6) (4, 8, 12) (8, 16, 24)
Dentro do for, poderíamos desempacotar os valores de cada tupla, se precisássemos usá-los individualmente:
>>> lista = [(1, 2, 3), (2, 4, 6), (4, 8, 12), (8, 16, 24)] >>> for tupla in lista: ... a, b, c = tupla ... print a * b * c ... 6 48 384 3072
Mas, poderíamos fazer melhor, desempacotando os elementos dentro da expressão do for:
>>> lista = [(1, 2, 3), (2, 4, 6), (4, 8, 12), (8, 16, 24)] >>> for (a, b, c) in lista: ... print a * b * c ... 6 48 384 3072
Poderíamos também omitir os parênteses na hora de desempacotar as tuplas:
>>> lista = [(1, 2, 3), (2, 4, 6), (4, 8, 12), (8, 16, 24)] >>> for a, b, c in lista: ... print a * b * c ... 6 48 384 3072
Mas nem tudo interessa
Considere que nas tuplas da lista lista acima, somente nos interessa o primeiro elemento de cada tupla. Para não precisar criar dois novos nomes (b e c) que nunca serão usados, podemos utilizar um idioma que é um tanto comum em código python: usar o caractere de undescore _ como o nome da variável que vai receber o primeiro e último valores das tuplas:
>>> lista = [(1, 2, 3), (2, 4, 6), (4, 8, 12), (8, 16, 24)] >>> for a, _, _ in lista: ... print a * 2 ... 2 4 8 16
Lembre-se: usamos isso somente em casos em que os elementos não serão necessários no escopo do for.
O _ é utilizado comumente como um nome para não me interessa. Por exemplo*, em uma tupla contendo nome, sobrenome e apelido, em um momento em que estamos interessados apenas no nome e no sobrenome, poderíamos usar o _ para indicar que o apelido não é importante neste momento:
dados_pessoais = ('Joao', 'Silva', 'joaozinho')
...
nome, sobrenome, _ = dados_pessoais
*Exemplo adaptado dessa resposta no StackOverflow.com
Como o autor da resposta no link acima comenta, é preciso tomar cuidado com o uso do _, pois ele também é utilizado em outros contextos e isso pode gerar confusão e mau-funcionamento. Ele é bastante usado com a biblioteca de internacionalização gettext como um atalho para funções usadas com muita frequência.
Então é isso. O desempacotamento de tuplas é um dos recursos que eu considero mais legais em Python, pois elimina bastante código desnecessário. Até a próxima! 🙂