Trilha de aprendizado · Nível 10 · Tutorial 1

Consumir iteradores com iter e next

Distinguir uma fonte iterável de um iterador e controlar seu consumo, reconhecendo avanço, esgotamento e possibilidade de iniciar uma nova passagem.

  • Nível: Intermediário
  • Duração: 15 min
  • 7 passos
Consumir iteradores com iter e next

O que você vai percorrer

  1. Distinguir a fonte do percurso Reconheça a diferença entre a fonte iterável e o objeto que guarda a posição de um percurso. 2 min
  2. Avançar um elemento de cada vez Use iter e next para avançar por uma fonte, acompanhando a posição preservada pelo iterador. 2 min
  3. Reconhecer e tratar o esgotamento Identifique quando um iterador termina e escolha entre tratar StopIteration ou fornecer um valor padrão a next. 2 min
  4. Comparar percursos independentes e estado compartilhado Compare iteradores criados separadamente com dois nomes que apontam para o mesmo iterador. 3 min
  5. Entender o que for consome Veja como o for obtém e avança um iterador, incluindo o efeito de um consumo anterior com next e de uma interrupção com break. 2 min
  6. Converter apenas o que ainda resta Use list para reunir os elementos que ainda estão disponíveis em um iterador, sem confundir essa operação com uma nova passagem pela fonte. 1 min
  7. Aplicar o controle de consumo Integre o uso de iter, next, for e list para acompanhar posições independentes e compartilhadas em uma mesma fonte. 4 min

O que você vai aprender

  • Distinguir iteráveis de iteradores usando listas, range e os resultados de iter.
  • Obter um iterador com iter e solicitar elementos individualmente com next.
  • Identificar o esgotamento por StopIteration e usar next com um valor padrão.
  • Prever os resultados de consumos sucessivos e de duas referências ao mesmo iterador.

Antes de começar

  • Percorrer textos e intervalos com for e range
  • Organizar e atualizar dados em listas
  • Controlar referências e cópias de coleções
  • Tratar exceções com try, except, else e finally

Passo 1 de 7

Distinguir a fonte do percurso

Reconheça a diferença entre a fonte iterável e o objeto que guarda a posição de um percurso.

Fonte e percurso

Dois papéis diferentes

Uma fonte iterável é um objeto do qual Python pode obter um percurso. Uma lista e um objeto range são exemplos: eles organizam valores que podem ser percorridos.

Um iterador é o objeto que realiza esse percurso. Ele entrega elementos sucessivos e guarda a posição atual do consumo. Pense na fonte como uma coleção de itens e no iterador como um cursor que avança por ela.

A fonte não é o cursor

A lista permanece como fonte; a posição pertence ao iterador criado para percorrê-la.

Diagrama de uma lista com três elementos e um cursor separado apontando para a posição antes do primeiro elemento.

Fonte iterável: os valores. Iterador: a posição de leitura.

Obtendo iteradores

Use iter para iniciar um percurso

A função iter(...) recebe uma fonte iterável e devolve um iterador. O resultado passa a representar um percurso daquela fonte.

Neste momento, observe os papéis: cores e numeros são as fontes; percurso_cores e percurso_numeros são os iteradores.

Lista e range como fontes

python
cores = ["azul", "verde", "amarelo"]
numeros = range(3)

percurso_cores = iter(cores)
percurso_numeros = iter(numeros)

Exemplo

Uma categoria pode incluir a outra

Listas e objetos range são iteráveis, mas não são iteradores.

Já percurso_cores e percurso_numeros são iteradores — e também são iteráveis. Portanto, as categorias não são excludentes: todo iterador pode ser usado como iterável, mas nem todo iterável é um iterador.

Classifique os objetos

Fonte ou percurso?

Associe cada expressão à descrição mais adequada.

Toque em um item e depois no par correspondente.

Passo 2 de 7

Avançar um elemento de cada vez

Use iter e next para avançar por uma fonte, acompanhando a posição preservada pelo iterador.

Criar o percurso e pedir o próximo valor

Da fonte ao iterador

Use iter(fonte) para obter um iterador. Em seguida, next(iterador) solicita um elemento e desloca a posição desse iterador para o próximo.

A fonte continua sendo a lista ou o range; quem guarda a posição do consumo é o iterador.

Um avanço por chamada

python
tarefas = ["revisar", "testar", "publicar"]
percurso = iter(tarefas)

print(next(percurso))  # revisar
print(next(percurso))  # testar

# A lista-fonte não foi alterada:
print(tarefas)         # ['revisar', 'testar', 'publicar']

A posição avança, a lista permanece

Diagrama de uma lista com três cartões e um cursor de iterador após entregar os dois primeiros itens, apontando para o terceiro; a lista original permanece inteira.

Após duas chamadas a next(percurso), o cursor está antes de publicar. Os itens já entregues continuam na lista.

