Python Atribuição Múltipla
Até aqui, cada variável ganhou a sua linha: paes = 12, depois leite = 2, depois ovos = 30. O Python permite fazer isso tudo numa linha só, e ainda tem um truque famoso: trocar o valor de duas variáveis sem precisar de uma terceira. Isso se chama atribuição múltipla: atribuir (guardar) vários valores de uma vez.
- A criar várias variáveis numa linha:
paes, leite, ovos = 12, 2, 30. - A dar o mesmo valor a várias variáveis:
vendidos = perdidos = 0. - A trocar dois valores com
a, b = b, a, e por que o jeito "óbvio" não funciona. - Que o lado direito é calculado inteiro antes de qualquer variável mudar.
- Os erros reais quando o número de nomes e de valores não bate.
Os programas desta aula foram rodados com o Python 3.14 na máquina fictícia da Ana (usuária ana, computador notebook), com python3 arquivo.py.
A ideia: distribuir as etiquetas de uma vez
A Ana chega da feira com três sacolas e três etiquetas na mão: "pães", "leite", "ovos". Em vez de pôr uma sacola na mesa, colar a etiqueta, voltar, pegar a outra… ela enfileira as sacolas, enfileira as etiquetas na mesma ordem e cola tudo de uma vez: a primeira etiqueta na primeira sacola, a segunda na segunda, a terceira na terceira.
Na atribuição múltipla, os nomes ficam à esquerda do = e os valores à direita, separados por vírgula, e o Python faz a correspondência pela posição. Para dar certo, as duas filas precisam ter o mesmo tamanho: três etiquetas, três sacolas.
1. Várias variáveis numa linha
nome, idade, cidade = "Ana", 29, "Teresina" print(nome) print(idade) print(cidade)
$ python3 am-varias.py Ana 29 Teresina
- nome, idade, cidade
- Os nomes das variáveis, separados por vírgula: a fila de etiquetas.
- =
- "Recebem", como sempre.
- "Ana", 29, "Teresina"
- Os valores, também separados por vírgula: a fila de sacolas. Podem ser de tipos diferentes, texto e número misturados.
- a correspondência
- O 1º nome recebe o 1º valor, o 2º recebe o 2º, o 3º recebe o 3º:
nomefica com"Ana",idadecom29,cidadecom"Teresina".
O resultado é exatamente o mesmo que escrever três linhas:
nome = "Ana" idade = 29 cidade = "Teresina"
Outro exemplo, com as compras da Ana:
paes, leite, ovos = 12, 2, 30
print("Pães:", paes, "| Leite:", leite, "| Ovos:", ovos)
$ python3 am-compras.py Pães: 12 | Leite: 2 | Ovos: 30
Use a forma de uma linha para valores que andam juntos (um par de coordenadas, o nome e a idade de uma pessoa, as quantidades de uma compra). Para valores sem relação, ou para mais de três ou quatro nomes, linhas separadas são mais fáceis de ler: fica difícil contar qual valor vai para qual nome.
Missão: junte as três primeiras linhas numa linha só, com atribuição múltipla, na ordem bolo, torta, sonho. A saída deve continuar igual.
bolo = 3
torta = 2
sonho = 10
print("Bolos:", bolo, "| Tortas:", torta, "| Sonhos:", sonho)
bolo, torta, sonho = 3, 2, 10
print("Bolos:", bolo, "| Tortas:", torta, "| Sonhos:", sonho)
2. O mesmo valor para várias variáveis
Quando várias variáveis começam com o mesmo valor, dá para encadear os =:
vendidos = devolvidos = perdidos = 0 print(vendidos, devolvidos, perdidos) vendidos = 5 print(vendidos, devolvidos, perdidos)
$ python3 am-mesmo.py 0 0 0 5 0 0
A primeira linha prende as três etiquetas ao mesmo valor, 0. Depois, vendidos = 5 muda só a etiqueta vendidos de lugar; as outras duas continuam no 0, como você viu na cópia de variáveis em Variáveis.
As três etiquetas ficam presas ao mesmo valor, e não a três cópias. Com números e textos isso nunca dá problema. Com listas, que podem ser alteradas por dentro, dá: a = b = [] cria uma lista só com dois nomes. A história completa está em Mutável × Imutável.
3. Trocando dois valores
Na padaria, a Carla trabalha de manhã e o Bruno à tarde. Nesta semana eles vão trocar de turno. Parece fácil:
manha = "Carla"
tarde = "Bruno"
manha = tarde
tarde = manha
print("Manhã:", manha)
print("Tarde:", tarde)
$ python3 am-troca-errada.py Manhã: Bruno Tarde: Bruno
O Bruno ficou nos dois turnos, e a Carla sumiu. Siga as linhas:
manha = tarde:manhapassa a ser"Bruno". Nesse momento, nenhuma variável guarda mais a"Carla".tarde = manha:tarderecebe o valor atual demanha, que já é"Bruno".
O jeito tradicional (que funciona em qualquer linguagem) é guardar um dos valores numa variável auxiliar antes, como quem põe um copo na mesa para destrocar dois copos de lugar:
manha = "Carla"
tarde = "Bruno"
guarda = manha
manha = tarde
tarde = guarda
print("Manhã:", manha)
print("Tarde:", tarde)
$ python3 am-troca-aux.py Manhã: Bruno Tarde: Carla
No Python, a atribuição múltipla faz isso numa linha, sem variável auxiliar:
manha = "Carla"
tarde = "Bruno"
manha, tarde = tarde, manha
print("Manhã:", manha)
print("Tarde:", tarde)
$ python3 am-troca.py Manhã: Bruno Tarde: Carla
- tarde, manha
- O lado direito é calculado primeiro e inteiro: o Python pega os valores atuais,
"Bruno"e"Carla", e os guarda de lado, nessa ordem. - manha, tarde =
- Só depois ele cola as etiquetas:
manhano primeiro valor guardado ("Bruno"),tardeno segundo ("Carla"). Como os valores já estavam guardados, nenhum se perde.
Missão: o programa troca os turnos do jeito errado e a Carla some. Troque as duas linhas do meio por uma linha com manha, tarde = tarde, manha.
manha = "Carla"
tarde = "Bruno"
manha = tarde
tarde = manha
print("Manhã:", manha)
print("Tarde:", tarde)
manha = "Carla"
tarde = "Bruno"
manha, tarde = tarde, manha
print("Manhã:", manha)
print("Tarde:", tarde)
4. O lado direito vem primeiro, sempre
A regra que fez a troca funcionar vale para qualquer atribuição múltipla: todos os valores da direita são calculados com as variáveis como estavam antes da linha. Compare:
a = 1 b = 10 a, b = b, a + b print(a, b)
$ python3 am-direita.py 10 11
a = 1 b = 10 a = b b = a + b print(a, b)
$ python3 am-direita2.py 10 20
No primeiro programa, a + b foi calculado com o a antigo: 1 + 10 = 11. No segundo, em duas linhas, quando a conta a + b foi feita o a já tinha virado 10: 10 + 10 = 20. Uma linha só e duas linhas não são a mesma coisa quando uma variável depende da outra.
Formas diferentes de criar várias variáveis
paes = 12; leite = 2; ovos = 30 print(paes, leite, ovos)
$ python3 am-pontovirgula.py 12 2 30
O ; (ponto e vírgula) permite escrever vários comandos na mesma linha. Funciona, mas a PEP 8, o guia de estilo do Python (aula Estilo de Código), desaconselha: cada comando na sua linha é mais fácil de ler.
| Forma | Quando usar |
|---|---|
| Uma linha para cada variável | O padrão. Sempre que os valores não têm relação entre si, ou são muitos |
nome, idade = "Ana", 29 | Para poucos valores que andam juntos |
x = y = 0 | Para começar vários contadores com o mesmo número ou texto |
a, b = b, a | Para trocar dois valores. É o jeito do Python |
a = 1; b = 2 | Evite: o estilo do Python pede um comando por linha |
Por trás dos panos, o lado direito 12, 2, 30 é um valor só: uma tupla, um pacote de valores em ordem. Veja o que acontece com um nome só do lado esquerdo:
pedido = 12, 2, 30 print(pedido)
$ python3 am-tupla.py (12, 2, 30)
A atribuição múltipla, na verdade, "abre o pacote" e distribui os valores pelos nomes. Esse abrir se chama desempacotamento (unpacking), palavra que vai aparecer nas mensagens de erro abaixo. Tuplas e desempacotamento têm aulas próprias: Tuplas e Desempacotamento.
Quando dá errado
paes, leite = 12, 2, 30
$ python3 am-muitos.py
Traceback (most recent call last):
File "/home/ana/am-muitos.py", line 1, in <module>
paes, leite = 12, 2, 30
^^^^^^^^^^^
ValueError: too many values to unpack (expected 2, got 3)
- ^^^^^^^^^^^
- Aponta o lado esquerdo, a fila de nomes.
- ValueError
- "Erro de valor".
- too many values to unpack
- "Valores demais para desempacotar": sobrou sacola sem etiqueta.
- (expected 2, got 3)
- "(esperava 2, recebeu 3)": dois nomes, três valores.
Nenhuma variável foi criada: o Python confere as quantidades antes de colar qualquer etiqueta. Como consertar: um nome para cada valor, paes, leite, ovos = 12, 2, 30.
O pedaço got 3 ("recebeu 3") é novo 3.14. No Python 3.13, que vem no Debian 13, a mesma linha dá ValueError: too many values to unpack (expected 2), sem dizer quantos valores vieram.
paes, leite, ovos = 12, 2
$ python3 am-poucos.py
Traceback (most recent call last):
File "/home/ana/am-poucos.py", line 1, in <module>
paes, leite, ovos = 12, 2
^^^^^^^^^^^^^^^^^
ValueError: not enough values to unpack (expected 3, got 2)
"Valores insuficientes para desempacotar (esperava 3, recebeu 2)": sobrou etiqueta sem sacola. Como consertar: acrescente o valor que falta, paes, leite, ovos = 12, 2, 30, ou tire o nome que sobra.
paes, leite = 12
$ python3 am-um.py
Traceback (most recent call last):
File "/home/ana/am-um.py", line 1, in <module>
paes, leite = 12
^^^^^^^^^^^
TypeError: cannot unpack non-iterable int object
"Não dá para desempacotar um objeto int não iterável". Um número sozinho não é um pacote: não tem "itens" para distribuir (iterável é tudo o que pode ser percorrido item por item, como você vai ver em for). Se a ideia era dar 12 aos dois, a forma certa é a da seção 2: paes = leite = 12.
a, b, c = "Ana" print(a, b, c)
$ python3 am-texto.py A n a
Surpresa: um texto é um pacote, de letras. O Python desempacotou "Ana" em três letras, uma para cada nome. Se o texto tivesse quatro letras, viria o ValueError de valores demais. Raramente é isso que se quer; quando acontecer sem querer, confira se faltaram as vírgulas do lado direito.
Missão: o programa para com ValueError. Leia a mensagem e conserte a primeira linha (sem mudar o print).
paes, leite = 12, 2, 30
print("Pães:", paes, "| Leite:", leite, "| Ovos:", ovos)
paes, leite, ovos = 12, 2, 30
print("Pães:", paes, "| Leite:", leite, "| Ovos:", ovos)
Referência rápida
| Escrita | O que faz |
|---|---|
a, b, c = 1, 2, 3 | a recebe 1, b recebe 2, c recebe 3 (pela posição) |
x = y = z = 0 | As três variáveis recebem o mesmo valor |
a, b = b, a | Troca os valores de a e b |
a, b = b, a + b | Todo o lado direito é calculado com os valores de antes da linha |
t = 1, 2, 3 | Um nome só: guarda a tupla (1, 2, 3) |
| Mensagem | Causa provável |
|---|---|
ValueError: too many values to unpack (expected 2, got 3) | Mais valores do que nomes |
ValueError: not enough values to unpack (expected 3, got 2) | Menos valores do que nomes |
TypeError: cannot unpack non-iterable int object | Vários nomes e um número só do lado direito |
| Os dois turnos ficaram com o mesmo valor, sem erro | Troca feita em duas linhas (a = b, b = a): use a, b = b, a |
Exercícios
1. Complete a troca
Complete para trocar os valores de x e y:
2. Qual é a saída?
a, b, c = 5, 6, 7 print(b)
3. E esta?
a, b = 2, 5 a, b = b, a * b print(a, b)
4. O que acontece com x, y = 1, 2, 3?
5. Depois de a = 1, b = 2, a = b e b = a, quanto valem a e b?
6. Qual linha dá o valor 0 a entradas e a saidas?
Missão final: o caixa do dia
Missão: o caixa da padaria começa o dia zerado. (1) Troque as duas primeiras linhas por uma, entradas = saidas = 0. (2) A Ana anotou as vendas e as compras invertidas: antes do print, acrescente uma linha que troque os valores de entradas e saidas. Deve aparecer Entradas: 30 | Saídas: 120.
entradas = 0
saidas = 0
entradas = entradas + 120
saidas = saidas + 30
print("Entradas:", entradas, "| Saídas:", saidas)
entradas = saidas = 0
entradas = entradas + 120
saidas = saidas + 30
entradas, saidas = saidas, entradas
print("Entradas:", entradas, "| Saídas:", saidas)
Resumo
a, b, c = 1, 2, 3cria várias variáveis numa linha; os valores são distribuídos pela posição.- O número de nomes e de valores tem de bater; senão,
ValueError(too manyounot enough values to unpack). x = y = 0dá o mesmo valor a várias variáveis.a, b = b, atroca dois valores sem variável auxiliar. Em duas linhas (a = b,b = a), um dos valores se perde.- O lado direito é calculado inteiro antes de qualquer variável mudar.
- Use a forma de uma linha para poucos valores que andam juntos; no resto, uma variável por linha.