Python Desempacotamento
Na aula Tuplas, a data de nascimento da Ana virou (12, 3, 1990), e para usar cada parte era preciso escrever aniversario[0], aniversario[1], aniversario[2]. Funciona, mas ninguém lembra o que é o [1]. O desempacotamento (em inglês, unpacking) resolve isso: numa linha só, cada valor da tupla vai para uma variável com nome: dia, mes, ano = aniversario.
- A desempacotar uma tupla (ou lista, ou texto) em várias variáveis de uma vez.
- A trocar o valor de duas variáveis com
a, b = b, a, e por que o jeito "óbvio" não funciona. - A juntar "o resto" numa lista com o asterisco:
primeira, *resto = notas. - A ignorar valores com
_e a desempacotar dentro dofor. - Os erros reais:
too many values to unpack,not enough values to unpacke companhia.
A ideia: desfazer a mala
A Ana chega de viagem com uma mala que tem três coisas: uma camiseta, uma calça e um tênis. Desfazer a mala é tirar cada coisa e pôr no seu lugar: a camiseta na gaveta de cima, a calça na do meio, o tênis na sapateira. Uma coisa para cada lugar, na ordem.
Desempacotar é isso. A tupla é a mala; as variáveis à esquerda do = são os lugares. O Python tira o primeiro valor e põe na primeira variável, o segundo na segunda, e assim por diante. A regra de ouro: o número de lugares tem de ser igual ao número de coisas. Sobrou coisa ou faltou coisa, o Python reclama.
1. O primeiro desempacotamento
aniversario = (12, 3, 1990)
dia, mes, ano = aniversario
print(dia)
print(mes)
print(ano)
print(f"Nasci em {dia}/{mes}/{ano}")
- aniversario = (12, 3, 1990)
- A "mala": uma tupla com três valores.
- dia, mes, ano
- Três variáveis separadas por vírgula, do lado esquerdo do
=. São os três "lugares". - =
- A atribuição de sempre. Só que, com várias variáveis à esquerda, o Python desempacota o valor da direita.
- resultado
diarecebe12,mesrecebe3,anorecebe1990. Na ordem: primeiro com primeiro, segundo com segundo.
$ python3 d_basico.py 12 3 1990 Nasci em 12/3/1990
Compare com a aula anterior: f"Nasci em {dia}/{mes}/{ano}" se lê muito melhor que f"Nasci em {aniversario[0]}/{aniversario[1]}/{aniversario[2]}". Esse é o ganho do desempacotamento: nomes no lugar de números.
2. Não é só tupla
Dá para desempacotar qualquer coisa que tenha itens em sequência: listas, textos (letra por letra) e até uma tupla escrita ali mesmo, sem parênteses.
nome, idade = ["Ana", 34] print(nome, idade) a, b, c = "sol" print(a, b, c) x, y = 10, 20 print(x, y)
$ python3 d_fontes.py Ana 34 s o l 10 20
A última forma, x, y = 10, 20, é a que você já viu na aula Atribuição Múltipla. Agora dá para entender o que acontece por dentro: 10, 20 é uma tupla (a vírgula faz a tupla, lembra?), e o Python a desempacota em x e y.
3. A troca: a, b = b, a
A Ana tem duas variáveis, a com "café" e b com "chá", e quer trocar: a fica com o chá e b com o café. O jeito que parece óbvio dá errado:
a = "café" b = "chá" a = b b = a print(a, b)
$ python3 d_troca_errada.py chá chá
Os dois ficaram com chá. Na linha 3, a = b pôs "chá" em a, e o "café" se perdeu: nenhuma variável guarda mais esse valor. Na linha 4, b = a copiou o chá de volta. É como trocar o conteúdo de dois copos sem um terceiro copo: não dá.
O jeito clássico, em muitas linguagens, é usar um terceiro copo, uma variável auxiliar:
a = "café" b = "chá" guarda = a a = b b = guarda print(a, b)
$ python3 d_troca_aux.py chá café
Em Python existe um jeito mais curto, com desempacotamento:
a = "café"
b = "chá"
print("Antes:", a, b)
a, b = b, a
print("Depois:", a, b)
$ python3 d_troca.py Antes: café chá Depois: chá café
- O Python calcula primeiro o lado direito inteiro:
b, avira a tupla("chá", "café"). Os dois valores ficam guardados nessa tupla. - Só depois ele desempacota a tupla no lado esquerdo:
arecebe "chá",brecebe "café". - Nada se perde, porque a tupla fez o papel do terceiro copo, sem você precisar criá-lo.
Missão: troque os valores de a e b com uma linha só, usando desempacotamento, para o programa mostrar a = chá e b = café.
a = "café"
b = "chá"
# escreva a troca aqui
print("a =", a)
print("b =", b)
a = "café"
b = "chá"
a, b = b, a
print("a =", a)
print("b =", b)
4. O asterisco: "e o resto"
E quando você quer só o primeiro valor, e o resto junto? A Ana tem as notas do bimestre e quer separar a primeira das outras. Com um * antes do nome, a variável vira uma lista que recolhe tudo o que sobrou:
notas = (8, 10, 6, 10, 9) primeira, *resto = notas print(primeira) print(resto) *inicio, ultima = notas print(inicio) print(ultima) primeira, *meio, ultima = notas print(primeira, meio, ultima)
$ python3 d_estrela.py 8 [10, 6, 10, 9] [8, 10, 6, 10] 9 8 [10, 6, 10] 9
- primeira, *resto = notas
primeirapega o primeiro valor (8).*restopega todo o resto, numa lista.- *inicio, ultima = notas
- O asterisco pode vir antes:
ultimapega o último valor (9) einiciorecolhe o que vem antes dele. - primeira, *meio, ultima = notas
- Ou no meio: primeiro e último com nome, e o miolo numa lista.
- [ … ]
- Repare nos colchetes: a variável com asterisco é sempre uma lista, mesmo que a origem seja uma tupla.
Se não sobrar nada para o asterisco, ele fica com uma lista vazia. Não é erro:
primeiro, *resto = ["só eu"] print(primeiro) print(resto)
$ python3 d_estrela_vazia.py só eu []
Com o asterisco, a regra de ouro fica mais flexível: as variáveis sem asterisco precisam de um valor cada, e o asterisco aceita qualquer quantidade, até zero. Mas só pode haver um asterisco por desempacotamento (veja Quando dá errado).
5. Ignorando valores com _
Às vezes você não precisa de um dos valores. O costume em Python é dar a ele o nome _ (sublinhado), que quer dizer "não me interessa":
nome, _, cidade = ("Ana", 34, "Teresina")
print(nome, "mora em", cidade)
primeiro, *_ = ("seg", "ter", "qua")
print(primeiro)
$ python3 d_ignorar.py Ana mora em Teresina seg
O _ é uma variável comum; o Python guarda o 34 nela normalmente. O nome é só um recado para quem lê: "este valor eu descartei de propósito". E *_ descarta todo o resto.
6. Desempacotando no for
Aqui o desempacotamento brilha. Uma lista de tuplas é muito comum: cada tupla é um "registro" (um aluno e sua nota, um produto e seu preço). No for, você desempacota cada tupla direto nas variáveis do laço:
turma = [("Ana", 9), ("Bia", 7), ("Caio", 8)]
for nome, nota in turma:
print(f"{nome} tirou {nota}")
$ python3 d_for.py Ana tirou 9 Bia tirou 7 Caio tirou 8
A cada volta, o for pega uma tupla, por exemplo ("Ana", 9), e faz nome, nota = ("Ana", 9). Sem desempacotar, você escreveria for aluno in turma: e depois aluno[0] e aluno[1]. Esse mesmo truque aparece de novo em Percorrendo um Dicionário e em enumerate() e zip().
Funções que devolvem dois valores
Algumas funções do Python devolvem uma tupla, justamente para você desempacotar. A divmod(a, b) devolve o resultado da divisão inteira e o resto, juntos. Com 17 ovos e caixas de 5:
caixas, sobram = divmod(17, 5)
print("Caixas cheias:", caixas)
print("Ovos que sobram:", sobram)
$ python3 d_divmod.py Caixas cheias: 3 Ovos que sobram: 2
Quando você aprender a criar suas próprias funções, vai ver que return a, b faz a mesma coisa: devolve uma tupla (aula return).
7. O asterisco do outro lado: espalhar no print
O * também funciona ao contrário: na hora de chamar uma função, *dias espalha os itens como se você tivesse escrito cada um separado por vírgula.
dias = ("seg", "ter", "qua")
print(dias)
print(*dias)
print(*dias, sep=" - ")
$ python3 d_print.py
('seg', 'ter', 'qua')
seg ter qua
seg - ter - qua
print(*dias) é o mesmo que print("seg", "ter", "qua"): três valores separados, que o print mostra com espaço entre eles (ou com o sep que você escolher, como na aula As Opções sep e end).
Formas diferentes de fazer a mesma coisa
| Objetivo | Sem desempacotar | Desempacotando |
|---|---|---|
| Pegar as partes de uma data | dia = data[0]mes = data[1]ano = data[2] | dia, mes, ano = data |
| Trocar duas variáveis | guarda = aa = bb = guarda | a, b = b, a |
| Primeiro item e o resto | primeira = notas[0]resto = list(notas[1:]) | primeira, *resto = notas |
| Percorrer uma lista de pares | for aluno in turma: print(aluno[0], aluno[1]) | for nome, nota in turma: print(nome, nota) |
Qual usar? Desempacotar quando você sabe quantos valores vêm e quer todos com nome: o código fica mais curto e mais claro. Use índice (data[0]) quando precisa de um item só, numa tupla grande.
Quando dá errado
too many values to unpack
dia, mes = (12, 3, 1990)
$ python3 d_muitos.py
Traceback (most recent call last):
File "/home/ana/d_muitos.py", line 1, in <module>
dia, mes = (12, 3, 1990)
^^^^^^^^
ValueError: too many values to unpack (expected 2, got 3)
- File "/home/ana/d_muitos.py", line 1
- O erro está na linha 1.
- ^^^^^^^^
- Os acentos circunflexos marcam
dia, mes: o lado esquerdo, onde estão os "lugares". - ValueError
- "Erro de valor": o tipo está certo (é uma tupla), mas ela não serve do jeito que veio.
- too many values to unpack
- "Valores demais para desempacotar". Vieram mais coisas do que lugares.
- (expected 2, got 3)
- "Esperava 2, recebeu 3": duas variáveis, três valores. O 1990 ficou sem lugar.
Como consertar: uma variável para cada valor (dia, mes, ano = …), ou recolha o que sobra: dia, mes, *_ = ….
O "got 3" (quantos valores vieram) é novidade do Python 3.14. No Python 3.13, que vem no Debian 13, a mesma linha mostra só ValueError: too many values to unpack (expected 2). O erro é o mesmo; a mensagem é que ficou mais completa.
not enough values to unpack
dia, mes, ano = (12, 3)
$ python3 d_poucos.py
Traceback (most recent call last):
File "/home/ana/d_poucos.py", line 1, in <module>
dia, mes, ano = (12, 3)
^^^^^^^^^^^^^
ValueError: not enough values to unpack (expected 3, got 2)
"Valores insuficientes para desempacotar (esperava 3, recebeu 2)". Três lugares, duas coisas: o ano ficaria vazio. Como consertar: confira de onde vem a tupla; se o número de valores pode variar, use o asterisco: dia, *resto = ….
notas = (8, 10, 6, 10, 9) *a, *b = notas
$ python3 d_duas_estrelas.py
File "/home/ana/d_duas_estrelas.py", line 2
*a, *b = notas
^^^^^^
SyntaxError: multiple starred expressions in assignment
"Várias expressões com asterisco na atribuição". Com dois asteriscos, o Python não teria como decidir quantos valores vão para cada um. Repare que não aparece Traceback: um SyntaxError (erro de escrita) é encontrado antes de o programa começar a rodar. Como consertar: só um asterisco por desempacotamento.
*todos = [1, 2, 3]
$ python3 d_estrela_so.py
File "/home/ana/d_estrela_so.py", line 1
*todos = [1, 2, 3]
^^^^^^
SyntaxError: starred assignment target must be in a list or tuple
"O alvo com asterisco precisa estar numa lista ou tupla". O asterisco quer dizer "o resto", e só existe resto se houver mais alguém. Como consertar: se você quer todos os itens numa lista, não precisa de asterisco: todos = list([1, 2, 3]). (Funcionaria *todos, = [1, 2, 3], com uma vírgula, mas ninguém escreve assim.)
total = 30 a, b = total
$ python3 d_int.py
Traceback (most recent call last):
File "/home/ana/d_int.py", line 2, in <module>
a, b = total
^^^^
TypeError: cannot unpack non-iterable int object
"Não é possível desempacotar um objeto int, que não é iterável". Iterável é tudo o que tem itens para percorrer (tupla, lista, texto). Um número é um valor só; não há o que tirar da "mala". Como consertar: confira se a variável à direita é mesmo a tupla que você imagina (print(type(total))).
Missão: a fila da padaria tem quatro pessoas, e o programa dá ValueError: too many values to unpack. Conserte a linha 2 para que primeira fique com a Ana e esperando com a lista dos outros três.
fila = ["Ana", "Bia", "Caio", "Davi"]
primeira, esperando = fila
print("Primeira:", primeira)
print("Esperando:", esperando)
fila = ["Ana", "Bia", "Caio", "Davi"]
primeira, *esperando = fila
print("Primeira:", primeira)
print("Esperando:", esperando)
Referência rápida
| Escrita | O que faz |
|---|---|
a, b = (1, 2) | Desempacota: a = 1, b = 2 |
a, b = 1, 2 | O mesmo, com a tupla sem parênteses |
a, b = b, a | Troca os valores de a e b |
primeiro, *resto = seq | Primeiro item e o resto numa lista |
*inicio, ultimo = seq | Último item e o que vem antes numa lista |
nome, _, cidade = registro | _ marca o valor que você vai ignorar |
for nome, nota in turma: | Desempacota cada tupla da lista, a cada volta |
print(*seq) | Espalha os itens como valores separados na chamada |
| Mensagem | Causa provável |
|---|---|
ValueError: too many values to unpack (expected 2, got 3) | Mais valores do que variáveis |
ValueError: not enough values to unpack (expected 3, got 2) | Menos valores do que variáveis |
SyntaxError: multiple starred expressions in assignment | Mais de um * no lado esquerdo |
SyntaxError: starred assignment target must be in a list or tuple | Um *nome sozinho à esquerda do = |
TypeError: cannot unpack non-iterable int object | Tentou desempacotar um valor só (um número) |
Exercícios
1. A coordenada
Complete para tirar os dois valores de padaria = (-5.0892, -42.8019):
2. A troca
Complete a troca de x e y:
3. O resto
Complete o símbolo para que outros recolha todos os itens depois do primeiro:
4. Depois de a, *b = (1, 2, 3), o que vale b?
5. nome, idade = ("Ana", 34, "Teresina") dá qual erro?
6. Por que a = b seguido de b = a não troca os valores?
Missão final: a conta da padaria
Missão: cada compra é uma tupla com o nome, o preço e a quantidade. Mude o for para desempacotar cada tupla em nome, preco, quantidade e mostre, para cada uma, uma linha como pão: R$ 5.00 (o preço vezes a quantidade, com duas casas: {preco * quantidade:.2f}).
compras = [("pão", 0.50, 10), ("leite", 4.75, 2), ("café", 18.90, 1)]
for item in compras:
print(item)
compras = [("pão", 0.50, 10), ("leite", 4.75, 2), ("café", 18.90, 1)]
for nome, preco, quantidade in compras:
print(f"{nome}: R$ {preco * quantidade:.2f}")
No lab, a solução mostra pão: R$ 5.00, leite: R$ 9.50 e café: R$ 18.90.
Resumo
- Desempacotar é tirar os valores de uma sequência para várias variáveis de uma vez:
dia, mes, ano = data. - Funciona com tupla, lista, texto, e com a tupla sem parênteses
1, 2. a, b = b, atroca dois valores: o lado direito é calculado inteiro antes.- O
*nomerecolhe "o resto" numa lista (pode ficar vazia). Só um asterisco por vez. _é o nome costumeiro para um valor que você vai ignorar.for nome, nota in turma:desempacota cada tupla da lista.- Variáveis e valores precisam bater: senão,
too many values to unpackounot enough values to unpack, com(expected X, got Y).