A pausa não reinicia o percurso

O estado fica guardado

Você pode chamar next agora, executar outras instruções e chamá-lo novamente depois. O iterador não volta sozinho ao começo: ele preserva a posição alcançada.

O mesmo vale para uma fonte range.

Consumo parcial de um range

python
numeros = range(10, 13)
percurso = iter(numeros)

primeiro = next(percurso)
print(primeiro)        # 10

mensagem = "a posição continua guardada"
print(mensagem)

segundo = next(percurso)
print(segundo)         # 11

Dica

Rastreie antes de executar

Para prever uma chamada a next, marque mentalmente o próximo elemento ainda não entregue. Depois da chamada, mova essa marca uma posição para a frente.

Pratique o rastreamento

Qual valor vem depois?

Complete o comentário com o valor exibido pela segunda chamada:

cores = ["azul", "verde", "amarelo"]
percurso = iter(cores)

print(next(percurso))  # azul
print(next(percurso))  # ____

Retome depois da pausa

Complete o resultado:

valores = range(3, 6)
percurso = iter(valores)

print(next(percurso))  # 3
print(next(percurso))  # 4

# outras instruções podem aparecer aqui
print(next(percurso))  # ____

Passo 3 de 7

Reconhecer e tratar o esgotamento

Identifique quando um iterador termina e escolha entre tratar StopIteration ou fornecer um valor padrão a next.

O último item não é um erro

Depois do fim

Um iterador se esgota somente quando você pede um elemento depois do último disponível. A chamada que entrega o último elemento funciona normalmente; a próxima chamada sinaliza que não há mais valores com StopIteration.

Posição após o último elemento

Observe a diferença entre receber o último valor e tentar avançar além dele.

Diagrama de uma sequência com os itens azul, verde e amarelo. Um cursor entrega amarelo como último item e, numa solicitação seguinte, aparece depois da sequência sem item para entregar.

O esgotamento acontece na solicitação posterior ao último elemento.

Último valor e esgotamento

Execute as chamadas em ordem.

python
it = iter(["azul", "verde"])

print(next(it))  # azul
print(next(it))  # verde: último elemento
print(next(it))  # StopIteration

Tratar o sinal ou usar um padrão

Duas escolhas para o consumo manual

Quando a ausência de outro elemento for esperada, você pode capturar especificamente StopIteration. Outra opção é usar next(iterador, padrao): em vez de lançar a exceção, ele retorna o padrão.

Escolha um padrão que não possa ser confundido com um dado válido. Aqui, "SEM_ITEM" é melhor do que "azul", pois cores podem aparecer na fonte.

Duas formas de lidar com o fim

As duas abordagens abaixo detectam o término sem reiniciar o iterador.

python
it = iter(["azul"])

try:
    print(next(it))
    print(next(it))
except StopIteration:
    print("Não há outro item.")

outro = iter(["azul"])
print(next(outro, "SEM_ITEM"))
print(next(outro, "SEM_ITEM"))
print(next(outro, "SEM_ITEM"))

Atenção

Esgotado continua esgotado

O valor padrão não entra na fonte e não reinicia o iterador. Depois de esgotado, cada nova chamada com o mesmo padrão retorna esse padrão. Um iterador vazio também sinaliza o fim já na primeira solicitação.

Preveja o resultado

Qual é a saída?

Considere o código:

it = iter(["A"])
print(next(it, "FIM"))
print(next(it, "FIM"))
print(next(it, "FIM"))

O que será exibido?

Iterador vazio

Qual é o resultado de next(iter([]), "SEM_ITEM")?

Passo 4 de 7

Comparar percursos independentes e estado compartilhado

Compare iteradores criados separadamente com dois nomes que apontam para o mesmo iterador.

Dois iteradores, duas posições

A mesma fonte pode iniciar dois percursos

Uma lista ou um range é uma fonte iterável. Cada chamada a iter(fonte) cria um iterador com sua própria posição de consumo. Portanto, dois iteradores obtidos da mesma lista podem avançar de forma independente.

Cursores independentes

Cada chamada a iter(tarefas) cria um cursor novo sobre a mesma lista; a lista não é duplicada nem consumida.

Diagrama de uma lista com três tarefas e dois cursores independentes. Um cursor está antes da primeira tarefa e outro está antes da segunda.

A fonte é compartilhada, mas cada iterador mantém sua própria posição.

Percursos independentes

Execute e acompanhe cada posição separadamente.

python
tarefas = ["planejar", "codificar", "revisar"]

primeiro = iter(tarefas)
segundo = iter(tarefas)

print(next(primeiro))  # planejar
print(next(primeiro))  # codificar
print(next(segundo))   # planejar

Dois nomes não criam dois percursos

O estado é único

