Trilha de aprendizado · Nível 10 · Tutorial 7

Compor fluxos de transformação sob demanda

Conectar fontes, filtros, transformações e limites em um fluxo incremental, usando funções e itertools sem criar listas intermediárias desnecessárias.

  • Nível: Intermediário
  • Duração: 20 min
  • 8 passos
Compor fluxos de transformação sob demanda

O que você vai percorrer

  1. Transformar valores com map Aplique uma função nomeada aos valores de uma fonte somente quando cada resultado for solicitado. 2 min
  2. Selecionar valores com filter Selecione valores sob demanda com um predicado e acompanhe os candidatos examinados até cada resultado aceito. 2 min
  3. Encadear fontes com chain Una fontes em uma única sequência de consumo, preservando a ordem e sem criar uma lista concatenada. 2 min
  4. Organizar etapas e observar a demanda Nomeie cada etapa de um fluxo e use registros para observar o que acontece na montagem e no consumo. 3 min
  5. Decidir quando filtrar e transformar Compare a ordem de filter e map para preservar o critério de seleção e evitar trabalho desnecessário quando isso for válido. 3 min
  6. Posicionar o limite no fluxo Compare o limite aplicado aos candidatos com o limite aplicado aos resultados aceitos e observe o consumo da fonte. 3 min
  7. Reconhecer etapas que consomem toda a entrada Entenda por que sorted interrompe a entrega incremental e como sua posição em relação a islice altera tanto o consumo quanto o significado do resultado. 2 min
  8. Aplicação final: compor e verificar um fluxo Monte um fluxo completo, execute testes locais e use os registros para comprovar que o processamento só acontece quando há consumo. 4 min

O que você vai aprender

  • Aplicar funções a elementos sob demanda com map e selecionar elementos com filter.
  • Encadear fontes com itertools.chain sem concatenar listas.
  • Construir um fluxo com etapas nomeadas e um consumidor final explícito.
  • Verificar como a ordem das etapas altera os resultados e a quantidade de elementos solicitados à fonte.

Antes de começar

  • Transformar dados com expressões geradoras
  • Limitar o consumo de iteradores com itertools
  • Passar funções como argumentos
  • Escolher entre lambda, funções nomeadas e compreensões
  • Escrever e executar testes de funções com pytest

Passo 1 de 8

Transformar valores com map

Aplique uma função nomeada aos valores de uma fonte somente quando cada resultado for solicitado.

map cria uma transformação sob demanda

Uma fonte, uma função

map(funcao, fonte) cria um iterador de resultados. Ele guarda a função e a fonte, mas não chama a função para todos os valores no momento da criação.

Use uma função nomeada quando o nome ajuda a deixar clara a responsabilidade da etapa.

Criando o iterador

python
def dobrar(numero):
    print(f"transformando {numero}")
    return numero * 2

numeros = [2, 4, 6]
dobrados = map(dobrar, numeros)

print(dobrados)

Criação não consome a fonte

Diagrama mostrando a lista 2, 4, 6 conectada a uma etapa dobrar e a um iterador map; antes de next, nenhum valor atravessou a etapa.

Após criar dobrados, a função dobrar ainda não foi chamada.

Cada next aciona uma transformação

Um pedido, uma chamada

Ao pedir o próximo resultado com next(dobrados), o map obtém o próximo elemento da fonte, chama dobrar para esse elemento e entrega o retorno.

Assim, duas chamadas a next transformam somente os dois primeiros valores.

Consumindo aos poucos

python
print(next(dobrados))
print(next(dobrados))

Exemplo

Saída esperada

transformando 2
4
transformando 4
8

A primeira solicitação chama dobrar(2) e entrega 4. A segunda chama dobrar(4) e entrega 8. O valor 6 continua sem transformação até que alguém solicite outro resultado.

A demanda caminha até a fonte

Diagrama de duas solicitações sucessivas atravessando um iterador map até uma fonte e retornando os valores transformados 4 e 8; o último valor da fonte permanece aguardando.

