Python range()

Na aula for, você viu que o for percorre sequências: as letras de um texto, os itens de uma lista. Mas e para contar de 1 até 100? Escrever uma lista com cem números à mão não tem graça. Para isso existe a função range() (em inglês, "faixa", "intervalo"): ela fabrica uma sequência de números para o for percorrer. Você diz onde começa, onde termina e de quanto em quanto pular.

Você vai aprender
  • As três formas do range(): com o fim; com o início e o fim; com início, fim e passo.
  • A regra que mais confunde: o fim não entra. E por que ela é assim.
  • A contar de 5 em 5, só os pares, e para trás, com passo negativo.
  • A ver os números de um range com list(range(…)).
  • A repetir algo N vezes, inclusive um N digitado pelo usuário.
  • Os erros reais: passo zero, número com vírgula, o texto do input() e o range vazio que não avisa nada.

Todos os programas desta aula rodaram no Python 3.14 da máquina da Ana (usuária ana, computador notebook), com python3 arquivo.py; as linhas com >>> foram digitadas no modo interativo.


A ideia: as senhas da padaria

A padaria do bairro tem uma máquina de senhas. Às 7 horas, o funcionário anota no quadro: "hoje de manhã, as senhas vão da 1 até antes da 6". Saem as senhas 1, 2, 3, 4 e 5. A 6 é a primeira que não é atendida de manhã: ela marca onde a faixa para.

O range() funciona exatamente assim. Você dá a ele:

  • o início: o primeiro número que entra;
  • o fim: o número onde a faixa para, que não entra;
  • o passo (opcional): de quanto em quanto pular.

1. range(fim): só o fim

Com um número só, o range começa do zero e para antes do número dado:

for numero in range(5):
    print(numero)
$ python3 range5.py
0
1
2
3
4

Cinco números, de 0 a 4. O 5 não aparece. Pode parecer estranho, mas tem uma vantagem: range(5) dá exatamente 5 voltas. Quer repetir algo 10 vezes? range(10). O número que você escreve é a quantidade de voltas.

Começar do zero também não é capricho: no Python, as posições de um texto e de uma lista começam do 0 (lembra dos índices?). O range(5) dá justamente as posições de algo com 5 itens: 0, 1, 2, 3 e 4.


2. range(início, fim): escolhendo onde começa

Para começar de outro número, ponha o início antes do fim, separados por vírgula. As senhas da padaria:

for senha in range(1, 6):
    print(f"Senha {senha}, por favor!")
$ python3 senhas.py
Senha 1, por favor!
Senha 2, por favor!
Senha 3, por favor!
Senha 4, por favor!
Senha 5, por favor!
range
A função que fabrica a sequência de números.
1
O início: o primeiro número, que entra.
,
A vírgula separa os valores (os argumentos) que você passa à função.
6
O fim: onde a sequência para. O 6 não entra; o último número é o 5.
Um truque para não errar

Para ir de A até B, incluindo o B, escreva range(A, B + 1). De 1 a 10: range(1, 11). De 1 a 100: range(1, 101). E range(A, B) sempre tem B − A números: range(1, 6) tem 6 − 1 = 5.

Somando de 1 a 100

Na aula while, somar uma sequência pedia contador, condição e passo. Com for e range, o laço fica assim:

soma = 0
for numero in range(1, 101):
    soma += numero
print(f"1 + 2 + ... + 100 = {soma}")
$ python3 soma100.py
1 + 2 + ... + 100 = 5050

O range(1, 101) entrega os números de 1 a 100, um por volta, e o acumulador soma vai juntando.


3. range(início, fim, passo): pulando de tanto em tanto

O terceiro número é o passo: de quanto em quanto a sequência anda. Sem ele, o passo é 1. A Ana põe um bolo no forno por meia hora e quer conferir de 5 em 5 minutos:

for minuto in range(0, 31, 5):
    print(f"{minuto} minutos")
$ python3 cinco_em_cinco.py
0 minutos
5 minutos
10 minutos
15 minutos
20 minutos
25 minutos
30 minutos

Começa no 0 e soma 5 a cada volta: 0, 5, 10… até 30. O próximo seria 35, que já passa do fim (31); aí a sequência para. Repare que o fim é 31, e não 30: com range(0, 30, 5), o 30 ficaria de fora.

Com passo 2, começando de um número par, saem só os pares:

for numero in range(2, 11, 2):
    print(numero, end=" ")
print()
$ python3 pares.py
2 4 6 8 10 

Missão: mostre os múltiplos de 3, de 3 até 30 (incluindo o 30), um por linha. Mude só os números do range: o início, o fim e o passo.

for numero in range(1, 11):
    print(numero)
for numero in range(3, 31, 3):
    print(numero)

4. Contar para trás: passo negativo

Com um passo negativo, a sequência anda para trás. Aí o início é o número maior, e o fim, o menor:

for segundo in range(5, 0, -1):
    print(f"{segundo}...")
