Como Construir um Iterator Básico em Python

Em Python, iteradores são ferramentas poderosas que permitem percorrer uma coleção de valores sem precisar trabalhar diretamente com a estrutura de dados subjacente. Seja lidando com listas, conjuntos ou até mesmo objetos personalizados, entender como criar seu próprio iterador pode ser muito benéfico.

Neste post do blog, discutiremos como construir um iterador básico usando uma classe de exemplo chamada Example, e depois exploraremos uma implementação mais direta utilizando um gerador.

O que é um Iterador?

Um iterador é um objeto que se conforma ao protocolo do iterador. Isso significa que ele deve fornecer dois métodos essenciais:

  1. __iter__(): Este método retorna o próprio objeto iterador.
  2. __next__(): Este método retorna o próximo valor da coleção. Quando não há mais itens a serem retornados, ele gera uma exceção StopIteration.

Esses métodos facilitam a iteração sobre os elementos em um loop.

Criando um Iterador Básico

Vamos detalhar como criar um iterador passo a passo.

Passo 1: Definir a Classe

Começaremos definindo uma classe chamada Example. Esta classe receberá uma lista de valores e os exporá através do iterador.

class Example:
    def __init__(self, values):
        self.values = values

Passo 2: Implementar os Métodos do Iterador

Agora, implementaremos os métodos __iter__ e __next__ na classe Example.

class Example:
    def __init__(self, values):
        self.values = values

    def __iter__(self):
        self.index = 0  # Inicializar o índice
        return self

    def __next__(self):
        if self.index < len(self.values):
            result = self.values[self.index]
            self.index += 1  # Mover para o próximo índice
            return result
        else:
            raise StopIteration  # Não há mais valores a retornar

Passo 3: Usar o Iterador

Agora você pode criar uma instância de Example e iterar através de seus valores assim:

e = Example([1, 2, 3])
for value in e:
    print("O objeto de exemplo contém", value)

Este código produzirá a saída:

O objeto de exemplo contém 1
O objeto de exemplo contém 2
O objeto de exemplo contém 3

Construindo um Iterador Contador

Para ilustrar ainda mais o conceito, vamos construir um iterador Counter simples que conta de um número baixo para um número alto.

Classe Counter

Aqui está como você pode construir o iterador Counter:

class Counter:
    def __init__(self, low, high):
        self.current = low - 1
        self.high = high

    def __iter__(self):
        return self

    def __next__(self):
        self.current += 1
        if self.current < self.high:
            return self.current
        raise StopIteration

Usando o Counter

Você pode usar a classe Counter assim:

for c in Counter(3, 9):
    print(c)

Isso imprimirá:

3
4
5
6
7
8

Uma Abordagem Alternativa: Usando Geradores

Embora as classes de iteradores acima sejam úteis, implementar um gerador pode ser ainda mais simples. Geradores gerenciam automaticamente o estado e o protocolo de iteração para você.

Aqui está como você pode criar um contador como um gerador:

def counter(low, high):
    current = low
    while current < high:
        yield current
        current += 1

for c in counter(3, 9):
    print(c)

A saída permanece a mesma, mas a abordagem do gerador torna seu código mais limpo e mais fácil de manter.

Conclusão

Criar iteradores em Python permite que você defina seu próprio comportamento de looping e manipule como os objetos expõem seus valores. Ao implementar os métodos __iter__() e __next__(), você pode fornecer uma experiência de iteração personalizada. Além disso, usar geradores simplifica o processo, economizando tempo e reduzindo a complexidade.

Para leituras adicionais sobre este tópico, considere conferir o artigo de David Mertz sobre Iteradores e Geradores Simples.

Agora que você tem uma compreensão básica de como criar iteradores em Python, pode começar a aplicar esses conceitos em seus próprios projetos!