Python enumerate() e zip()

O for percorre uma lista item por item. Mas duas perguntas aparecem logo: "em que posição está este item?" (para numerar uma lista de compras) e "como andar em duas listas ao mesmo tempo?" (os nomes dos alunos numa lista, as notas em outra). Para a primeira, existe a função embutida enumerate(); para a segunda, a zip(). As duas deixam o for mais curto e mais claro, e evitam um dos jeitos mais desajeitados de escrever um laço: o range(len(lista)).

Você vai aprender
  • A numerar os itens de um for com enumerate(), começando do 0 ou do 1 (start=1).
  • A percorrer duas ou três listas lado a lado com zip().
  • O que o zip() faz quando as listas têm tamanhos diferentes, e como a opção strict=True transforma isso num erro.
  • A montar um dicionário com dict(zip(…)).
  • A usar os dois juntos para fazer um ranking.
  • Os erros reais: ValueError: too many values to unpack e ValueError: zip() argument 2 is shorter than argument 1.

A ideia: a senha da fila e o zíper

Na padaria do bairro, cada pessoa que chega pega uma senha: 1, 2, 3… A pessoa continua sendo a mesma, mas agora vem acompanhada de um número. É o que o enumerate() faz: entrega cada item da lista junto com o número da posição dele. O nome vem do inglês enumerate, "enumerar", "numerar um por um".

Agora pense num zíper de casaco. Ele tem dois lados com dentes, e ao fechar, cada dente de um lado se encaixa no dente correspondente do outro: o primeiro com o primeiro, o segundo com o segundo. A função zip() (é esse o nome, "zíper" em inglês) faz isso com listas: junta o primeiro item de uma com o primeiro da outra, o segundo com o segundo, e assim por diante.


1. enumerate(): o item e a sua posição

fila = ["Ana", "Bruno", "Clara"]

for posicao, nome in enumerate(fila):
    print(posicao, nome)
$ python3 fila.py
0 Ana
1 Bruno
2 Clara
enumerate(fila)
Em cada volta do laço, entrega dois valores: a posição e o item.
for posicao, nome in …
Duas variáveis no for, separadas por vírgula: a primeira recebe a posição; a segunda, o item. É o desempacotamento que você viu na aula Desempacotamento.
0, 1, 2
A contagem começa do zero, igual aos índices da lista (aula Acessando Itens): fila[0] é "Ana".

O que o enumerate() entrega, por dentro

No modo interativo, dá para espiar. O enumerate() sozinho não mostra os pares; para vê-los, transforme em lista com list():

