Desafio Python

Pipeline preguiçoso com geradores

Enunciado

Crie um pipeline de processamento usando geradores que:

  1. Leia números de uma lista;
  2. Filtre apenas os pares;
  3. Eleve cada par ao quadrado;
  4. Some apenas os 3 primeiros resultados.

Implemente funções geradoras separadas para cada etapa e uma expressão geradora para o quadrado. O resultado final deve ser a soma dos 3 primeiros quadrados de pares.

Requisitos

  • Usar pelo menos uma função geradora com yield para filtrar pares.
  • Usar uma expressão geradora para elevar ao quadrado.
  • Consumir apenas os 3 primeiros resultados com itertools.islice ou next().
  • Imprimir a soma final.

Código inicial

import itertools

def apenas_pares(numeros):
    # complete com yield
    pass

def pipeline(numeros):
    # complete: filtre, eleve ao quadrado e pegue os 3 primeiros
    pass

# Teste:
numeros = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(pipeline(numeros))

Saída esperada

56
Ver dica

A soma dos quadrados dos 3 primeiros pares (2, 4, 6) é 4 + 16 + 36 = 56. Use itertools.islice(gerador, 3) para limitar a 3 itens.

Mostrar solução
import itertools

def apenas_pares(numeros):
    """Gerador que produz apenas números pares."""
    for n in numeros:
        if n % 2 == 0:
            yield n

def pipeline(numeros):
    """Encadeia geradores de forma preguiçosa e soma os 3 primeiros quadrados."""
    pares = apenas_pares(numeros)               # etapa 1: filtra pares
    quadrados = (x * x for x in pares)          # etapa 2: expressão geradora
    primeiros = itertools.islice(quadrados, 3)  # etapa 3: pega só 3
    return sum(primeiros)                       # etapa 4: soma

# Teste:
numeros = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(pipeline(numeros))

Passo a passo

  1. apenas_pares percorre a lista e usa yield para emitir somente os pares.
  2. Em pipeline, chamamos apenas_pares(numeros) para obter um gerador.
  3. A expressão geradora (x * x for x in pares) transforma cada par em seu quadrado, sem criar lista.
  4. itertools.islice(quadrados, 3) limita a produção aos 3 primeiros quadrados.
  5. sum(primeiros) consome o islice e soma os valores.
  6. O resultado é impresso.

Por que funciona

Cada etapa é um gerador que só produz o próximo item quando solicitado. A avaliação preguiçosa evita calcular quadrados desnecessários: como islice para após 3 itens, os demais pares nem chegam a ser processados. Isso mostra o poder de encadear geradores para formar pipelines eficientes.

Erros comuns

  • Usar list comprehensions em vez de geradores: [x*x for x in pares] cria a lista inteira, perdendo a preguiça.
  • Esquecer o islice e somar todos os quadrados: o resultado seria diferente (ex.: 220 para a lista completa).
  • Chamar apenas_pares sem consumir: geradores são preguiçosos; nada acontece até serem iterados.
  • Reutilizar um gerador já consumido: após o sum, o gerador está esgotado e não produz mais nada.

Outra forma de resolver

Poderia ser feito em uma única expressão geradora:

import itertools

def pipeline(numeros):
    pares = (n for n in numeros if n % 2 == 0)
    quadrados = (x * x for x in pares)
    return sum(itertools.islice(quadrados, 3))

Essa versão é mais concisa, mas separar em funções melhora a legibilidade e a reutilização.

Saída esperada

56