Range: gerando sequências numéricas

1. Introdução à função range()

A função range() é uma das ferramentas mais fundamentais e versáteis do Python para geração de sequências numéricas. Ela produz uma sequência imutável de números inteiros, sendo amplamente utilizada em loops for e em situações onde precisamos iterar um número específico de vezes.

Diferentemente de listas explícitas como [0, 1, 2, 3], o range() não armazena todos os valores na memória de uma só vez. Em vez disso, ele gera cada número sob demanda, tornando-o extremamente eficiente para trabalhar com sequências grandes.

A função aceita até três parâmetros:
- start: valor inicial da sequência (padrão é 0)
- stop: valor limite (exclusivo, ou seja, a sequência para antes deste valor)
- step: incremento entre os valores (padrão é 1)

2. Sintaxe básica do range()

range(stop): sequência de 0 até n-1

A forma mais simples do range() recebe apenas um argumento:

# Gera números de 0 a 4
for i in range(5):
    print(i, end=' ')
# Saída: 0 1 2 3 4

range(start, stop): sequência personalizada

Com dois argumentos, definimos o início e o fim da sequência:

# Gera números de 3 a 7
for i in range(3, 8):
    print(i, end=' ')
# Saída: 3 4 5 6 7

range(start, stop, step): controle do incremento

O terceiro argumento permite controlar o passo entre os números:

# Gera números pares de 0 a 10
for i in range(0, 11, 2):
    print(i, end=' ')
# Saída: 0 2 4 6 8 10

3. Tipos de sequências geradas

Sequências crescentes (step positivo)

# Múltiplos de 5 entre 0 e 50
multiplos_5 = list(range(0, 51, 5))
print(multiplos_5)
# Saída: [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50]

Sequências decrescentes (step negativo)

# Contagem regressiva de 10 a 0
for i in range(10, -1, -1):
    print(i, end=' ')
# Saída: 10 9 8 7 6 5 4 3 2 1 0

Exemplos com números pares, ímpares e múltiplos

# Números ímpares de 1 a 20
impares = list(range(1, 21, 2))
print(f"Ímpares: {impares}")

# Múltiplos de 3 até 30
multiplos_3 = list(range(0, 31, 3))
print(f"Múltiplos de 3: {multiplos_3}")

4. Iterando com range() em loops for

Uso clássico com for i in range()

# Repetindo uma ação 5 vezes
for i in range(5):
    print(f"Iteração {i + 1}: Olá, mundo!")

Percorrendo índices de listas com range(len())

frutas = ['maçã', 'banana', 'laranja', 'uva']
for i in range(len(frutas)):
    print(f"Índice {i}: {frutas[i]}")

Combinando range() com enumerate()

# Usando enumerate para acesso mais elegante
frutas = ['maçã', 'banana', 'laranja', 'uva']
for indice, fruta in enumerate(frutas):
    print(f"Posição {indice}: {fruta}")

5. Convertendo range() para outras estruturas

Convertendo para lista com list(range())

# Criando uma lista a partir de range
numeros = list(range(10))
print(numeros)
# Saída: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Convertendo para tupla com tuple(range())

# Criando uma tupla a partir de range
pares = tuple(range(0, 20, 2))
print(pares)
# Saída: (0, 2, 4, 6, 8, 10, 12, 14, 16, 18)

Diferenças de memória entre range() e listas

import sys

# Comparando uso de memória
range_obj = range(1000000)
lista_obj = list(range(1000000))

print(f"Memória do range: {sys.getsizeof(range_obj)} bytes")
print(f"Memória da lista: {sys.getsizeof(lista_obj)} bytes")

# Saída típica:
# Memória do range: 48 bytes
# Memória da lista: 8000056 bytes

6. Operações comuns com range()

Verificando pertencimento com in e not in

numeros = range(10, 21)

print(15 in numeros)   # True
print(25 in numeros)   # False
print(5 not in numeros) # True

Fatiamento de objetos range

# Fatiamento de range (Python 3.3+)
r = range(0, 100, 5)
print(list(r[2:7]))  # [10, 15, 20, 25, 30]
print(list(r[:5]))   # [0, 5, 10, 15, 20]
print(list(r[::-1])) # Sequência reversa

Comparação entre objetos range

# Comparando objetos range
r1 = range(0, 10, 2)
r2 = range(0, 10, 2)
r3 = range(0, 10, 3)

print(r1 == r2)  # True (mesma sequência)
print(r1 == r3)  # False (sequências diferentes)

7. Casos especiais e armadilhas

range() com argumentos negativos

# Cuidado com step negativo
print(list(range(10, 0)))     # [] - sequência vazia!
print(list(range(10, 0, -1))) # [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

range() vazio: quando start >= stop (step positivo)

# Sequências vazias
print(list(range(5, 3)))       # [] - start > stop
print(list(range(5, 5)))       # [] - start == stop
print(list(range(0, -5)))      # [] - start > stop com negativos

Erros comuns: esquecer que stop é exclusivo

# Erro comum: achar que range(5) inclui o 5
print(list(range(5)))  # [0, 1, 2, 3, 4] - não inclui o 5!

# Correto seria range(6) para incluir o 5
print(list(range(6)))  # [0, 1, 2, 3, 4, 5]

8. Aplicações práticas do range()

Gerando índices para loops aninhados

# Criando uma matriz 3x3
matriz = []
for i in range(3):
    linha = []
    for j in range(3):
        linha.append(i * 3 + j + 1)
    matriz.append(linha)

for linha in matriz:
    print(linha)
# Saída:
# [1, 2, 3]
# [4, 5, 6]
# [7, 8, 9]

Criando sequências para testes e simulações

# Simulando dados de temperatura
temperaturas = [20 + i * 0.5 for i in range(24)]
print(f"Temperaturas das 24 horas: {temperaturas[:5]}...")

# Gerando horários
horarios = [f"{h:02d}:00" for h in range(24)]
print(f"Horários: {horarios}")

Exemplo: tabuada com range() e formatação

# Tabuada do 7
numero = 7
print(f"Tabuada do {numero}:")
for i in range(1, 11):
    resultado = numero * i
    print(f"{numero} x {i:2d} = {resultado:3d}")

Referências