Pular para o conteúdo

Fundamentos

O laço for e a função range() em Python

Aprenda o laço for em Python com range() de um, dois e três argumentos, percorra textos e sequências e evite as armadilhas do limite que não entra.

Por Prof. Rodrigo Faustino · Atualizado em · 13 min de leitura

O for percorre uma sequência de valores e executa o bloco uma vez para cada valor. Quando o programa precisa repetir algo um número conhecido de vezes, a sequência vem da função range(): range(5) entrega os números 0, 1, 2, 3 e 4, e o laço faz cinco voltas. O ponto que mais pega quem começa é que o limite nunca entra na contagem: range(1, 6) vai de 1 até 5.

O artigo anterior mostrou o while, em que a pessoa escreve o valor inicial, o teste e a atualização. O for junta essas três peças numa linha só e deixa o Python cuidar delas. Este artigo explica o range() com um, dois e três argumentos, mostra que o for serve para textos e para grupos de valores, acompanha os usos mais comuns (somas, máximos, tabelas) e lista os erros que aparecem nas aulas.

Do while ao for

À esquerda, um while com quatro linhas coloridas: i igual a 1, while i menor ou igual a 5, print(i) e i mais igual a 1. À direita, o for equivalente, com duas linhas: for i in range(1, 6) e print(i). Um texto explica que o for reúne valor inicial, teste e atualização na primeira linha. Uma faixa diz que as duas versões imprimem de 1 a 5 e que o 6 é o limite e não entra. Dois quadros no fim indicam quando usar for, quando se sabe o que percorrer, e quando usar while, quando o fim depende de algo que só aparece rodando.
O mesmo trabalho com while e com for: o for cuida de três das quatro peças.

Veja a tabuada do 2 escrita com for:

for i in range(1, 6):
    print("2 x", i, "=", 2 * i)
soma = 0
for n in range(1, 11):
    soma = soma + n
print("soma de 1 a 10:", soma)
print(sum(range(1, 11)))

A saída é a tabuada de 2 x 1 = 2 a 2 x 5 = 10, depois soma de 1 a 10: 55 e, na última linha, 55 de novo. A primeira linha do laço tem a palavra for, o nome da variável que recebe cada valor (i), a palavra in, a sequência (range(1, 6)) e os dois-pontos. O bloco recuado embaixo é o corpo. Não há i = 1 antes nem i += 1 dentro: o for pega o primeiro valor do range na primeira volta, o segundo na segunda, e termina quando os valores acabam.

A segunda parte do exemplo é o padrão do acumulador, visto no artigo sobre por que repetir: a variável soma começa em 0 e recebe cada n. O resultado, 55, é o da soma dos dez primeiros números. A função sum() faz a mesma conta de uma vez, e vale conhecê-la, mas o laço com acumulador é o que se aprende primeiro porque o mesmo desenho serve para produtos, contagens e máximos.

A escolha entre os dois laços segue uma regra simples. Use for quando o programa já sabe o que percorrer: os números de 1 a 10, os itens de um grupo, as letras de um texto. Use while quando o fim depende de algo que só aparece com o programa rodando, como uma resposta digitada ou uma leitura de sensor.

FastMindAssistente de IA local

A IA que lembra da sua vida e mora no seu computador

  • Memória de longo prazo com a fonte de cada resposta
  • Funciona offline: seus dados ficam no seu PC
  • Lê PDFs, slides, fotos e gravações de reunião
Baixar grátis para Windows

Plano Essencial grátis para sempre

A função range()

Três retas numéricas de 0 a 10. Na primeira, range(5) marca em verde os pontos de 0 a 4, e o 5 aparece como uma bolinha vermelha tracejada chamada parada. Na segunda, range(2, 8) marca de 2 a 7, com a parada no 8. Na terceira, range(10, 0, -3) marca 10, 7, 4 e 1, com setas de passo menos 3 entre eles e a parada no 0. À direita de cada reta está a lista resultante.
range(início, parada, passo): o início entra, a parada nunca entra.

