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.

Você vai aprender
  • 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º: nome fica com "Ana", idade com 29, cidade com "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
Quando vale a pena

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.

Com números e textos, tudo bem; com listas, cuidado

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:

  1. manha = tarde: manha passa a ser "Bruno". Nesse momento, nenhuma variável guarda mais a "Carla".
  2. tarde = manha: tarde recebe o valor atual de manha, 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: manha no primeiro valor guardado ("Bruno"), tarde no 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.

FormaQuando usar
Uma linha para cada variávelO padrão. Sempre que os valores não têm relação entre si, ou são muitos
nome, idade = "Ana", 29Para poucos valores que andam juntos
x = y = 0Para começar vários contadores com o mesmo número ou texto
a, b = b, aPara trocar dois valores. É o jeito do Python
a = 1; b = 2Evite: o estilo do Python pede um comando por linha
A vírgula cria uma tupla

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

Mais valores do que nomes
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.

No Python 3.13, a mensagem é mais curta

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.

Menos valores do que nomes
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.

Um valor só para vários nomes
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.

Um texto para vários nomes: não dá erro
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

EscritaO que faz
a, b, c = 1, 2, 3a recebe 1, b recebe 2, c recebe 3 (pela posição)
x = y = z = 0As três variáveis recebem o mesmo valor
a, b = b, aTroca os valores de a e b
a, b = b, a + bTodo o lado direito é calculado com os valores de antes da linha
t = 1, 2, 3Um nome só: guarda a tupla (1, 2, 3)
MensagemCausa 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 objectVários nomes e um número só do lado direito
Os dois turnos ficaram com o mesmo valor, sem erroTroca 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:

x, y =

2. Qual é a saída?

a, b, c = 5, 6, 7
print(b)
Saída:

3. E esta?

a, b = 2, 5
a, b = b, a * b
print(a, b)
Saída:

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, 3 cria 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 many ou not enough values to unpack).
  • x = y = 0 dá o mesmo valor a várias variáveis.
  • a, b = b, a troca 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.