Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

Dúvida sobre iteráveis e __iter__

Estou com uma dúvida básica: Não entendi muito bem o conceito de iterável e consequentemente o iter, também. Desde já agradeço!

2 respostas
solução!

Falando menos tecnicamente, iterável é um objeto que pode ser percorrido por loops (pode ser obtido um iterador a partir deles): string, lista, tuplas e etc...

Iterators aparecem constantemente no Python mas escondidos à vista. São implementados de forma elegante em for loops, comprehensions, generators e etc... Nesse ponto pode-se dizer que tais estruturas são implementações do protocolo iterator (PEP 234). Para um objeto ser implementação do protocolo Iterator, deve implementar obrigatóriamente os métodos __iter__() e __next__(). E quando existe esses métodos implementados em uma classe o Python reconhece como Implementação de Iterator automaticamente.

A função iter() chama chama o método __iter__() que retorna um iterator do objeto.

Fiz esse exemplo aqui, não sei se melhora ou piora, sobre implementação de iterator:

class PotenciaDeDois:
    """Classe que implementa um iterator da potencia de base 2 para expoentes de 0 a n.
    """

    def __init__(self, max_exp=0):
        self.max_exp = max_exp

    def __iter__(self):
        """
        Returns:
            PotenciaDeDois: Retorna o iterator
        """
        self.n = 0
        return self

    def __next__(self):
        """Calcula o valor para cada expoente chamado

        Raises:
            StopIteration: Informa quando chega no último expoente

        Returns:
            int: Valor calculado da potencia de dois para o expoente
        """
        if self.n <= self.max_exp:
            result = 2 ** self.n
            self.n += 1
            return result
        else:
            raise StopIteration


expoente_max = 10

for i, valor in enumerate(PotenciaDeDois(expoente_max)):
    print(f'2**{i} = {valor}')

Resultado:

Resultado do código acima

Uma forma menos elegante para obter o mesmo resultado :

expoente_max = 10
numeros = PotenciaDeDois(expoente_max)
iter_numeros = iter(numeros)
contador = 0

while True:
    try:
        # obtem o proximo valor do iterator
        elemento = next(iter_numeros)
        # imprime contador e valor obtido do iterator
        print(f'2**{contador} = {elemento}')
        # incrementa contador
        contador += 1
    except StopIteration:
        # para o loop assim que a Exception gerada pelo Iterator é lançada
        break

Links úteis:

https://pythonacademy.com.br/blog/iterators-e-generators-em-python

https://www.w3schools.com/python/python_iterators.asp

Obrigado, Pedro! Resposta bem completa.