O range() tem três formas, e a figura mostra cada uma numa reta numérica. Para ver os números que ele produz, o exemplo os converte em lista com list():

print(list(range(5)))
print(list(range(2, 8)))
print(list(range(10, 0, -3)))
print(list(range(0, 10, 3)))
print(list(range(5, 2)))
print(list(range(0)))
print(range(5))
print(len(range(0, 10, 3)))
print(3 in range(5), 5 in range(5))

A saída tem nove linhas: [0, 1, 2, 3, 4], [2, 3, 4, 5, 6, 7], [10, 7, 4, 1], [0, 3, 6, 9], [], [], range(0, 5), 4 e True False. As formas são:

  • range(parada) começa em 0, anda de 1 em 1 e para antes da parada. range(5) dá 0, 1, 2, 3, 4.
  • range(início, parada) começa no início. range(2, 8) dá 2, 3, 4, 5, 6, 7.
  • range(início, parada, passo) anda de passo em passo. range(0, 10, 3) dá 0, 3, 6, 9, e range(10, 0, -3), com passo negativo, conta para trás: 10, 7, 4, 1.

Três detalhes aparecem na saída. O primeiro é que range(5, 2) e range(0) são vazios: um for sobre eles não roda nenhuma vez, e o programa segue adiante sem erro. Para contar para trás é preciso um passo negativo, como no range(10, 0, -3). O segundo é que print(range(5)) não mostra os números e sim range(0, 5): o range é uma descrição da sequência, e não uma lista pronta. O list() é o que a monta. O terceiro é que o len() e o in funcionam diretamente sobre ele.

O range não gasta memória

Como o range guarda só o início, a parada e o passo, e produz cada número quando o laço pede, ele serve para sequências enormes sem custo:

for i in range(1000000):
    if i == 3:
        break
print("parou em", i)
print(len(range(1000000)))

A saída é parou em 3 e 1000000. O programa nunca construiu uma lista de um milhão de itens. Isso importa na ESP32, que tem pouca memória: um laço com range(10000) custa o mesmo que um com range(10), enquanto uma lista com dez mil números ocuparia uma parte da RAM da placa. O break que aparece no exemplo sai do laço antes do fim, e é tema de um artigo adiante.

A variável depois do laço

Depois do for, a variável do laço continua existindo e guarda o último valor que recebeu:

for i in range(5):
    print(i)
print("depois, i vale", i)

A saída é de 0 a 4 e depois, i vale 4. O i vale 4, e não 5: o 5 nunca foi entregue ao laço. É por isso que se diz que o range(5) faz cinco voltas e o i chega a 4.

Contando para trás e de passo em passo

O passo negativo faz a contagem regressiva, e o passo maior que 1 serve para pular valores, como os múltiplos de 5 ou os ângulos de um servo:

for i in range(10, 0, -3):
    print(i)
for i in reversed(range(3)):
    print("rev", i)
for graus in range(0, 181, 45):
    print(graus)

A saída é 10, 7, 4, 1, depois rev 2, rev 1, rev 0 e por fim 0, 45, 90, 135, 180. A função reversed() é uma segunda forma de inverter o range. Repare no limite do último laço: para o 180 entrar, a parada é 181, e esse tipo de ajuste "um a mais" é o que mais gera dúvida.

Percorrendo textos e grupos

O for não precisa de range(): ele percorre qualquer sequência. Um texto entrega as letras, uma tupla entrega os itens:

for letra in "ESP32":
    print(letra)
for dia in ("seg", "ter", "qua"):
    print(dia)
for i in range(3):
    for j in range(3):
        print(i * j, end=" ")
    print()

A saída é E, S, P, 3 e 2, depois seg, ter e qua e, no fim, uma grade de três linhas: 0 0 0, 0 1 2 e 0 2 4. O terceiro laço é um for dentro de outro, e vale a mesma regra do while: o de dentro roda completo a cada volta do de fora. A grade mostra a tabuada de 0 a 2.