Cada resultado solicitado corresponde a uma chamada de dobrar neste exemplo.

Preveja o consumo pontual

O que acontece?

Considere o código:

chamadas = []

def triplicar(valor):
    chamadas.append(valor)
    return valor * 3

resultados = map(triplicar, [1, 2, 3])
primeiro = next(resultados)

Quais são os valores de primeiro e chamadas após esse código?

Passo 2 de 8

Selecionar valores com filter

Selecione valores sob demanda com um predicado e acompanhe os candidatos examinados até cada resultado aceito.

Filter seleciona, não transforma

Um filtro entrega os valores aprovados

Use filter(predicado, fonte) para criar um iterador que procura elementos cujo predicado retorne True. Ele não executa a busca ao ser criado: o trabalho acontece quando alguém solicita o próximo resultado.

Diferentemente de map, filter devolve o próprio valor da fonte quando ele é aceito. O predicado apenas decide se esse valor segue adiante.

Selecionando números pares

Crie este fluxo e consuma seus resultados um a um.

python
def eh_par(numero):
    return numero % 2 == 0

numeros = iter([3, 8, 11, 14])
pares = filter(eh_par, numeros)

print(next(pares))  # 8
print(next(pares))  # 14

Caminho de cada candidato

Para entregar 8, o filtro precisou avaliar 3 e depois 8. O valor entregue continua sendo 8, não o resultado booleano True.

Diagrama de fluxo mostrando os candidatos 3, 8, 11 e 14 passando por um predicado de paridade; 3 e 11 são rejeitados, enquanto 8 e 14 seguem para a saída.

O predicado decide o caminho; o elemento aceito é preservado.

Uma saída pode exigir várias avaliações

O filtro busca até achar uma aprovação

Ao chamar next(pares) pela primeira vez, filter examina 3 (rejeita) e 8 (aceita), então entrega 8. Na chamada seguinte, retoma de onde parou: examina 11 e depois entrega 14.

Assim, saídas entregues, candidatos examinados e chamadas do predicado são contagens relacionadas, mas não necessariamente iguais.

Observe as chamadas durante o consumo

A lista avaliados mostra exatamente quais candidatos chegaram ao predicado.

python
avaliados = []

def eh_par_registrando(numero):
    avaliados.append(numero)
    return numero % 2 == 0

pares = filter(eh_par_registrando, [3, 8, 11, 14])

print(avaliados)     # []: ainda não houve consumo
print(next(pares))   # 8
print(avaliados)     # [3, 8]
print(next(pares))   # 14
print(avaliados)     # [3, 8, 11, 14]

Dica

Leia os registros como evidência

A criação de pares não chama o predicado. Cada candidato examinado gera uma chamada; somente os que retornam True aparecem na saída.

Rastreie a próxima saída

Complete o rastreamento

Considere filter(eh_par, [5, 6, 9, 10]). Para produzir a primeira saída, o filtro examina ____ candidatos.

Qual valor é entregue?

Com filter(eh_par, [5, 6, 9, 10]), qual é o primeiro valor entregue por next(...)?

Passo 3 de 8

Encadear fontes com chain

Una fontes em uma única sequência de consumo, preservando a ordem e sem criar uma lista concatenada.

Uma sequência, duas fontes

Encadeamento incremental

itertools.chain recebe fontes e produz um iterador único. Ele entrega todos os elementos da primeira fonte; somente quando ela se esgota, passa para a próxima.

Isso preserva tanto a ordem dentro de cada fonte quanto a ordem em que você informou as fontes.

Ordem do chain

Observe que não há alternância entre as fontes: a segunda só começa após o fim da primeira.

Diagrama de duas sequências, A B C e 1 2, ligadas por chain em uma saída A B C 1 2, com a primeira fonte totalmente consumida antes da segunda.

chain(fonte_a, fonte_b) produz primeiro toda fonte_a e depois toda fonte_b.