Quando iter() recebe um iterador, ele devolve o próprio objeto. Assim, outro = iter(cursor) não copia nem reinicia o percurso. O mesmo vale para uma atribuição direta, como outro = cursor: há dois nomes para uma única posição de consumo.

Referências ao mesmo iterador

As chamadas alternadas avançam um único cursor.

python
tarefas = ["planejar", "codificar", "revisar"]

cursor = iter(tarefas)
outro_nome = iter(cursor)

print(cursor is outro_nome)  # True
print(next(cursor))          # planejar
print(next(outro_nome))      # codificar
print(next(cursor))          # revisar

Dica

Para começar de novo

Depois que um iterador se esgota, obtenha outro com iter(tarefas). Chamar iter() sobre o iterador esgotado não o recupera: ele continua sendo o mesmo objeto esgotado.

Preveja o compartilhamento

Qual valor aparece?

Considere o código:

numeros = [10, 20, 30]
a = iter(numeros)
b = a
next(a)
print(next(b))

Complete com o valor impresso: ____

Compare os dois cenários

Explique a diferença

Compare os casos abaixo. Por que o primeiro permite que ambos os nomes comecem por "A", enquanto o segundo compartilha os avanços?

itens = ["A", "B"]

# Caso 1
esquerda = iter(itens)
direita = iter(itens)

# Caso 2
cursor = iter(itens)
outro = iter(cursor)

Escreva pelo menos 80 caracteres (0/80).

Passo 5 de 7

Entender o que for consome

Veja como o for obtém e avança um iterador, incluindo o efeito de um consumo anterior com next e de uma interrupção com break.

O percurso interno do for

Um for também consome

Conceitualmente, ao receber uma fonte ou iterador, o for obtém um iterador e pede um elemento por vez. Para cada elemento recebido, ele executa o corpo do laço. Quando não há outro elemento, ocorre StopIteration; o próprio for encerra o laço normalmente, sem que você precise escrever try e except.

Fluxo de consumo

O cursor representa a posição guardada pelo iterador.

Diagrama de uma sequência de quatro itens com um cursor avançando item a item para um laço; após o último item, o fluxo termina.

O for solicita, usa e avança: cada elemento entregue deixa de estar disponível naquele iterador.

O ponto atual continua valendo

Começar depois de next e continuar depois de break

Se você já chamou next(it), um for sobre it começa no próximo elemento disponível. E, se o corpo executa break, o elemento que acionou o break já foi entregue e consumido; os elementos posteriores continuam disponíveis no mesmo iterador.

Observe o mesmo iterador em três consumos

Execute este código no seu Python 3 e acompanhe a posição de it.

python
numeros = [10, 20, 30, 40]
it = iter(numeros)

print(next(it))  # 10: já foi consumido

for numero in it:
    print(numero)
    if numero == 30:
        break

print("restante:")
for numero in it:
    print(numero)

# Saída:
# 10
# 20
# 30
# restante:
# 40

Dica

Fonte ou iterador?

Um novo for sobre a lista numeros cria uma nova passagem e volta ao início. Já um novo for sobre it usa a posição atual — ou não executa nada se it estiver esgotado.

Ordene o trabalho do for

Fluxo conceitual

Coloque na ordem as etapas de funcionamento de um for que percorre uma fonte.

  1. Executar o corpo do laço com o elemento recebido
  2. Solicitar o próximo elemento
  3. Obter um iterador da fonte
  4. Repetir solicitação e corpo até o iterador sinalizar StopIteration

Preveja o que ainda resta

Depois do break

Qual valor será impresso no último print?

it = iter([1, 2, 3, 4])
next(it)

for valor in it:
    if valor == 3:
        break

print(next(it))

Resposta: ____

Passo 6 de 7

Converter apenas o que ainda resta

Use list para reunir os elementos que ainda estão disponíveis em um iterador, sem confundir essa operação com uma nova passagem pela fonte.

list consome o restante

Do cursor atual até o fim

list(iterador) solicita todos os elementos que ainda estão disponíveis e cria uma nova lista com eles. Ao terminar, o iterador fica esgotado.

Se algum valor já foi entregue por next() ou por um for, ele não volta a aparecer na lista criada.

O que entra na nova lista

Observe que a conversão começa na posição atual do iterador, não no início da fonte.

Diagrama de uma lista fonte com quatro cartões: dois cartões iniciais apagados como já consumidos, dois cartões finais destacados como restantes, e uma seta dos cartões restantes para uma nova lista com esses dois cartões.

A lista resultante recebe somente os elementos restantes.

Veja o consumo acontecer

Conversão após um avanço

Execute este código e compare os dois valores impressos.

python
tarefas = ["revisar", "testar", "publicar"]
percurso = iter(tarefas)

print(next(percurso))
print(list(percurso))
print(list(percurso))

Exemplo

Saída esperada

