Módulo random do Python
Aprenda o módulo random do Python: gere números aleatórios, faça escolhas ponderadas, embaralhe sequências, use seed para reprodutibilidade e randomness criptográfica.
O módulo random integrado do Python gera números pseudoaleatórios e faz seleções aleatórias. Ele é baseado no algoritmo Mersenne Twister, que produz sequências pseudoaleatórias de alta qualidade adequadas para simulações, jogos, amostragem e testes — mas não para fins sensíveis à segurança, como geração de senhas ou chaves criptográficas. Este capítulo aborda:
- Geração de floats, inteiros e intervalos aleatórios
- Escolha de elementos aleatórios:
choice,choices,sample - Embaralhamento de sequências no local com
shuffle - Uso de seed para resultados reproduzíveis
- Distribuições contínuas:
uniform,gauss,triangular - Quando usar
secretsem vez derandom
Nenhuma instalação é necessária — import random é tudo que você precisa.
Importando o módulo
import randomTodos os exemplos abaixo assumem que esta importação está no escopo. Você também pode importar funções individuais para evitar o prefixo random., embora o prefixo deixe claro de onde cada função vem:
from random import randint, choice, shuffleGerando floats aleatórios
random()
random.random() retorna um float em [0.0, 1.0) — incluindo 0.0, mas nunca chegando a 1.0.
import random
print(random.random()) # e.g. 0.6394267984578837
print(random.random()) # e.g. 0.025010755222666936O valor muda a cada chamada porque o gerador avança seu estado interno.
uniform(a, b)
random.uniform(a, b) retorna um float N tal que a <= N <= b:
import random
random.seed(42)
print(random.uniform(1.5, 10.5)) # 7.254841186120954
print(random.uniform(-1.0, 1.0)) # e.g. -0.82 (some float in [-1, 1])Ao contrário de random(), uniform permite especificar ambos os extremos do intervalo, e o limite superior pode ser retornado.
Gerando inteiros aleatórios
randint(a, b)
random.randint(a, b) retorna um inteiro aleatório N tal que a <= N <= b. Ambos os extremos são inclusivos:
import random
random.seed(42)
die = random.randint(1, 6)
print(die) # 6Esta é a forma mais comum de simular lançamentos de dados, sorteios de cartas ou qualquer intervalo de inteiros discreto.
randrange(start, stop[, step])
random.randrange espelha o range() do Python — stop é exclusivo e você pode especificar um passo:
import random
random.seed(42)
# Pick an even number from 0 to 98 (0, 2, 4, ..., 98)
print(random.randrange(0, 100, 2)) # e.g. a random even integer
# Pick a multiple of 5 from 0 to 95
random.seed(42)
print(random.randrange(0, 100, 5)) # 15Quando você precisa de inteiros aleatórios de um intervalo que não começa em 0 ou precisa de um passo, randrange é mais expressivo que randint.
getrandbits(k)
random.getrandbits(k) retorna um inteiro não negativo aleatório com exatamente k bits aleatórios:
import random
random.seed(42)
print(random.getrandbits(8)) # 163 (an integer in 0..255)
print(random.getrandbits(16)) # an integer in 0..65535Isso é útil quando você precisa de inteiros aleatórios maiores do que os usados com randint, ou quando está trabalhando no nível de bits.
Escolhendo de sequências
choice(seq)
random.choice(seq) escolhe um elemento aleatoriamente de uma sequência não vazia. Funciona com listas, tuplas e strings:
import random
random.seed(42)
fruits = ['apple', 'banana', 'cherry']
print(random.choice(fruits)) # cherry
random.seed(42)
print(random.choice('ABCDE')) # A (picks one character)Se a sequência estiver vazia, um IndexError é lançado.
choices(population, weights=None, k=1)
random.choices escolhe k elementos com substituição (o mesmo elemento pode aparecer mais de uma vez). Você pode influenciar a seleção com weights:
import random
colors = ['red', 'blue', 'green']
# Equal probability — each run may differ
print(random.choices(colors, k=3))
# e.g. ['blue', 'red', 'red']
# Weighted: green is 3× more likely than red, blue is 2×
random.seed(42)
print(random.choices(colors, weights=[1, 2, 3], k=4))
# ['green', 'red', 'blue', 'blue']choices sempre retorna uma lista, mesmo quando k=1. O argumento weights é relativo — [1, 2, 3] dá a mesma distribuição que [10, 20, 30].
sample(population, k)
random.sample escolhe k elementos sem substituição — cada elemento pode aparecer apenas uma vez no resultado. Ele não modifica a sequência original:
import random
random.seed(42)
# Pick 4 unique numbers from 0-9
print(random.sample(range(10), 4)) # [1, 0, 4, 9]
# Simulate a lottery: 6 unique numbers from 1-49
random.seed(7)
ticket = sorted(random.sample(range(1, 50), 6))
print(ticket) # [4, 5, 10, 21, 26, 42]Se k for maior que o tamanho da população, random.sample lança um ValueError:
import random
try:
random.sample([1, 2, 3], 5)
except ValueError as e:
print(e) # Sample larger than population or is negativechoices vs sample em resumo:
choices | sample | |
|---|---|---|
| Substituição | Sim | Não |
| Resultados duplicados | Possível | Nunca |
| Modifica o original | Não | Não |
| Suporta pesos | Sim | Não (use choices) |
Embaralhando sequências
random.shuffle(seq) embaralha a lista no local e retorna None. A lista original é modificada:
import random
random.seed(42)
deck = [1, 2, 3, 4, 5]
random.shuffle(deck)
print(deck) # [4, 2, 3, 5, 1] (original list is modified)Se você precisar de uma cópia embaralhada sem alterar o original, use random.sample:
import random
random.seed(42)
original = [1, 2, 3, 4, 5]
shuffled = random.sample(original, len(original))
print(original) # [1, 2, 3, 4, 5] (unchanged)
print(shuffled) # [4, 2, 3, 5, 1]Usando seed para resultados reproduzíveis
Por padrão, o módulo random inicializa sua seed a partir do tempo do sistema (ou os.urandom()), então cada execução produz valores diferentes. Chamar random.seed() com um valor fixo bloqueia a sequência para que você obtenha saída idêntica toda vez — essencial para depuração, testes unitários e simulações reproduzíveis:
import random
random.seed(42)
print(random.random()) # 0.6394267984578837
print(random.randint(1, 10)) # 1
print(random.choice(['a', 'b', 'c'])) # c
# Reset to the same seed — identical sequence
random.seed(42)
print(random.random()) # 0.6394267984578837 (same as before)
print(random.randint(1, 10)) # 1
print(random.choice(['a', 'b', 'c'])) # crandom.seed() aceita um inteiro, uma string, um float, bytes ou None (que reinicializa a partir do sistema). A seed é uma operação global — afeta todas as chamadas subsequentes no mesmo programa, portanto, defina a seed uma vez no início de um bloco reproduzível.
Gerando dados de teste reproduzíveis
import random
random.seed(999)
test_scores = [round(random.uniform(0, 100), 2) for _ in range(5)]
print(test_scores) # [78.13, 8.01, 87.25, 57.38, 49.06]Cada execução com seed(999) produz exatamente a mesma lista, tornando isso útil para testes unitários que verificam valores específicos.
Distribuições contínuas
O módulo random inclui várias distribuições de probabilidade contínuas, úteis em simulações e modelagem estatística.
uniform(a, b)
Já abordado acima — uma distribuição plana onde cada valor em [a, b] é igualmente provável.
triangular(low, high, mode)
Retorna um float de uma distribuição triangular onde mode é o valor mais comum:
import random
random.seed(42)
# Most values cluster near 5, between 0 and 10
t = random.triangular(0, 10, 5)
print(t) # 5.753983033817951Útil quando você conhece o valor mínimo, máximo e mais provável, mas não a distribuição exata — comum em estimativas de projetos e modelagem de risco.
gauss(mu, sigma)
Retorna um float de uma distribuição Gaussiana (normal) com média mu e desvio padrão sigma:
import random
random.seed(42)
# Heights in cm: mean 170, std 10
heights = [round(random.gauss(170, 10), 1) for _ in range(5)]
print(heights) # [168.6, 168.3, 168.9, 177.0, 168.7]random.normalvariate(mu, sigma) é equivalente, mas seguro para threads; use normalvariate em programas com múltiplas threads.
expovariate(lambd)
Retorna um float de uma distribuição exponencial, onde lambd é 1 / média. Útil para modelar o tempo entre eventos (por exemplo, chegadas de clientes, pacotes de rede):
import random
random.seed(42)
# Mean inter-arrival time = 5 minutes; lambd = 1/5
wait = random.expovariate(1 / 5)
print(round(wait, 2)) # 5.1 (minutes until next arrival)Exemplos práticos
Simulando 60 lançamentos de dados
import random
random.seed(42)
counts = {face: 0 for face in range(1, 7)}
for _ in range(60):
counts[random.randint(1, 6)] += 1
print(counts)
# {1: 15, 2: 10, 3: 8, 4: 7, 5: 10, 6: 10}Com mais lançamentos, a distribuição se aproxima da probabilidade teórica de 1/6 para cada face.
Escolhendo um time aleatório
import random
random.seed(42)
players = ['Alice', 'Bob', 'Carol', 'Dave', 'Eve', 'Frank']
random.shuffle(players)
team_a = players[:3]
team_b = players[3:]
print('Team A:', team_a)
print('Team B:', team_b)Senha aleatória simples
Para contextos não relacionados à segurança (demonstrações, tokens descartáveis), random.choices funciona bem:
import random
import string
random.seed(42)
chars = string.ascii_letters + string.digits
password = ''.join(random.choices(chars, k=12))
print(password) # NbrnTP3fAbnFPara senhas ou tokens de usuário reais, use o módulo secrets (veja abaixo).
Quando usar secrets em vez de random
O módulo random não é criptograficamente seguro. Um invasor que observe saída suficiente pode prever valores futuros. Para qualquer coisa sensível à segurança, use o módulo secrets (Python 3.6+), que obtém dados da fonte aleatória criptográfica do sistema operacional:
import secrets
# Cryptographically secure random integer in [0, 100)
print(secrets.randbelow(100))
# Secure random token for a password-reset link (URL-safe base64)
token = secrets.token_urlsafe(32)
print(token) # e.g. 'gIg9XzExxFkHLAH9JCK8Zxb1aBEFZ...'
# Secure random hex string for an API key
api_key = secrets.token_hex(16)
print(api_key) # e.g. 'a3f1c2d4e5b6...'Regra geral: se você estiver gerando tokens, IDs de sessão, senhas ou qualquer valor que um adversário não deve ser capaz de adivinhar, use secrets. Use random para todo o resto (jogos, simulações, dados de teste, amostragem).
Referência rápida
| Função | Descrição | Retorna |
|---|---|---|
random.random() | Float em [0.0, 1.0) | float |
random.uniform(a, b) | Float em [a, b] | float |
random.randint(a, b) | Inteiro em [a, b] (ambos inclusivos) | int |
random.randrange(start, stop[, step]) | Inteiro de range(start, stop, step) | int |
random.getrandbits(k) | Inteiro não negativo com k bits aleatórios | int |
random.choice(seq) | Um elemento aleatório | tipo do elemento |
random.choices(pop, weights, k) | k elementos com substituição | list |
random.sample(pop, k) | k elementos sem substituição | list |
random.shuffle(seq) | Embaralha lista no local | None |
random.seed(a) | Define a seed aleatória | None |
random.gauss(mu, sigma) | Variante Gaussiana (normal) | float |
random.normalvariate(mu, sigma) | Variante normal (seguro para threads) | float |
random.triangular(low, high, mode) | Variante de distribuição triangular | float |
random.expovariate(lambd) | Variante de distribuição exponencial | float |
Capítulos relacionados
- Python Math — funções e constantes matemáticas
- Python Modules — como importar e organizar módulos
- Python Numbers — tipos inteiro, float e complexo
- Python Lists — trabalhando com sequências ordenadas
- Python For Loops — iteração para gerar dados aleatórios
- Python Try Except — tratamento de erros como
ValueErrordosample