Criar não é consumir

Usando chain

Execute o código e observe quando cada mensagem é exibida.

python
from itertools import chain


def fonte(nome, valores):
    for valor in valores:
        print(f"{nome} fornece {valor}")
        yield valor


primeira = fonte("primeira", ["A", "B"])
segunda = fonte("segunda", ["C", "D"])
fluxo = chain(primeira, segunda)

print("Fluxo criado")
print(next(fluxo))
print(list(fluxo))

O que acontece?

Ao criar fluxo, nenhuma fonte é avançada. O primeiro next(fluxo) pede A à primeira fonte. Depois, list(fluxo) consome o restante: B e, só então, C e D da segunda fonte.

chain não monta uma lista concatenada antecipadamente. Ele mantém o consumo incremental das fontes.

Dica

Não confunda com intercalação

Com ["A", "B"] e ["C", "D"], chain entrega A, B, C, D — não A, C, B, D. Alternar elementos por posição é outra operação.

Preveja a saída

Ordem de consumo

Considere:

from itertools import chain
numeros = [2, 4]
letras = ["x", "y"]
resultado = chain(numeros, letras)

Organize os valores na ordem em que list(resultado) os entrega.

  1. "y"
  2. 2
  3. "x"
  4. 4

Passo 4 de 8

Organizar etapas e observar a demanda

Nomeie cada etapa de um fluxo e use registros para observar o que acontece na montagem e no consumo.

Um fluxo legível tem etapas visíveis

Da fonte ao consumidor

Em vez de aninhar várias chamadas em uma única linha, dê um nome para cada etapa. Isso deixa claro o papel de cada uma: fonte fornece valores, selecionados aplica o filtro, transformados aplica a transformação e limitados expõe apenas a quantidade desejada.

A função de composição abaixo deve retornar o iterador final. Ela não deve chamar list, next nem usar um for para consumir o fluxo.

A demanda percorre o fluxo para trás

O consumidor pede uma saída; as etapas anteriores só trabalham o necessário para atendê-lo.

Diagrama de um fluxo com duas fontes entrando em chain, depois filter, map e islice até o consumidor. Uma seta de demanda aponta do consumidor para as fontes, e setas de valores apontam das fontes para o consumidor.

Os valores seguem das fontes ao consumidor; cada pedido do consumidor se propaga no sentido contrário.

Dica

Nomes revelam responsabilidades

Nomear etapas não torna o processamento menos incremental. Os nomes apenas guardam referências aos iteradores conectados.

Monte um fluxo que registra o trabalho

Experimento autocontido

Copie o código para um arquivo, por exemplo fluxo.py, e execute-o. A lista registro permite observar exatamente quando a fonte, o predicado e a transformação foram acionados.

fluxo.py

python
from itertools import chain, islice


def fonte_registrada(valores, registro):
    for valor in valores:
        registro.append(f"fonte:{valor}")
        yield valor


def eh_par(valor, registro):
    registro.append(f"predicado:{valor}")
    return valor % 2 == 0


def dobrar(valor, registro):
    registro.append(f"transformacao:{valor}")
    return valor * 2


def compor_fluxo(primeira, segunda, registro):
    fonte = chain(
        fonte_registrada(primeira, registro),
        fonte_registrada(segunda, registro),
    )
    selecionados = filter(lambda valor: eh_par(valor, registro), fonte)
    transformados = map(lambda valor: dobrar(valor, registro), selecionados)
    limitados = islice(transformados, 2)
    return limitados


registro = []
fluxo = compor_fluxo([1, 2], [3, 4], registro)

print("Após montar:", registro)
print("Primeira saída:", next(fluxo))
print("Após a primeira saída:", registro)
print("Restante:", list(fluxo))
print("Após consumir tudo:", registro)

Exemplo

O que observar

Após montar, o registro é []: criar e conectar os iteradores não chamou a fonte, o predicado nem a transformação.

