Iteradores

Python SELF PT
Nível 19 , Lição 4
Disponível

5.1 Iterable e Iterator

Como você já sabe, iteradores são objetos que implementam o protocolo iterador, permitindo obter elementos de uma coleção um de cada vez. Iteradores são amplamente usados em Python para percorrer elementos de sequências como listas, tuplas e strings.

Vamos ver como os iteradores são feitos e como usá-los.

Objeto iterável (Iterable)

Para que um objeto possa ser percorrido com um loop for, ele deve ser iterável – Iterable. Isso significa que nosso objeto deve implementar o método __iter__(), que retorna um objeto iterador.

Objeto iterador (Iterator)

Este é um objeto especial que tem função __next__() para retornar o próximo elemento da sequência. Quando os elementos acabam, o método __next__() lança uma exceção StopIteration como sinal de encerramento da iteração.

O iterador também deve implementar o método __iter__(), que retorna o próprio iterador.

Exemplo usando funções embutidas do Python

Neste exemplo, a lista numbers é um objeto iterável. Nós obtemos um iterador usando a função iter() e usamos a função next() para percorrer os elementos até que a exceção StopIteration seja lançada.


# Objeto iterável
numbers = [1, 2, 3, 4, 5]
            
# Obtemos um iterador do objeto iterável
iterator = iter(numbers)
            
# Usamos o iterador para percorrer os elementos
try:
    while True:
        number = next(iterator)
        print(number)
except StopIteration:
    pass
        

É isso que acontece quando você escreve um código assim:


# Objeto iterável
numbers = [1, 2, 3, 4, 5]
            
for number in numbers:
    print(number)
        

5.2 Essência do iterador

Iterador é um objeto que nos ajuda a percorrer um grupo de elementos um de cada vez. As implementações podem variar bastante. Vamos escrever nossa própria classe, onde vamos implementar todos os requisitos para um iterador.

Passo 1. Primeiro, vamos criar nossa classe

Que tal fazer ela retornar números de start a end sequencialmente?


class MyIterator:
    def __init__(self, start, end):
        self.current = start
        self.end = end
        

Passo 2. Suporte para a função __iter__

Agora precisamos adicionar a função __iter__, que vai retornar um objeto iterador, no qual a função __next()__ será chamada. Vamos retornar uma referência ao próprio objeto – isso é permitido.


class MyIterator:
    def __init__(self, start, end):
        self.current = start
        self.end = end
        
    def __iter__(self):
        return self
        

Passo 3. Suporte para a função __next__

Agora precisamos adicionar ao nosso objeto iterador a função __next__, que vai retornar o próximo elemento da nossa lista. Vamos simplesmente usar a variável current:


def __next__(self):
    current = self.current
    self.current += 1
    return current
        

Passo 4. Parada do iterador

Se o iterador já retornou todos os valores que pretendia, ele deve lançar uma exceção StopIteration. Vamos ajustar um pouco nossa última função:


def __next__(self):
    if self.current >= self.end:
        raise StopIteration
    current = self.current
    self.current += 1
    return current
        

Ótimo. Agora podemos usar nosso iterador. Aqui está um exemplo de todo o nosso código:


class MyIterator:
    def __init__(self, start, end):
        self.current = start
        self.end = end
        
    def __iter__(self):
        return self
        
    def __next__(self):
        if self.current >= self.end:
            raise StopIteration
        current = self.current
        self.current += 1
        return current
        
# Criar uma instância do iterador personalizado
my_iter = MyIterator(1, 5)
        
# Usamos o iterador para percorrer os elementos
for num in my_iter:
    print(num)

5.3 Iterador correto

Por que o iterador do exemplo anterior é ruim? Sim, é um iterador, ele funciona, mas é muito primitivo. Não é possível percorrer a mesma coleção de elementos simultaneamente com diferentes iteradores.

Seria mais correto escrever um código que, no método __iter__, não retorna uma referência para si mesmo, mas sim um objeto separado, que retornaria corretamente todos os elementos.

Exemplo:


class MyIterable:
    def __init__(self, data):
        self.data = data
    
    def __iter__(self):
        return MyIterator(self.data)
    
class MyIterator:
    def __init__(self, data):
        self.data = data
        self.index = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.index >= len(self.data):
            raise StopIteration
        item = self.data[self.index]
        self.index += 1
        return item
    
# Uso
my_iterable = MyIterable([1, 2, 3, 4])
for item in my_iterable:
    print(item)
    

Neste exemplo, temos duas classes — na primeira, passamos a coleção que vamos percorrer com o iterador. E a segunda é o iterador, que retorna os elementos da coleção no método next(). Ele também é bem simples, mas é assim que você deve adicionar iteradores às suas classes.

1
Опрос
Módulos e pacotes,  19 уровень,  4 лекция
недоступен
Módulos e pacotes
Módulos e pacotes
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION