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
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.
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
Plano Essencial grátis para sempre
A função range()
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 depassoempasso.range(0, 10, 3)dá 0, 3, 6, 9, erange(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.
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
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
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 intAs mensagens do simulador (MicroPython) e do Python do computador diferem na redação:
| Erro | Simulador (MicroPython) | Python no computador |
|---|---|---|
range(2.5) | TypeError: can't convert float to int | TypeError: 'float' object cannot be interpreted as an integer |
range(1, 10, 0) | ValueError: zero step | ValueError: range() arg 3 must not be zero |
for i in 5: | TypeError: 'int' object isn't iterable | TypeError: 'int' object is not iterable |
falta o : no for | SyntaxError: invalid syntax (linha 1) | SyntaxError: expected ':' |
| corpo sem recuo | SyntaxError: 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.