Na primeira chamada de next(fluxo), o fluxo examina 1 e o rejeita; depois examina 2, aceita-o e o transforma. Portanto, a primeira saída é 4, e os eventos registrados são, nesta ordem: fonte:1, predicado:1, fonte:2, predicado:2, transformacao:2.

Relate a primeira solicitação

Antes e durante o consumo

No seu computador, execute o programa até a linha Após a primeira saída. Qual é a diferença entre o registro após montar o fluxo e o registro após a primeira saída? Explique quais etapas participaram e por que o valor 1 aparece no registro mesmo não sendo entregue ao consumidor.

Escreva pelo menos 100 caracteres (0/100).

Passo 5 de 8

Decidir quando filtrar e transformar

Compare a ordem de filter e map para preservar o critério de seleção e evitar trabalho desnecessário quando isso for válido.

O predicado recebe o valor da etapa anterior

A ordem muda o que é testado

Em um fluxo, cada etapa recebe a saída da etapa anterior. Portanto, em map(transformar, filter(aceitar, dados)), o predicado aceitar recebe os valores originais. Já em filter(aceitar, map(transformar, dados)), ele recebe valores já transformados.

Mover o mesmo predicado não é apenas uma mudança de posição: pode mudar o significado da seleção.

Dois caminhos, dois valores testados

Diagrama comparando um filtro antes de uma transformação, que testa valores originais, com um filtro depois da transformação, que testa valores já transformados.

À esquerda, o filtro avalia a entrada; à direita, avalia a saída de map.

Mesmo predicado, resultado diferente

Compare os dois fluxos

Execute o código e observe os valores materializados ao final de cada fluxo.

python
dados = [1, 2, 3, 4]

def multiplicar_por_10(valor):
    return valor * 10

def maior_que_2(valor):
    return valor > 2

# O predicado recebe os valores originais.
filtrar_antes = map(
    multiplicar_por_10,
    filter(maior_que_2, dados),
)

# O mesmo predicado agora recebe valores multiplicados por 10.
filtrar_depois = filter(
    maior_que_2,
    map(multiplicar_por_10, dados),
)

print(list(filtrar_antes))  # [30, 40]
print(list(filtrar_depois)) # [10, 20, 30, 40]

Atenção

Não existe uma ordem automaticamente correta

Filtrar antes só é apropriado se o critério fizer sentido para o dado de entrada. Se a regra de negócio depende do valor transformado, mantenha o filtro depois de map.

Preserve o critério ao comparar

Se multiplicar por 10 e o critério desejado é “resultado maior que 20”, há duas formas equivalentes:

  • filtrar a entrada com valor > 2 e depois multiplicar;
  • multiplicar e filtrar a saída com valor > 20.

O predicado foi adaptado porque cada posição trabalha em uma escala diferente.

Compare resultado e trabalho realizado

Registre as transformações

Cada execução cria seu próprio registro. Ambas entregam os mesmos resultados, mas não executam a transformação na mesma quantidade de candidatos.

python
dados = [1, 2, 3, 4]

def executar(filtro_antes):
    transformados = []

    def multiplicar_por_10(valor):
        transformados.append(valor)
        return valor * 10

    if filtro_antes:
        fluxo = map(
            multiplicar_por_10,
            filter(lambda valor: valor > 2, dados),
        )
    else:
        fluxo = filter(
            lambda valor: valor > 20,
            map(multiplicar_por_10, dados),
        )

    return list(fluxo), transformados

print(executar(True))   # ([30, 40], [3, 4])
print(executar(False))  # ([30, 40], [1, 2, 3, 4])

Dica

Use os registros para justificar a escolha

Quando o filtro sobre a entrada preserva a regra de seleção, colocá-lo antes evita chamar a transformação para candidatos rejeitados. Isso mostra menos trabalho no registro; não é uma regra universal de ordenação.

Associe cada fluxo à sua observação

Fluxo, resultado e registro

Relacione cada fluxo à combinação correta de valores entregues e valores recebidos pela função de transformação.

