1
resposta

Como diminuir o código através de geradores?

No final do artigo da página https://www.alura.com.br/artigos/o-que-sao-iteradores-no-python, é sugerido que é possível diminuir o código usndo geradores, mas os exemplos da documentação são com inteiros, usando generate_ints. É possível usar para stings?

class IteradorHttp():
    def __init__(self):
        self.registro = open('acessos.log', 'r')
        self.linha_atual = ''

    def __iter__(self):
        return self

    def __next__(self):
        self.linha_atual = self.registro.readline()
        while self.linha_atual and not self.linha_atual.startswith('http://'):
            self.linha_atual = self.registro.readline()
        if self.linha_atual:
            return self.linha_atual
        raise StopIteration

iterador = IteradorHttp()

for url in iterador:
    print(url)

Como a ideia é fazer lazy evaluation desse código com geradores, resolvi buscar o forum pra ver como alguem que entende mais faria

1 resposta

Oi Marcos, como você está?

Peço desculpas pela demora em obter um retorno.

Uma das formas de otimizar o código é utilizar a palavra chave yield para transformar a função em uma função geradora, ou seja, que vai retornar o resultado de forma espaçada, um valor de cada vez e não tudo de uma uma só vez.

Segundo a documentação do Python, “qualquer função que contenha a palavra chave yield é uma função geradora”. Sendo assim, uma das formas de otimizar o código é modificá-lo para a estrutura a seguir:

def gerador(nome_arquivo):
  arquivo = open(nome_arquivo, 'r')
  linhas_do_arquivo = arquivo.readlines()

  for endereco in linhas_do_arquivo:
    if endereco.startswith('http://'):
      yield endereco

gen = gerador('acessos.log')

Porém, assim como existe a compreensão de lista, também existe a compreensão de geradores. A sintaxe para expressão do gerador é semelhante à de uma compreensão de lista, mas, os colchetes são substituídos por parênteses. Então, simplificando ainda mais o código, poderíamos reduzi-lo a duas linhas, como mostro abaixo:

registro = open('acessos.log', 'r')
sites_sem_https = (url for url in registro if url.startswith('http://'))

Essa expressão geradora, assim como a função geradora, não produz o resultado de imediato, é necessário utilizar a função next para acessar o resultado. Vale lembrar que é possível passar um segundo parâmetro para função next para evitar a impressão do StopIteration:

next(sites_sem_https, "Fim da Interação")

Qualquer dúvida fico à disposição.

Abraços e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓. Bons Estudos!