$ python3
Python 3.14.4 (main, Aug 20 2026, 10:41:58) [GCC 15.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> fila = ["Ana", "Bruno", "Clara"]
>>> enumerate(fila)
<enumerate object at 0x7fb1290e75b0>
>>> list(enumerate(fila))
[(0, 'Ana'), (1, 'Bruno'), (2, 'Clara')]

<enumerate object at 0x7fb1290e75b0> quer dizer "um objeto enumerate, guardado no endereço tal da memória". (Esse número muda a cada execução; não se preocupe com ele.) O enumerate() não monta uma lista: ele vai entregando os pares um de cada vez, conforme o for pede. Com list(), você vê todos: são tuplas (aula Tuplas), cada uma com a posição e o item.

Começando do 1: start=1

Para as pessoas, listas começam do 1. Ninguém escreve "item 0: arroz" numa lista de compras. A opção start ("começo") diz de qual número a contagem parte:

compras = ["arroz", "feijão", "café", "leite"]

print("Lista de compras:")
for numero, item in enumerate(compras, start=1):
    print(f"{numero}. {item}")
$ python3 compras.py
Lista de compras:
1. arroz
2. feijão
3. café
4. leite
>>> list(enumerate(fila, start=1))
[(1, 'Ana'), (2, 'Bruno'), (3, 'Clara')]

O start=1 muda só o número que aparece. A lista continua a mesma: compras[0] ainda é "arroz".

Missão: a lista da Ana está saindo numerada a partir do 0. Faça a numeração começar do 1, mudando só a chamada do enumerate().

compras = ["arroz", "feijão", "café", "leite"]

for numero, item in enumerate(compras):
    print(f"{numero}. {item}")
compras = ["arroz", "feijão", "café", "leite"]

for numero, item in enumerate(compras, start=1):
    print(f"{numero}. {item}")

Sem o enumerate(): os jeitos antigos

Antes de conhecer o enumerate(), muita gente numera de um destes dois jeitos:

compras = ["arroz", "feijão", "café", "leite"]

numero = 1
for item in compras:
    print(f"{numero}. {item}")
    numero = numero + 1

for i in range(len(compras)):
    print(f"{i + 1}. {compras[i]}")
$ python3 contador_manual.py
1. arroz
2. feijão
3. café
4. leite
1. arroz
2. feijão
3. café
4. leite

Os dois funcionam, mas cada um tem um ponto fraco. No primeiro, você cuida do contador à mão: se esquecer o numero = numero + 1 (ou colocá-lo fora do laço), todos os itens saem com o número 1. No segundo, o range(len(compras)) percorre os números, e o item só aparece por compras[i], com colchetes e mais uma chance de errar o índice. O enumerate() entrega as duas coisas prontas.


2. zip(): duas listas lado a lado

A professora guardou os nomes dos alunos numa lista e as notas em outra, na mesma ordem: a primeira nota é da Ana, a segunda é do Bruno, a terceira é da Clara.

alunos = ["Ana", "Bruno", "Clara"]
notas = [9.0, 6.5, 8.0]

for aluno, nota in zip(alunos, notas):
    situacao = "aprovado" if nota >= 7 else "recuperação"
    print(f"{aluno}: {nota} ({situacao})")
$ python3 boletim_zip.py
Ana: 9.0 (aprovado)
Bruno: 6.5 (recuperação)
Clara: 8.0 (aprovado)
zip(alunos, notas)
Fecha o zíper: junta o 1º aluno com a 1ª nota, o 2º com a 2ª, o 3º com a 3ª.
for aluno, nota in …
Em cada volta, um par: aluno recebe o item da primeira lista; nota, o da segunda. A ordem das variáveis é a ordem das listas no zip().
"aprovado" if nota >= 7 else "recuperação"
Um if numa linha só (aula if em uma Linha), só para enfeitar o boletim.

Por dentro, também são tuplas:

>>> alunos = ["Ana", "Bruno", "Clara"]
>>> notas = [9.0, 6.5, 8.0]
>>> list(zip(alunos, notas))
[('Ana', 9.0), ('Bruno', 6.5), ('Clara', 8.0)]

Missão: o programa mostra só os nomes. Use zip() para mostrar cada aluno com a sua nota, no formato Ana: 9.0.

alunos = ["Ana", "Bruno", "Clara"]
notas = [9.0, 6.5, 8.0]

for aluno in alunos:
    print(aluno)
alunos = ["Ana", "Bruno", "Clara"]
notas = [9.0, 6.5, 8.0]

for aluno, nota in zip(alunos, notas):
    print(f"{aluno}: {nota}")

Três listas (ou mais)

O zip() aceita quantas listas você quiser. A cada volta, vem um item de cada uma:

produtos = ["arroz", "café", "sal"]
precos = [25.9, 18.5, 3.2]
quantidades = [2, 1, 3]

total = 0
for produto, preco, quantidade in zip(produtos, precos, quantidades):
    subtotal = preco * quantidade
    total = total + subtotal
    print(f"{quantidade} x {produto}: R$ {subtotal:.2f}")
print(f"Total: R$ {total:.2f}")
$ python3 tres_listas.py
2 x arroz: R$ 51.80
1 x café: R$ 18.50
3 x sal: R$ 9.60
Total: R$ 79.90

Montando um dicionário: dict(zip(…))

Uma lista de chaves e uma lista de valores, juntas pelo zip(), viram um dicionário (aula Dicionários):

>>> dict(zip(alunos, notas))
{'Ana': 9.0, 'Bruno': 6.5, 'Clara': 8.0}

3. Listas de tamanhos diferentes

Chegou um aluno novo, o Davi, e a professora pôs o nome dele na lista. Mas ainda não lançou a nota:

alunos = ["Ana", "Bruno", "Clara", "Davi"]
notas = [9.0, 6.5, 8.0]

for aluno, nota in zip(alunos, notas):
    print(aluno, nota)
print("Fim")
$ python3 tamanhos.py
Ana 9.0
Bruno 6.5
Clara 8.0
Fim

O Davi sumiu, e sem aviso nenhum. O zip() para assim que a lista mais curta acaba: depois da Clara, não há mais nota para encaixar, então o zíper termina ali. Isso pode ser exatamente o que você quer… ou pode esconder um erro de verdade, como uma nota que alguém esqueceu de lançar.

strict=True: exigir o mesmo tamanho

Quando as listas têm de ter o mesmo tamanho, diga isso ao zip() com a opção strict=True ("estrito", "rigoroso"). Aí, em vez de cortar calado, ele dá erro:

alunos = ["Ana", "Bruno", "Clara", "Davi"]
notas = [9.0, 6.5, 8.0]

for aluno, nota in zip(alunos, notas, strict=True):
    print(aluno, nota)
print("Fim")
$ python3 estrito.py
Ana 9.0
Bruno 6.5
Clara 8.0
Traceback (most recent call last):
  File "/home/ana/estrito.py", line 4, in <module>
    for aluno, nota in zip(alunos, notas, strict=True):
                       ~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: zip() argument 2 is shorter than argument 1
Ana 9.0 … Clara 8.0
As três primeiras voltas aconteceram normalmente. O zip() só descobre que faltou uma nota quando tenta montar o quarto par.
line 4, in <module>
O erro aconteceu na linha do for, a do zip(); as marcas ~~~^^^ apontam para ele.
ValueError: zip() argument 2 is shorter than argument 1
"Erro de valor: o argumento 2 do zip() é mais curto que o argumento 1." O argumento 1 é alunos (4 itens); o 2 é notas (3 itens). Se fosse o contrário, a mensagem diria is longer than, "é mais longo que".
Fim (não apareceu)
O programa parou no erro. Melhor assim: um boletim sem a nota do Davi não pode passar despercebido.
Quando usar strict=True

Sempre que as listas representam a mesma coisa (o nome e a nota do mesmo aluno, o produto e o preço do mesmo produto), use strict=True. Se um dia uma lista ficar maior que a outra, você descobre na hora, em vez de receber um resultado errado em silêncio.


4. Os dois juntos: o ranking

As notas já estão em ordem, da maior para a menor. Para mostrar o ranking, você precisa do lugar (enumerate) e do par aluno-nota (zip):

alunos = ["Clara", "Ana", "Bruno"]
notas = [9.5, 8.0, 7.0]

for lugar, (aluno, nota) in enumerate(zip(alunos, notas), start=1):
    print(f"{lugar}º lugar: {aluno} com {nota}")
$ python3 ranking.py
1º lugar: Clara com 9.5
2º lugar: Ana com 8.0
3º lugar: Bruno com 7.0
zip(alunos, notas)
Primeiro, os pares: ('Clara', 9.5), ('Ana', 8.0), ('Bruno', 7.0).
enumerate(…, start=1)
Depois, cada par ganha um número: (1, ('Clara', 9.5))…
lugar, (aluno, nota)
O desempacotamento acompanha o formato: o número vai para lugar, e o par, entre parênteses, se abre em aluno e nota. Sem os parênteses (for lugar, aluno, nota in …), o Python tentaria distribuir os 2 valores de cada volta (o número e o par) em 3 variáveis, e pararia com ValueError: not enough values to unpack (expected 3, got 2): "valores de menos para desempacotar (esperava 3, recebeu 2)".

Formas diferentes de fazer a mesma coisa

Mostrar cada aluno com a sua nota, de três jeitos:

for i in range(len(alunos)):
    print(alunos[i], notas[i])
for i, aluno in enumerate(alunos):
    print(aluno, notas[i])
for aluno, nota in zip(alunos, notas, strict=True):
    print(aluno, nota)
FormaQuando usar
zip(alunos, notas, strict=True)Para andar em duas listas juntas. É a mais clara: sem índice, sem colchetes, e avisa se os tamanhos não baterem
enumerate(lista)Quando você precisa do número da posição: para numerar, ou para mudar o item com lista[i] = …
range(len(lista))Evite. Funciona, mas é mais longo e mais fácil de errar. Se a outra lista for mais curta, dá IndexError no meio do laço

Quando dá errado

Duas variáveis no for, mas sem o enumerate()

A Ana queria numerar a lista, escreveu as duas variáveis no for… e esqueceu o enumerate():

compras = ["arroz", "feijão", "café"]

for numero, item in compras:
    print(numero, item)
$ python3 sem_enumerate.py
Traceback (most recent call last):
  File "/home/ana/sem_enumerate.py", line 3, in <module>
    for numero, item in compras:
        ^^^^^^^^^^^^
ValueError: too many values to unpack (expected 2)
line 3
O erro está na linha do for.
^^^^^^^^^^^^
As marcas apontam para numero, item: o problema está em distribuir o valor nas duas variáveis.
ValueError: too many values to unpack (expected 2)
"Valores demais para desempacotar (esperava 2)." Sem o enumerate(), cada volta entrega um item só: o texto "arroz". O Python tenta abrir esse texto em duas variáveis, como faria com uma tupla, e encontra cinco letras para duas variáveis.

Como consertar: for numero, item in enumerate(compras, start=1):.

Usar o mesmo zip duas vezes

Assim como o enumerate(), o zip() entrega os pares um de cada vez, e só uma vez. Se você guarda o resultado numa variável e percorre duas vezes, a segunda vem vazia, sem erro:

>>> pares = zip(alunos, notas)
>>> list(pares)
[('Ana', 9.0), ('Bruno', 6.5), ('Clara', 8.0)]
>>> list(pares)
[]

O zíper já foi fechado até o fim; não há mais nada para entregar. Como consertar: chame o zip() de novo, direto no for (for aluno, nota in zip(alunos, notas):), ou guarde uma lista com pares = list(zip(alunos, notas)), que pode ser percorrida quantas vezes você quiser. A aula Iteradores explica por que isso acontece.

Missão: rode e veja o ValueError: falta a nota do Davi. Ele tirou 7.5. Acrescente a nota que falta (mantenha o strict=True).

alunos = ["Ana", "Bruno", "Clara", "Davi"]
notas = [9.0, 6.5, 8.0]

for aluno, nota in zip(alunos, notas, strict=True):
    print(aluno, nota)
alunos = ["Ana", "Bruno", "Clara", "Davi"]
notas = [9.0, 6.5, 8.0, 7.5]

for aluno, nota in zip(alunos, notas, strict=True):
    print(aluno, nota)

Referência rápida

EscritaO que entrega
enumerate(lista)Pares (posição, item), começando do 0
enumerate(lista, start=1)Pares (número, item), começando do 1
for i, item in enumerate(lista):Percorre com o número e o item
zip(a, b)Pares (item de a, item de b), até a lista mais curta acabar
zip(a, b, c)Trios, um item de cada lista
zip(a, b, strict=True)Igual, mas dá ValueError se os tamanhos forem diferentes
dict(zip(chaves, valores))Um dicionário
list(enumerate(…)), list(zip(…))Uma lista com todas as tuplas (para ver, ou para usar mais de uma vez)
for n, (a, b) in enumerate(zip(x, y), start=1):Os dois juntos
SintomaCausa provável
ValueError: too many values to unpack (expected 2) num forDuas variáveis no for, mas faltou o enumerate() ou o zip()
ValueError: zip() argument 2 is shorter than argument 1strict=True e a segunda lista tem menos itens (com is longer than, mais itens)
Itens somem no fim, sem erroListas de tamanhos diferentes num zip() sem strict=True
A segunda volta num zip guardado não mostra nadaO zip (e o enumerate) só pode ser percorrido uma vez
<enumerate object at 0x…> ou <zip object at 0x…>Você mostrou o objeto, não os pares: use list(…) ou um for

Exercícios

1. Numerando a partir do 1

Complete para a numeração começar do 1:

for numero, item in enumerate(compras, ):

2. O zíper

Complete para percorrer os produtos e os preços juntos:

for produto, preco in (produtos, precos):

3. alunos tem 4 nomes e notas tem 3 notas. Quantas voltas dá o for aluno, nota in zip(alunos, notas):?

4. O que list(enumerate(["a", "b"])) devolve?

5. Para que serve o strict=True no zip()?

Missão final: o pódio

Missão: mostre o pódio da gincana, no formato 1º lugar: Clara (95 pontos), usando enumerate() e zip() juntos, com a contagem começando do 1.

nomes = ["Clara", "Ana", "Bruno"]
pontos = [95, 80, 70]

# escreva o for aqui
nomes = ["Clara", "Ana", "Bruno"]
pontos = [95, 80, 70]

for lugar, (nome, ponto) in enumerate(zip(nomes, pontos), start=1):
    print(f"{lugar}º lugar: {nome} ({ponto} pontos)")

Resumo

  • enumerate(lista) entrega cada item junto com a sua posição: for i, item in enumerate(lista):. Começa do 0; com start=1, do 1.
  • zip(a, b) anda em duas (ou mais) listas ao mesmo tempo, item com item, como um zíper.
  • Com tamanhos diferentes, o zip() para na lista mais curta, sem avisar. Com strict=True, dá ValueError: zip() argument 2 is shorter than argument 1.
  • dict(zip(chaves, valores)) monta um dicionário.
  • Juntos: for n, (a, b) in enumerate(zip(x, y), start=1):.
  • enumerate e zip entregam os pares um de cada vez, e só uma vez. Para ver todos ou reaproveitar, use list(…).
  • Prefira os dois ao range(len(lista)): menos colchetes, menos chances de errar.