Toque em um item e depois no par correspondente.

Passo 6 de 8

Posicionar o limite no fluxo

Compare o limite aplicado aos candidatos com o limite aplicado aos resultados aceitos e observe o consumo da fonte.

Dois significados para o mesmo limite

Candidatos ou resultados?

A posição de islice define o que está sendo limitado.

  • Em filter(predicado, islice(fonte, 4)), só quatro candidatos chegam ao filtro. Se houver rejeições, podem sair menos de quatro valores.
  • Em islice(filter(predicado, fonte), 4), o filtro continua pedindo candidatos até entregar quatro valores aceitos ou até a fonte se esgotar.

Portanto, um limite depois de filter pode fazer a fonte avançar bem além da quantidade de saídas desejada.

Posição do limite e demanda

Compare os dois percursos do fluxo.

Diagrama com duas fontes encadeadas e dois fluxos lado a lado: no primeiro, o limite aparece antes do filtro; no segundo, aparece depois do filtro. Tokens rejeitados e aceitos mostram que o segundo fluxo pode buscar mais candidatos.

À esquerda, o limite fecha a entrada do filtro. À direita, o filtro busca candidatos até completar o limite de resultados aceitos.

Compare com registros novos

Uma execução independente para cada fluxo

Execute o código. Cada chamada de executar cria fontes e listas de registro novas; assim, os dados observados em um fluxo não se misturam aos do outro.

A primeira composição limita quatro candidatos. A segunda solicita dois resultados pares, por isso precisa passar pelos ímpares até encontrar dois pares.

Limitar antes ou depois do filtro

Crie um arquivo Python, cole o código e execute-o.

python
from itertools import chain, islice


def fonte(nome, valores, fornecidos):
    for valor in valores:
        fornecidos.append((nome, valor))
        yield valor


def par(valor, avaliados):
    avaliados.append(valor)
    return valor % 2 == 0


def transformar(valor, transformados):
    transformados.append(valor)
    return valor * 10


def executar(limite_antes_do_filtro):
    fornecidos = []
    avaliados = []
    transformados = []

    primeira = fonte("primeira", [1, 3, 4], fornecidos)
    segunda = fonte("segunda", [5, 6, 8], fornecidos)
    encadeada = chain(primeira, segunda)

    if limite_antes_do_filtro:
        candidatos_limitados = islice(encadeada, 4)
        aceitos = filter(lambda valor: par(valor, avaliados), candidatos_limitados)
        fluxo = map(lambda valor: transformar(valor, transformados), aceitos)
    else:
        aceitos = filter(lambda valor: par(valor, avaliados), encadeada)
        transformados_sob_demanda = map(
            lambda valor: transformar(valor, transformados),
            aceitos,
        )
        fluxo = islice(transformados_sob_demanda, 2)

    resultado = list(fluxo)
    print("resultado:", resultado)
    print("fornecidos:", fornecidos)
    print("avaliados:", avaliados)
    print("transformados:", transformados)


print("Limite de 4 candidatos:")
executar(limite_antes_do_filtro=True)

print("\nLimite de 2 resultados aceitos:")
executar(limite_antes_do_filtro=False)

Escolha a composição pelo contrato

Limitar resultados válidos

As fontes encadeadas produzem [1, 3, 4] e depois [5, 6, 8]. Você precisa obter os dois primeiros valores pares, transformados por * 10. Qual composição atende ao requisito e quantos elementos da fonte são solicitados?

Passo 7 de 8

Reconhecer etapas que consomem toda a entrada

Entenda por que sorted interrompe a entrega incremental e como sua posição em relação a islice altera tanto o consumo quanto o significado do resultado.

sorted precisa ver toda a fonte

Uma barreira no fluxo

sorted devolve uma nova lista ordenada. Para decidir qual valor vem primeiro, ele precisa consumir toda a entrada finita antes de disponibilizar qualquer resultado.