Quando se precisa do número da volta junto com o valor, a função enumerate() entrega os dois:

for i, dia in enumerate(("seg", "ter", "qua")):
    print(i, dia)
for i, dia in enumerate(("seg", "ter"), 1):
    print(i, dia)
for a, b in ((1, 2), (3, 4)):
    print(a + b)

A saída é 0 seg, 1 ter, 2 qua, depois 1 seg e 2 ter e, por fim, 3 e 7. O enumerate numera a partir de 0, ou a partir do número dado como segundo argumento (o 1 do segundo laço). O terceiro laço mostra que o for pode separar um par em duas variáveis, a e b, a cada volta. O exemplo usa tuplas porque as listas, com todos os seus recursos, são tema de um artigo mais à frente da série.

FastTeacherPara professores

Da ementa ao semestre planejado

  • Plano de ensino e calendário montados sozinhos
  • Diário de aulas pronto para colar no SIGA
  • Slides e listas de exercícios com gabarito
Conhecer o FastTeacher

Versão Community grátis · Windows

Os padrões de sempre, agora com for

O acumulador, o contador e o máximo são os mesmos de qualquer laço. Com as leituras de um sensor guardadas numa tupla, o programa calcula a média, acha o maior valor e mostra cada posição:

leituras = (512, 530, 498, 505, 521)
soma = 0
for v in leituras:
    soma = soma + v
print("media", soma / len(leituras))
maior = leituras[0]
for v in leituras:
    if v > maior:
        maior = v
print("maior", maior)
for i in range(len(leituras)):
    print(i, leituras[i])

A saída é media 513.2, maior 530 e cinco linhas de 0 512 a 4 521. O leituras[0] pega o item de posição 0, o primeiro, e o leituras[i] pega o da posição i. As posições começam em 0, o que combina com o range(len(leituras)): ele vai de 0 até o último índice, 4. O padrão do máximo começa com o primeiro valor, e não com 0, porque assim ele funciona também quando todos os valores são negativos. Quando só o valor interessa, e não a posição, o primeiro estilo (for v in leituras) é mais claro e mais curto do que o range(len(...)).

Sair antes ou pular uma volta

Dois comandos mudam o ritmo do laço: o break sai dele de uma vez e o continue pula para a próxima volta.

for i in range(5):
    if i == 3:
        break
    print(i)
for i in range(5):
    if i % 2 == 0:
        continue
    print("impar", i)

A saída é 0, 1, 2, depois impar 1 e impar 3. No primeiro laço o break interrompe tudo quando i chega a 3, e o 3 não é impresso. No segundo, o continue abandona o resto do corpo quando i é par e vai para a volta seguinte, então só os ímpares são impressos. Os detalhes de break e continue ficam para o artigo dedicado a eles.

O que muda na ESP32

O for e o range são os mesmos do Python do computador. O uso mais comum em hardware é varrer uma faixa de valores, como o brilho de um LED com PWM:

from machine import Pin, PWM
import time
led = PWM(Pin(2), freq=1000)
for duty in range(0, 1024, 256):
    led.duty(duty)
    print("duty", duty)
    time.sleep_ms(100)
led.duty(0)
print("fim")

A saída é duty 0, duty 256, duty 512, duty 768 e fim. O range(0, 1024, 256) dá quatro degraus de brilho, e o time.sleep_ms segura cada um por um instante, para dar para ver a mudança. O artigo sobre PWM, LED, buzzer e servo explica o duty e a faixa de valores; aqui o que importa é que o passo do range ajusta a suavidade da transição.

O range() só aceita números inteiros. Para valores decimais, o jeito é calcular a partir do inteiro da volta, e não somar um passo decimal várias vezes:

for i in range(0, 11, 5):
    print(i / 10)
x = 0.0
for i in range(10):
    x = x + 0.1
