Iteradores
O que são Iteradores em Python?
Imagine que você tem uma caixa de bombons. Você quer comer um bombom de cada vez, sem precisar revirar a caixa inteira. Um iterador é exatamente isso: um "entregador" que te dá um elemento por vez de uma coleção.
Em Python, iteradores são objetos que permitem percorrer elementos um a um, sem precisar acessar todos de uma vez. Eles são fundamentais para loops for, list comprehensions e muito mais.
O Protocolo do Iterador
Para um objeto ser um iterador, ele precisa seguir um "contrato" com dois métodos especiais:
__iter__()- Retorna o próprio iterador (ou um objeto iterador)__next__()- Retorna o próximo elemento da sequência
Quando não há mais elementos, __next__() deve lançar a exceção StopIteration.
Diferença Crucial: Iterável vs Iterador
Essa é a parte que mais confunde iniciantes. Vamos deixar claro:
- Iterável: É qualquer objeto que pode ser percorrido (como listas, strings, dicionários). Ele tem o método
__iter__(). - Iterador: É o objeto que realmente percorre os elementos. Ele tem
__iter__()e__next__().
Pense assim: Um iterável é como uma biblioteca (tem muitos livros), e um iterador é como um bibliotecário que te entrega um livro por vez.
# Exemplo prático
lista = [1, 2, 3] # Isso é um ITERÁVEL
iterador = iter(lista) # Isso é um ITERADOR
print(type(lista)) # <class 'list'> - iterável
print(type(iterador)) # <class 'list_iterator'> - iterador
A Função iter() e next()
Vamos ver como usar essas funções na prática:
# Criando um iterador a partir de uma lista
frutas = ["maçã", "banana", "uva"]
iterador_frutas = iter(frutas)
# Obtendo elementos um por um
print(next(iterador_frutas)) # maçã
print(next(iterador_frutas)) # banana
print(next(iterador_frutas)) # uva
# print(next(iterador_frutas)) # Isso causaria StopIteration!
StopIteration: O Sinal de Fim
Quando o iterador não tem mais elementos, ele levanta a exceção StopIteration. É assim que os loops sabem quando parar.
# Tratando StopIteration
letras = iter("ABC")
try:
while True:
letra = next(letras)
print(f"Letra: {letra}")
except StopIteration:
print("Acabaram as letras!")
# Saída:
# Letra: A
# Letra: B
# Letra: C
# Acabaram as letras!
Exemplos com Listas e Strings
Percorrendo uma lista manualmente
numeros = [10, 20, 30, 40, 50]
it = iter(numeros)
print(next(it)) # 10
print(next(it)) # 20
print(next(it)) # 30
Percorrendo uma string caractere por caractere
palavra = "Python"
it_palavra = iter(palavra)
for i in range(len(palavra)):
print(f"Caractere {i+1}: {next(it_palavra)}")
# Saída:
# Caractere 1: P
# Caractere 2: y
# Caractere 3: t
# Caractere 4: h
# Caractere 5: o
# Caractere 6: n
Criando seu Próprio Iterador
Você pode criar classes que se comportam como iteradores:
class Contador:
def __init__(self, limite):
self.limite = limite
self.atual = 0
def __iter__(self):
return self # O próprio objeto é o iterador
def __next__(self):
if self.atual < self.limite:
valor = self.atual
self.atual += 1
return valor
else:
raise StopIteration
# Usando nosso iterador personalizado
contador = Contador(5)
for numero in contador:
print(numero) # 0, 1, 2, 3, 4
Como o for Funciona por Baixo dos Panos
Quando você escreve for item in lista:, o Python faz isso:
# O que acontece internamente
iterador = iter(lista) # Pega o iterador
while True:
try:
item = next(iterador) # Pega próximo elemento
# executa o bloco do for com 'item'
except StopIteration:
break # Sai do loop quando acaba
Erros Comuns e Dicas
❌ Erro 1: Tentar reutilizar um iterador
lista = [1, 2, 3]
it = iter(lista)
print(list(it)) # [1, 2, 3]
print(list(it)) # [] - vazio! O iterador já se esgotou
❌ Erro 2: Confundir iterável com iterador
lista = [1, 2, 3]
# next(lista) # ERRO! list não é iterador, é iterável
# Correto:
next(iter(lista)) # Funciona!
✅ Dica 1: Use list() para "materializar" um iterador
# Se você precisa ver todos os elementos de um iterador
meu_iter = iter(range(10))
todos = list(meu_iter)
print(todos) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
✅ Dica 2: Iteradores economizam memória
# range(1000000) não cria uma lista com 1 milhão de números
# Ele cria um iterador que gera cada número sob demanda
for i in range(1000000):
if i > 10:
break
print(i)
Resumo Visual
ITERÁVEL (tem __iter__)
|
| iter()
v
ITERADOR (tem __iter__ e __next__)
|
| next()
v
ELEMENTOS (um por vez até StopIteration)
Na Prática: Quando Usar Iteradores
- Arquivos grandes: Processar linha por linha sem carregar tudo na memória
- Sequências infinitas: Gerar números sob demanda
- Pipelines de dados: Processar dados em etapas
- Economia de memória: Quando você não precisa de todos os elementos de uma vez
# Exemplo prático: lendo um arquivo grande
with open("arquivo_grande.txt") as arquivo:
for linha in arquivo: # arquivo já é um iterador!
processar(linha) # Processa uma linha por vez
Lembre-se: iteradores são como um canudo de refrigerante - você só consegue sugar um gole de cada vez, e depois que acaba, não tem mais volta!