Assim, um fluxo pode ser incremental antes de sorted, mas deixa de entregar valores sob demanda nesse ponto.

O que acontece antes da primeira saída

Mesmo que o consumidor peça apenas um valor depois de sorted, a etapa de ordenação precisa receber todos os valores da fonte.

Diagrama de uma fonte de números fluindo para um recipiente de ordenação que coleta todos os elementos antes de liberar uma sequência ordenada para um limite.

sorted materializa a entrada completa em uma lista antes de liberar o primeiro elemento.

Atenção

Limite posterior não evita a ordenação

Em islice(sorted(fonte), 3), o limite entrega no máximo três resultados, mas sorted já consumiu toda a fonte. Portanto, esse limite não reduz o trabalho exigido pela ordenação.

A posição do limite muda a pergunta

Dois fluxos, dois significados

Compare as duas composições:

  • sorted(islice(fonte, 3)): pega os três primeiros valores fornecidos e os ordena.
  • islice(sorted(fonte), 3): ordena todos os valores da fonte e então pega os três menores.

As duas usam limite e ordenação, mas respondem a perguntas diferentes.

Compare no seu computador

Execute este código e observe os resultados e os registros da fonte.

python
from itertools import islice


def fonte_registrada(valores, registro):
    for valor in valores:
        registro.append(valor)
        yield valor

valores = [7, 2, 9, 1, 5]

registro_prefixo = []
prefixo_ordenado = sorted(
    islice(fonte_registrada(valores, registro_prefixo), 3)
)

registro_global = []
menores_globais = list(
    islice(sorted(fonte_registrada(valores, registro_global)), 3)
)

print(prefixo_ordenado, registro_prefixo)
print(menores_globais, registro_global)
# [2, 7, 9] [7, 2, 9]
# [1, 2, 5] [7, 2, 9, 1, 5]

Dica

Materialize no fim, quando for necessário

Converter o resultado final limitado com list(...) pode ser uma escolha adequada, por exemplo, para exibir ou reutilizar os poucos valores selecionados. O problema é criar listas intermediárias sem que alguma etapa realmente precise delas.

Verifique a consequência

Consumo e limite

No fluxo islice(sorted(fonte), 2), a fonte pode permanecer parcialmente não consumida porque o limite pede apenas dois resultados.

Resultado e alcance

sorted(islice(fonte, 3)) pode produzir valores diferentes de list(islice(sorted(fonte), 3)).

Passo 8 de 8

Aplicação final: compor e verificar um fluxo

Monte um fluxo completo, execute testes locais e use os registros para comprovar que o processamento só acontece quando há consumo.

Fluxo final: etapas nomeadas e demanda sob controle

Da fonte ao consumidor

Neste desafio, duas fontes finitas são encadeadas com chain. O fluxo então seleciona leituras positivas, converte as leituras aceitas e entrega somente as três primeiras conversões.

A função montar_fluxo apenas conecta as etapas e retorna o iterador final. O consumo acontece depois, em list(fluxo). Os nomes fontes, validas e convertidas deixam clara a responsabilidade de cada etapa.

Sentido da demanda

O consumidor pede resultados à direita. Essa demanda volta pelas etapas até a fonte; os valores aceitos seguem no sentido contrário.

Diagrama de duas fontes conectadas por chain, seguidas de filter, map, islice e um consumidor final. Setas mostram a demanda indo do consumidor para as fontes e os valores indo das fontes para o consumidor.

Para obter três saídas aceitas, o filtro pode precisar solicitar mais de três candidatos às fontes.

Dica

Critério de incrementalidade

Após chamar montar_fluxo, o registro deve continuar vazio. As chamadas à fonte, ao predicado e à conversão só devem aparecer quando o consumidor avançar o iterador.

Prática local: montar, consumir e testar

Crie os arquivos no seu computador

Crie um arquivo chamado fluxo_leituras.py com o código abaixo. Em seguida, crie test_fluxo_leituras.py com os testes da próxima tela. Não substitua chain, filter, map ou islice por compreensões ou listas intermediárias.