print("Já!")
$ python3 regressiva_range.py
5...
4...
3...
2...
1...
Já!

A regra do fim continua valendo: o 0 é onde a contagem para, e ele não entra. Para incluir o zero, o fim teria de ser -1: range(5, -1, -1).

Missão: é réveillon. Faça a contagem regressiva de 10 até 1, um número por linha, e depois o Feliz Ano Novo!.

for numero in range(1, 11):
    print(numero)
print("Feliz Ano Novo!")
for numero in range(10, 0, -1):
    print(numero)
print("Feliz Ano Novo!")

5. Vendo os números: list(range(…))

Se você mostrar um range direto, o Python não lista os números; ele mostra só a "receita":

>>> range(5)
range(0, 5)

Isso acontece porque o range não guarda os números: ele calcula cada um na hora em que o for pede. É por isso que até um range(1000000) ocupa quase nada na memória. Para ver a sequência inteira, transforme-a numa lista com list():

>>> list(range(5))
[0, 1, 2, 3, 4]
>>> list(range(1, 6))
[1, 2, 3, 4, 5]
>>> list(range(0, 21, 5))
[0, 5, 10, 15, 20]
>>> list(range(5, 0, -1))
[5, 4, 3, 2, 1]
>>> list(range(5, 0))
[]
>>> len(range(1, 6))
5
>>> sum(range(1, 101))
5050

Essa é a melhor forma de tirar dúvida sobre um range: antes de pôr no for, olhe os números com list(). Repare em três linhas:

  • list(range(5, 0)) deu [], uma lista vazia: de 5 até 0 andando de 1 em 1 para frente, não há número nenhum. Para trás, só com passo negativo.
  • len(range(1, 6)) diz quantos números há, sem precisar listá-los: 5.
  • sum(range(1, 101)) soma a sequência inteira de uma vez: o mesmo 5050 do laço da seção 2. A função sum() ("soma") tem mais detalhes em Funções Embutidas.

Experimente: mude os números e rode para ver a sequência. Tente prever o resultado antes: range(10), range(3, 8), range(1, 20, 4), range(10, 0, -3), range(8, 3).

print(list(range(2, 15, 3)))

6. Repetir N vezes

Muitas vezes você nem precisa do número: só quer repetir. Quando a variável do laço não vai ser usada, o costume é chamá-la de _ (um sublinhado sozinho), que quer dizer "não interessa":

for _ in range(3):
    print("Hip, hip, hurra!")
$ python3 hurra.py
Hip, hip, hurra!
Hip, hip, hurra!
Hip, hip, hurra!

E a quantidade pode vir do usuário. Como o input() devolve texto, converta com int() antes de passar ao range (aula Conversão de Tipos):

vezes = int(input("Quantas vezes? "))
for volta in range(vezes):
    print(f"Volta {volta + 1} de {vezes}")
$ python3 quantas.py
Quantas vezes? 3
Volta 1 de 3
Volta 2 de 3
Volta 3 de 3

O range(3) deu 0, 1 e 2; o volta + 1 mostra 1, 2 e 3, que é como as pessoas contam.


Formas diferentes de fazer a mesma coisa

Contar de 1 a 5 tem várias escritas. Todas dão 1 2 3 4 5:

FormaQuando usar
for n in range(1, 6):A mais comum: diga onde começa e onde para (o fim é 6 para incluir o 5)
for n in range(5): e usar n + 1Quando o importante é "5 voltas" e o número da volta é só para mostrar
n = 1 / while n <= 5: / n += 1Funciona, mas tem mais peças para errar; deixe o while para quando não se sabe quantas voltas vão ser
for n in [1, 2, 3, 4, 5]:Só para poucos números escolhidos à mão (ex.: [2, 3, 5, 7]); para faixas, use range

E para percorrer uma lista com o número da posição, dá para combinar range e len:

compras = ["pão", "leite", "café"]
for posicao in range(len(compras)):
    print(f"{posicao + 1}. {compras[posicao]}")
$ python3 indice.py
1. pão
2. leite
3. café

Funciona: len(compras) é 3, e range(3) dá as posições 0, 1 e 2. Mas o Python tem uma ferramenta feita para isso, mais clara, o enumerate(), que você vai ver em enumerate() e zip().


Quando dá errado

Queria ir até 10 e parou no 9
for numero in range(1, 10):
    print(numero, end=" ")
print()
$ python3 ate10.py
1 2 3 4 5 6 7 8 9 

Sem mensagem de erro: o Python fez exatamente o que foi pedido. O fim não entra, então range(1, 10) para no 9. É o erro mais comum com range, tão comum que tem nome: erro "por um" (em inglês, off-by-one). Como consertar: fim = último número + 1: range(1, 11).

Contagem para trás sem o passo negativo
for segundo in range(5, 0):
    print(f"{segundo}...")
print("Já!")
$ python3 vazio.py
Já!