revisar
['testar', 'publicar']
[]

A primeira conversão consome testar e publicar. Na segunda, não há mais nenhum elemento disponível; por isso, o resultado é [].

Atenção

A lista fonte não é consumida

O consumo acontece em percurso, não em tarefas. Depois desse código, tarefas continua sendo ["revisar", "testar", "publicar"].

Novo iterador, nova passagem

Volte à fonte, não ao iterador

Para começar outra passagem, obtenha outro iterador da fonte com iter(tarefas). Esse novo iterador começa no início, mesmo que o anterior esteja esgotado.

Comparando os dois percursos

percurso_antigo permanece esgotado; novo_percurso tem uma posição própria.

python
tarefas = ["revisar", "testar", "publicar"]

percurso_antigo = iter(tarefas)
next(percurso_antigo)
print(list(percurso_antigo))

novo_percurso = iter(tarefas)
print(list(novo_percurso))

Dois estados diferentes

Os dois iteradores vêm da mesma lista, mas guardam posições de consumo independentes.

Diagrama comparativo de uma única lista fonte conectada a dois cursores: o cursor superior está no fim e leva a uma lista vazia; o cursor inferior está no início e leva a uma lista contendo todos os três elementos.

Criar outro iterador permite percorrer a mesma fonte novamente.

Preveja as conversões

Complete a lista resultante

Considere o código:

numeros = [4, 8, 12]
percurso = iter(numeros)
next(percurso)
resultado = list(percurso)

O valor de resultado é ___.

Nova passagem pela fonte

Depois do código anterior, execute:

outro = iter(numeros)
resultado_novo = list(outro)

O valor de resultado_novo é ___.

Passo 7 de 7

Aplicar o controle de consumo

Integre o uso de iter, next, for e list para acompanhar posições independentes e compartilhadas em uma mesma fonte.

Um percurso completo sobre a mesma fonte

Fonte preservada, posições em movimento

A lista é a fonte: ela não muda enquanto os iteradores são consumidos. Neste exemplo, percurso e apelido apontam para o mesmo iterador, enquanto independente começa outro percurso na mesma lista.

Leia as chamadas na ordem: cada next, o for interrompido e list(percurso) avançam a posição de percurso.

Posições de consumo

Diagrama de uma lista com quatro tarefas; dois ponteiros ligados ao mesmo cursor depois da segunda tarefa, um cursor independente no início e um novo cursor também no início.

Dois nomes podem compartilhar um único cursor; chamar iter novamente na lista cria outro cursor.

Rastreie o consumo

python
tarefas = ["preparar", "revisar", "enviar", "arquivar"]

percurso = iter(tarefas)
apelido = percurso
independente = iter(tarefas)

print(next(percurso))       # preparar
print(next(apelido))        # revisar: mesmo estado de percurso
print(next(independente))   # preparar: estado independente

for tarefa in percurso:
    print(f"for: {tarefa}")
    break                   # entrega "enviar" e então interrompe

print(list(percurso))       # ['arquivar']
print(next(percurso, "sem tarefa"))

novo_percurso = iter(tarefas)
print(list(novo_percurso))
print(tarefas)

Prática local: preveja e confirme

Execute no seu Python 3

Antes de executar o código anterior, preveja cada linha exibida. Depois, copie-o para um arquivo .py ou para o interpretador Python 3 no seu computador e compare sua previsão com o resultado.

Observe especialmente que o break não devolve "enviar": esse valor já foi entregue ao corpo do for. Por isso, só "arquivar" resta para list(percurso).

Explique os estados finais

Quais valores são exibidos pelo código? Explique quais nomes compartilham estado, o que resta após o break e por que novo_percurso consegue começar pelas quatro tarefas novamente.

Escreva pelo menos 120 caracteres (0/120).

Transfira o raciocínio para range

Percursos de um intervalo

Considere o código:

<code>faixa = range(3)
a = iter(faixa)
b = iter(faixa)
print(next(a))
print(next(a))
print(next(b))</code>

Qual é a saída?

Síntese do controle de consumo

Resumo

O que você controla ao iterar

  • A fonte, como uma lista ou um range, permite obter iteradores; consumi-los não altera seus elementos.
  • next avança um iterador, e dois nomes ligados ao mesmo objeto compartilham a mesma posição.
  • for e list também consomem o iterador recebido: for pode parar com break, e list coleta somente o que ainda resta.
  • Após o esgotamento, next(iterador, padrao) retorna o padrão sem reiniciar nada.
  • Para uma nova passagem pela fonte, obtenha outro iterador com iter(fonte).

Tutorial concluído

Parabéns! Você concluiu: Consumir iteradores com iter e next

Você concluiu o controle básico de consumo de iteradores. Agora consegue separar a fonte da posição de percurso, prever o estado compartilhado e iniciar uma nova passagem quando necessário.

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