fluxo_leituras.py

O módulo registra cada valor fornecido, cada avaliação do filtro e cada conversão.

python
from itertools import chain, islice


def fonte(nome, valores, registro):
    for valor in valores:
        registro.append(f"fonte:{nome}:{valor}")
        yield valor


def criar_predicado(registro):
    def eh_positivo(leitura):
        registro.append(f"filtro:{leitura}")
        return leitura > 0

    return eh_positivo


def criar_conversor(registro):
    def para_dez_unidades(leitura):
        registro.append(f"map:{leitura}")
        return leitura * 10

    return para_dez_unidades


def montar_fluxo(lote_a, lote_b, registro):
    fontes = chain(
        fonte("A", lote_a, registro),
        fonte("B", lote_b, registro),
    )
    validas = filter(criar_predicado(registro), fontes)
    convertidas = map(criar_conversor(registro), validas)
    return islice(convertidas, 3)

test_fluxo_leituras.py

Execute no terminal, na pasta dos arquivos: pytest -q.

python
from fluxo_leituras import montar_fluxo


def test_montar_nao_processa_nada_antes_do_consumo():
    registro = []

    fluxo = montar_fluxo([4, -1, 8], [0, 5, 12], registro)

    assert registro == []
    assert list(fluxo) == [40, 80, 50]


def test_consumo_para_apos_tres_resultados_aceitos():
    registro = []

    resultado = list(montar_fluxo([4, -1, 8], [0, 5, 12], registro))

    assert resultado == [40, 80, 50]
    assert registro == [
        "fonte:A:4", "filtro:4", "map:4",
        "fonte:A:-1", "filtro:-1",
        "fonte:A:8", "filtro:8", "map:8",
        "fonte:B:0", "filtro:0",
        "fonte:B:5", "filtro:5", "map:5",
    ]
    assert "fonte:B:12" not in registro

Conferir decisões e concluir

Relate o que você verificou

Depois de executar os testes, relate: (1) os valores entregues; (2) o que o registro mostrou antes do consumo; e (3) uma alteração de ordem — como mover islice ou inserir sorted — e seu efeito sobre o resultado ou sobre o trabalho realizado.

Escreva pelo menos 180 caracteres (0/180).

Resumo

Checklist de um fluxo correto e legível

Use estes critérios ao revisar um fluxo sob demanda.

  • As fontes são conectadas incrementalmente com chain, sem criar uma lista concatenada.
  • Cada etapa tem um nome que comunica sua função: fonte, filtro, transformação e limite.
  • A função de composição retorna o iterador final; um consumidor explícito, como list, inicia o trabalho.
  • filter pode examinar vários candidatos para entregar uma saída; map só transforma os valores aceitos que são solicitados.
  • A posição de islice muda se o limite vale para candidatos ou para resultados aceitos.
  • Uma operação como sorted consome toda a entrada antes de disponibilizar resultados; um limite posterior não reduz esse consumo.
  • Registros e testes verificam tanto os valores finais quanto o trabalho adiado e o alcance real da fonte.

Tutorial concluído

Parabéns! Você concluiu: Compor fluxos de transformação sob demanda

Muito bem! Você conectou fontes, filtro, transformação e limite sem listas intermediárias desnecessárias, e usou registros para confirmar quando o processamento ocorreu.

Baixe o Aplicativo agora para ter acesso a + de 5000 cursos gratuitos, exercícios, certificado e muito conteúdo sem pagar nada!

  • Cursos online 100% gratuitos do início ao fim

    Milhares de cursos online em vídeo, ebooks e áudiobooks.

  • Mais de 60 mil exercícios gratuitos

    Para testar seus conhecimentos no decorrer dos cursos online

  • Certificado Digital gratuito válido em todo o Brasil

    Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail

Aplicativo Cursa na tela de ebook, na tela de curso em vídeo e na tela de exercícios do curso, mais o certificado de conclusão de curso