Nenhum número, nenhum erro: o laço deu zero voltas. Sem o terceiro número, o passo é +1, e não existe caminho de 5 até 0 andando para frente. O range ficou vazio (list(range(5, 0)) é []). Como consertar: range(5, 0, -1).

Passo zero
for numero in range(1, 10, 0):
    print(numero)
$ python3 passo0.py
Traceback (most recent call last):
  File "/home/ana/passo0.py", line 1, in <module>
    for numero in range(1, 10, 0):
                  ~~~~~^^^^^^^^^^
ValueError: range() arg 3 must not be zero

"Erro de valor: o argumento 3 do range() não pode ser zero". Com passo zero, a sequência nunca sairia do 1; em vez de criar um laço infinito, o Python recusa. Os ~~~~~^^^^^^^^^^ marcam a chamada do range na linha 1. Como consertar: use um passo diferente de zero (1, 2, −1…).

Número com casas decimais
for valor in range(0, 1, 0.1):
    print(valor)
$ python3 decimal.py
Traceback (most recent call last):
  File "/home/ana/decimal.py", line 1, in <module>
    for valor in range(0, 1, 0.1):
                 ~~~~~^^^^^^^^^^^
TypeError: 'float' object cannot be interpreted as an integer

"Erro de tipo: um objeto float (número com casas decimais) não pode ser interpretado como inteiro". O range só trabalha com números inteiros: início, fim e passo. Como consertar: conte com inteiros e divida dentro do laço. Para ir de 0.0 a 0.9 de 0.1 em 0.1: for n in range(10): e use n / 10.

Passou o texto do input() direto
vezes = input("Quantas vezes? ")
for volta in range(vezes):
    print("Oi!")
$ python3 texto.py
Quantas vezes? 3
Traceback (most recent call last):
  File "/home/ana/texto.py", line 2, in <module>
    for volta in range(vezes):
                 ~~~~~^^^^^^^
TypeError: 'str' object cannot be interpreted as an integer

A mesma família do erro anterior, agora com str (texto): o input() devolveu o texto '3', e o range quer um número inteiro. Como consertar: vezes = int(input("Quantas vezes? ")).


Referência rápida

EscritaNúmerosO que faz
range(5)0, 1, 2, 3, 4Do 0 até antes do fim; dá exatamente 5 voltas
range(1, 6)1, 2, 3, 4, 5Do início até antes do fim
range(0, 31, 5)0, 5, 10, …, 30De 5 em 5
range(2, 11, 2)2, 4, 6, 8, 10Os pares de 2 a 10
range(5, 0, -1)5, 4, 3, 2, 1Para trás: passo negativo, início maior que o fim
range(5, 0)(nenhum)Vazio: para frente não há caminho de 5 a 0
list(range(…))—Mostra os números como uma lista
len(range(…)) / sum(range(…))—Quantos números há / a soma deles
for _ in range(n):—Repetir n vezes sem usar o número
SintomaCausa provável
Faltou o último númeroO fim não entra: use fim = último + 1
O laço não roda nenhuma vez, sem erroInício maior que o fim sem passo negativo (ou o contrário)
ValueError: range() arg 3 must not be zeroPasso zero
TypeError: 'float' object cannot be interpreted as an integerNúmero com casas decimais no range
TypeError: 'str' object cannot be interpreted as an integerTexto (do input()) no range: faltou o int()

Exercícios

1. De 1 a 10

Complete para o laço passar pelos números de 1 a 10, incluindo o 10:

for numero in range(1, ):

2. O último número

Qual é o último número de range(0, 20, 4)?

O último é .

3. Quantos números?

Quantos números tem range(3, 10)?

Tem números.

4. O que list(range(4)) mostra?

5. Qual range faz a contagem 3, 2, 1?

6. for i in range(10, 1): não mostrou nada e não deu erro. Por quê?

Missão final: a soma dos pares

Missão: some todos os números pares de 1 a 100 (2 + 4 + 6 + … + 100). Escreva um for com um range de passo 2 no lugar do comentário, juntando cada número no total.

total = 0
# escreva o for aqui

print(f"Soma dos pares de 1 a 100: {total}")
total = 0
for numero in range(2, 101, 2):
    total += numero
print(f"Soma dos pares de 1 a 100: {total}")

No lab, saiu Soma dos pares de 1 a 100: 2550. Para conferir de outro jeito, rode print(sum(range(2, 101, 2))).


Resumo

  • range() fabrica uma sequência de números inteiros para o for percorrer.
  • range(fim) começa do 0; range(início, fim) começa do início; range(início, fim, passo) pula de passo em passo.
  • O fim nunca entra. Para incluir o B, use range(A, B + 1). range(n) dá exatamente n voltas.
  • Para trás, passo negativo e início maior: range(5, 0, -1). Sem o passo negativo, o range fica vazio, sem aviso.
  • list(range(…)) mostra os números; use para tirar dúvida antes de pôr no for.
  • Só inteiros: passo zero dá ValueError; float ou texto dão TypeError (converta o input() com int()).