print(x, x == 1.0)

A saída é 0.0, 0.5 e 1.0 na primeira parte, e 1.0000001 False na segunda. A divisão i / 10 parte de um inteiro exato e dá 0,5 sem erro. A soma de 0,1 dez vezes acumula o erro de arredondamento do float de 32 bits: o resultado fica em 1.0000001 e a comparação com 1 falha. No Python do computador, o float de 64 bits dá 0.9999999999999999, também diferente de 1. O for com range evita o problema do laço while com decimais, porque o número de voltas é fixo, mas o valor acumulado ainda carrega o erro.

Erros comuns e como reconhecê-los

Seis cartões em duas fileiras de três. range(1, 5) produz 1 2 3 4, porque o 5 não entra. range(5, 1) produz nada, porque falta o passo negativo. range(2.5) dá TypeError, porque range só aceita inteiros. range(1, 10, 0) dá ValueError, porque o passo não pode ser zero. print(range(3)) mostra range(0, 3), que não é uma lista. Mudar o i dentro do corpo não afeta a volta seguinte, porque o for pega o próximo valor do range. Uma faixa diz que as duas primeiras dão resultado errado sem avisar e as duas seguintes dão erro.
Seis armadilhas do for e do range e o que cada uma produz.

Os dois primeiros cartões da figura são erros de lógica que o Python não acusa. range(1, 5) entrega 1, 2, 3 e 4, e quem queria até 5 perde o último. range(5, 1) entrega nada, e o laço não roda, sem mensagem. Os dois seguintes dão erro de verdade:

for i in range(2.5):
    print(i)
Traceback (most recent call last):
  File "main.py", line 1, in <module>
TypeError: can't convert float to int

As mensagens do simulador (MicroPython) e do Python do computador diferem na redação:

ErroSimulador (MicroPython)Python no computador
range(2.5)TypeError: can't convert float to intTypeError: 'float' object cannot be interpreted as an integer
range(1, 10, 0)ValueError: zero stepValueError: range() arg 3 must not be zero
for i in 5:TypeError: 'int' object isn't iterableTypeError: 'int' object is not iterable
falta o : no forSyntaxError: invalid syntax (linha 1)SyntaxError: expected ':'
corpo sem recuoSyntaxError: invalid syntax (linha 2)IndentationError: expected an indented block after 'for' statement on line 1

"Iterable" quer dizer "algo que se pode percorrer", e um número solto, como o 5 do for i in 5:, não é. O que o aluno queria era range(5).

Em sala de aula: onde o for costuma tropeçar

Os casos abaixo se repetem nas turmas que acabaram de aprender o range.

O limite que não entra

É o erro número um. O exercício pede os números de 1 a 10 e o programa mostra de 1 a 9, porque o aluno escreveu range(1, 10). A frase que resolve: o primeiro número do range entra, o segundo não. Para ir até 10, a parada é 11.

Mudar o i dentro do laço

Alguns alunos acham que somar algo ao i dentro do corpo vai "pular" voltas. Não pula:

for i in range(3):
    print("antes", i)
    i = i + 10
    print("depois", i)

A saída é antes 0, depois 10, antes 1, depois 11, antes 2 e depois 12. O i muda dentro da volta, mas na volta seguinte o for pega o próximo valor do range e ignora a mudança. Para pular valores, o caminho é o passo do range; para um laço que muda o próprio contador, o while.

Esperar uma lista

O print(range(5)) mostra range(0, 5), e o aluno acha que algo quebrou. O list(range(5)) mostra os números.

Usar o for onde o while era necessário

Um programa que pede notas até o usuário digitar -1 não sabe quantas voltas dará, então o range não se aplica. A pergunta de decisão é: o número de voltas é conhecido antes de o laço começar?

O nome da variável que se repete

Em dois laços aninhados com a mesma variável (for i dentro de for i), o de dentro sobrescreve o de fora e o resultado confunde. Nomes diferentes, como i e j, ou nomes com sentido, como linha e coluna, evitam o problema. Quando a variável do laço não é usada no corpo, a convenção é chamá-la de _, como em for _ in range(3):, que repete três vezes sem precisar do número.

O recuo e os dois-pontos

Os erros de sintaxe do for são os mesmos do if e do while: dois-pontos esquecidos e corpo sem recuo. O simulador diz só invalid syntax e a linha. O artigo sobre if e else tem a lista de erros de recuo.

Exercício: tabela de temperaturas

Converter graus Celsius em Fahrenheit, de 0 a 100 de 25 em 25, com a fórmula F = C * 9 / 5 + 32. É um exercício de range com passo, e a tabela mostra o laço funcionando.

for c in range(0, 101, 25):
    f = c * 9 / 5 + 32
    print(c, "C =", f, "F")

A saída tem cinco linhas: 0 C = 32.0 F, 25 C = 77.0 F, 50 C = 122.0 F, 75 C = 167.0 F e 100 C = 212.0 F. O 101 é a parada que deixa o 100 entrar. A divisão com / devolve float, e por isso os resultados aparecem com .0.

Para uma versão interativa, a tabuada do número que a pessoa digitar usa o input() e o int() antes do laço:

n = int(input("Tabuada de: "))
for i in range(1, 11):
    print(n, "x", i, "=", n * i)

Com a entrada 5, a saída vai de 5 x 1 = 5 a 5 x 10 = 50. O int() é o do artigo sobre conversão de tipos, e o laço for só começa depois que o número foi lido.

Perguntas frequentes

O range pode começar em 1?

Pode: range(1, 11) vai de 1 a 10. Sem o primeiro argumento, o range começa em 0, e isso combina com o jeito de numerar posições que o Python usa.

O range aceita números negativos?

Aceita no início, na parada e no passo. range(-3, 3) vai de -3 a 2, e range(5, -1, -1) conta de 5 a 0.

Como faço um laço de 0 a 1 de 0,1 em 0,1?

Use range(0, 11) e divida cada valor por 10, como no exemplo do i / 10. O range só trabalha com inteiros.

Qual a diferença entre for i in range(len(x)) e for item in x?

O primeiro percorre as posições, e o segundo percorre os valores. Prefira o segundo quando a posição não for necessária.

O for pode ter else?

Pode, e o bloco do else roda quando o laço termina sem break. É assunto do artigo sobre break, continue e o else dos laços.

Para continuar

A trilha Lógica com Python tem os desafios de for e range. A Tabuada do 2 e a Soma de 1 a 10 são os mais diretos, os Pares de 1 a 10 e os Múltiplos de 5 pedem o passo e o limite com cuidado. Se o while ainda for a primeira ideia que vem à cabeça, releia o artigo O laço while.

O próximo assunto é o "faça-enquanto": como repetir um bloco que precisa rodar pelo menos uma vez, com while True e break, já que o Python não tem um comando próprio para isso.

Para praticar no PyPlaca

Trilhas

Lições

Fichas de componentes

FastTeacherPara professores

Da ementa ao semestre planejado

  • Plano de ensino e calendário montados sozinhos
  • Diário de aulas pronto para colar no SIGA
  • Slides e listas de exercícios com gabarito
Conhecer o FastTeacher

Versão Community grátis · Windows

FastMindAssistente de IA local

A IA que lembra da sua vida e mora no seu computador

  • Memória de longo prazo com a fonte de cada resposta
  • Funciona offline: seus dados ficam no seu PC
  • Lê PDFs, slides, fotos e gravações de reunião
Baixar grátis para Windows

Plano Essencial grátis para sempre

FastTeacherPara professores

Da ementa ao semestre planejado

  • Plano de ensino e calendário montados sozinhos
  • Diário de aulas pronto para colar no SIGA
  • Slides e listas de exercícios com gabarito
Conhecer o FastTeacher

Versão Community grátis · Windows