Python random
Jogar um dado, tirar um nome do chapéu para o amigo secreto, embaralhar a ordem das apresentações da turma, dar um palpite na Mega-Sena. Tudo isso é sorteio, e o módulo random ("aleatório") faz todos eles. É ele que vai dar vida aos jogos do guia, como o Jogo de Adivinhação e o Jogo da Forca.
- A sortear números inteiros com
randint(e por que o fim entra no sorteio). - Os outros sorteios de números:
random,uniform,randrange. - A sortear itens de uma lista:
choice,choices(até com pesos) esample. - A embaralhar uma lista com
shuffle, que muda a própria lista e devolveNone. - A repetir exatamente o mesmo sorteio com
random.seed. - Por que o
randomnão serve para senhas, e o módulosecrets. - Os erros reais: lista vazia, amostra maior que a lista,
shufflenum texto, e oseedno lugar errado.
A ideia: o globo do bingo
No bingo da quermesse, as bolinhas giram no globo e sai uma de cada vez, sem ninguém escolher. O módulo random é esse globo: você diz quais são as bolinhas (os números de 1 a 75, os nomes da turma, as frutas da feira), e ele tira uma, ou várias, ou embaralha todas.
Uma diferença importante para esta aula: como o resultado é sorteado, a saída muda a cada execução. Os números que aparecem nos exemplos abaixo foram os que saíram no computador da Ana; quando você rodar, os seus vão ser outros. Isso não é erro. (A seção 5 mostra como fazer o sorteio se repetir quando você precisar.)
1. Um número inteiro: randint
import random
print("O dado deu:", random.randint(1, 6))
$ python3 dado.py O dado deu: 2 $ python3 dado.py O dado deu: 1 $ python3 dado.py O dado deu: 2
- import random
- Traz o módulo de sorteios.
- random.randint(1, 6)
- Sorteia um número inteiro (random integer, "inteiro aleatório") de 1 a 6, incluindo o 1 e o 6. Cada um tem a mesma chance.
Três jogadas, três execuções, e o 2 saiu duas vezes: num dado de verdade também acontece. Repare no detalhe que mais confunde quem já conhece o range: no range(1, 6), o 6 fica de fora; no randint(1, 6), o 6 entra. As duas pontas fazem parte do sorteio.
Missão: nos jogos de tabuleiro de aventura, usa-se um dado de 20 lados. Mude o programa para sortear de 1 a 20 e ajuste a frase. (Rode várias vezes: o número muda, e tudo bem. A missão confere que ele está entre 1 e 20.)
import random
print("Dado de 6 lados:", random.randint(1, 6))
import random
print("Dado de 20 lados:", random.randint(1, 20))
2. Outros números: random, uniform, randrange
import random print(random.random()) print(random.uniform(1.5, 2.5)) print(random.randint(1, 10)) print(random.randrange(0, 100, 5))
$ python3 numeros.py 0.5203349410522208 2.444173566535794 2 65 $ python3 numeros.py 0.9415966565976439 2.4721534510169167 4 15
| Função | Sorteia | Exemplo de uso |
|---|---|---|
random.random() | Um float de 0 até 1 (o 0 pode sair, o 1 nunca) | Uma chance: if random.random() < 0.3: acontece 30% das vezes |
random.uniform(a, b) | Um float entre a e b | Uma altura entre 1,5 e 2,5 metros |
random.randint(a, b) | Um int de a até b, com o b | O dado: randint(1, 6) |
random.randrange(a, b, passo) | Um int do range(a, b, passo), sem o b | Um múltiplo de 5 menor que 100: randrange(0, 100, 5) |
O randrange segue as regras do range: o fim fica de fora e dá para escolher o passo. randrange(0, 100, 5) sorteia um entre 0, 5, 10, …, 95.
3. Itens de uma lista: choice, choices, sample
import random
frutas = ["maçã", "banana", "uva", "manga", "caju"]
print("Uma fruta:", random.choice(frutas))
print("Três, podendo repetir:", random.choices(frutas, k=3))
print("Duas, sem repetir:", random.sample(frutas, 2))
print("A lista continua igual:", frutas)
$ python3 escolher.py Uma fruta: maçã Três, podendo repetir: ['maçã', 'maçã', 'caju'] Duas, sem repetir: ['banana', 'uva'] A lista continua igual: ['maçã', 'banana', 'uva', 'manga', 'caju']
- random.choice(frutas)
- "Escolha" (choice) um item. Funciona com qualquer sequência: lista, tupla, texto (
random.choice("aeiou")sorteia uma vogal). - random.choices(frutas, k=3)
- Escolhe vários, um de cada vez, devolvendo a bolinha ao globo depois de cada um: o mesmo item pode sair de novo (saíram duas maçãs). O
ké quantos. - random.sample(frutas, 2)
- Uma "amostra" (sample) de 2 itens diferentes: a bolinha que saiu fica fora do globo. É o sorteio de quem ganha os prêmios de uma rifa: a mesma pessoa não ganha duas vezes.
Nenhum dos três muda a lista original. A Mega-Sena é um sample: 6 dezenas diferentes, de 1 a 60.
import random
dezenas = random.sample(range(1, 61), 6)
print("Palpite:", sorted(dezenas))
$ python3 mega.py Palpite: [16, 17, 30, 33, 55, 60]
O range(1, 61) são as bolinhas de 1 a 60 (o 61 fica de fora), e o sorted só arruma o palpite em ordem para ler.
Sorteio com pesos
Na roleta da quermesse, nem todo prêmio tem a mesma chance. O choices aceita weights ("pesos"): quanto maior o peso, mais fácil sair.
import random
premios = ["bala", "pirulito", "chocolate", "bicicleta"]
chances = [60, 30, 9, 1]
sorteados = random.choices(premios, weights=chances, k=20)
for premio in premios:
print(f"{premio}: {sorteados.count(premio)}")
$ python3 pesos.py bala: 10 pirulito: 7 chocolate: 3 bicicleta: 0
Em 20 giros, a bala saiu metade das vezes e a bicicleta, nenhuma: com peso 1 em 100, ela é rara. Os pesos não precisam somar 100; o que conta é a proporção entre eles.
4. Embaralhando: shuffle
import random
fila = ["Ana", "Bia", "Caio", "Duda", "Enzo"]
random.shuffle(fila)
print("Ordem de apresentação:", fila)
$ python3 embaralhar.py Ordem de apresentação: ['Caio', 'Enzo', 'Bia', 'Duda', 'Ana']
- random.shuffle(fila)
- "Embaralha" (shuffle) a própria lista, como embaralhar um baralho: depois dessa linha, a variável
filaestá em outra ordem. Ele não cria uma lista nova e não devolve nada (devolveNone).
shuffle não devolve a lista
Escrever fila = random.shuffle(fila) é um erro muito comum: o shuffle embaralha a lista e devolve None, e a variável passa a guardar None (veja em Quando dá errado). Use o shuffle sozinho na linha. Se você quiser manter a lista original e ter uma cópia embaralhada, use embaralhada = random.sample(fila, len(fila)).
5. Repetindo o sorteio: random.seed
Um computador não sabe jogar dados de verdade. O que o random faz é uma conta muito bem bolada, que produz uma sequência de números que parecem não ter padrão nenhum. Por isso eles se chamam números pseudoaleatórios ("quase aleatórios"). Essa conta parte de um número inicial, a semente (seed). Sem você dizer nada, o Python escolhe uma semente diferente a cada execução (a partir de uma fonte de aleatoriedade do sistema operacional), e por isso os resultados mudam.
Com random.seed(N), você escolhe a semente. A mesma semente gera sempre a mesma sequência:
import random random.seed(42) print(random.randint(1, 6), random.randint(1, 6), random.randint(1, 6))
$ python3 semente1.py 6 1 1 $ python3 semente1.py 6 1 1
Duas execuções, os mesmos três números. E rodando no editor do guia, com a mesma semente e o mesmo Python, saem os mesmos 6 1 1. Cada semente dá a sua sequência:
import random
random.seed(42)
print("Primeira vez:", random.randint(1, 100), random.randint(1, 100))
random.seed(42)
print("De novo: ", random.randint(1, 100), random.randint(1, 100))
random.seed(43)
print("Outra semente:", random.randint(1, 100), random.randint(1, 100))
$ python3 semente2.py Primeira vez: 82 15 De novo: 82 15 Outra semente: 5 37
- random.seed(42)
- "Plante a semente 42": a partir daqui, os sorteios seguem a sequência da semente 42. O número é qualquer um; 42 é só uma escolha comum entre programadores.
- random.seed(42) de novo
- Volta ao começo da mesma sequência: 82 e 15 outra vez.
Para que serve um sorteio que não é surpresa? Para testar: quando um jogo dá um defeito só com certos sorteios, com a semente fixa você repete a mesma partida até achar o problema. Também é por isso que as missões desta aula que conferem um resultado exato usam seed. Num jogo de verdade, deixe sem seed.
A documentação do Python garante que random.seed(N) seguido de random.random() dá os mesmos números em versões diferentes. Para as outras funções (randint, choice, shuffle…), o resultado é o mesmo em qualquer computador com a mesma versão, mas pode mudar de uma versão do Python para outra.
Missão: a Ana quer sortear a sobremesa do almoço de domingo. O programa já plantou a semente 3, mas pega sempre o primeiro item. Troque o cardapio[0] por um sorteio com random.choice. Com essa semente, deve sair pudim.
import random
random.seed(3)
cardapio = ["bolo", "pudim", "sorvete", "pavê"]
print("Sobremesa de hoje:", cardapio[0])
import random
random.seed(3)
cardapio = ["bolo", "pudim", "sorvete", "pavê"]
print("Sobremesa de hoje:", random.choice(cardapio))
6. Sorteio não é segredo: o módulo secrets
Se a sequência do random sai de uma conta, quem descobrir o estado dessa conta consegue prever os próximos números. Para um jogo, tanto faz. Para uma senha, um código de confirmação ou um token de acesso, é perigoso. Para isso o Python tem o módulo secrets ("segredos"), que usa a fonte de aleatoriedade segura do sistema operacional:
import secrets
import string
caracteres = string.ascii_letters + string.digits
senha = "".join(secrets.choice(caracteres) for _ in range(12))
print("Senha:", senha)
$ python3 senha.py Senha: B8YqjeJxWxg0
O string.ascii_letters são as letras de a a z, minúsculas e maiúsculas, e o string.digits, os algarismos. O secrets.choice funciona como o random.choice, só que de forma segura (e não aceita seed: não dá para repetir). Regra simples: jogos e simulações, random; senhas e segurança, secrets.
Formas diferentes de sortear: qual usar
| Quero… | Use | Cuidado |
|---|---|---|
| Um inteiro de 1 a 6 | random.randint(1, 6) | O 6 entra |
Um inteiro de um range (com passo) | random.randrange(0, 100, 5) | O fim fica de fora |
| Um número com vírgula | random.uniform(a, b) ou random.random() | — |
| Um item da lista | random.choice(lista) | Lista vazia dá erro |
| Vários itens, podendo repetir | random.choices(lista, k=n) | Aceita weights |
| Vários itens, sem repetir | random.sample(lista, n) | n não pode passar do tamanho da lista |
| Embaralhar a própria lista | random.shuffle(lista) | Devolve None; só listas |
| Uma cópia embaralhada | random.sample(lista, len(lista)) | A original fica igual |
Um item com randint (jeito antigo) | lista[random.randint(0, len(lista) - 1)] | Funciona, mas o choice é mais claro e não erra o - 1 |
| Uma senha, um código secreto | secrets.choice(…) | Nunca random |
Quando dá errado
IndexError
import random sorteio = [] print(random.choice(sorteio))
$ python3 erro_vazia.py
Traceback (most recent call last):
File "/home/ana/erro_vazia.py", line 4, in <module>
print(random.choice(sorteio))
~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/random.py", line 353, in choice
raise IndexError('Cannot choose from an empty sequence')
IndexError: Cannot choose from an empty sequence
"Não dá para escolher de uma sequência vazia." O globo está sem bolinhas. A sua linha é a 4; a de baixo, de /usr/lib/python3.14/random.py, é o lugar onde o próprio módulo levantou o erro (o raise, aula raise). Como consertar: confira antes: if sorteio: (uma lista vazia conta como falso).
ValueError
import random alunos = ["Bia", "Caio", "Duda"] print(random.sample(alunos, 5))
$ python3 erro_sample.py
Traceback (most recent call last):
File "/home/ana/erro_sample.py", line 4, in <module>
print(random.sample(alunos, 5))
~~~~~~~~~~~~~^^^^^^^^^^^
File "/usr/lib/python3.14/random.py", line 436, in sample
raise ValueError("Sample larger than population or is negative")
ValueError: Sample larger than population or is negative
"Amostra maior que a população, ou negativa." Não dá para tirar 5 nomes diferentes de uma lista de 3. Como consertar: peça no máximo len(alunos) itens; ou, se repetir não for problema, use random.choices(alunos, k=5).
shuffle: a lista vira None
import random fila = ["Ana", "Bia", "Caio"] fila = random.shuffle(fila) print(fila) print(fila[0])
$ python3 erro_shuffle.py
None
Traceback (most recent call last):
File "/home/ana/erro_shuffle.py", line 6, in <module>
print(fila[0])
~~~~^^^
TypeError: 'NoneType' object is not subscriptable
Primeiro o print(fila) mostrou None: o shuffle embaralhou a lista e devolveu nada, e esse nada foi guardado em fila (a lista embaralhada se perdeu). Depois, fila[0]: "um objeto NoneType não aceita índice" (subscriptable = "que aceita [ ]"; aula O Valor None). Como consertar: random.shuffle(fila) sozinho na linha, sem fila =.
TypeError
import random palavra = "python" random.shuffle(palavra)
$ python3 erro_texto.py
Traceback (most recent call last):
File "/home/ana/erro_texto.py", line 4, in <module>
random.shuffle(palavra)
~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/random.py", line 363, in shuffle
x[i], x[j] = x[j], x[i]
~^^^
TypeError: 'str' object does not support item assignment
"Um objeto str não aceita que se troque um item." O shuffle embaralha trocando os itens de lugar, e um texto não pode ser alterado (os textos são imutáveis, aula Mutável × Imutável). O mesmo vale para tuplas. Como consertar: transforme em lista, embaralhe e junte: letras = list(palavra), random.shuffle(letras), "".join(letras). Ou, numa linha: "".join(random.sample(palavra, len(palavra))).
randint com número com vírgula, ou com as pontas trocadas
import random print(random.randint(1, 6.5))
$ python3 erro_randint.py
Traceback (most recent call last):
File "/home/ana/erro_randint.py", line 3, in <module>
print(random.randint(1, 6.5))
~~~~~~~~~~~~~~^^^^^^^^
File "/usr/lib/python3.14/random.py", line 339, in randint
b = _index(b)
TypeError: 'float' object cannot be interpreted as an integer
import random print(random.randint(10, 1))
$ python3 erro_randint2.py
Traceback (most recent call last):
File "/home/ana/erro_randint2.py", line 3, in <module>
print(random.randint(10, 1))
~~~~~~~~~~~~~~^^^^^^^^
File "/usr/lib/python3.14/random.py", line 341, in randint
raise ValueError(f"empty range in randint({a}, {b})")
ValueError: empty range in randint(10, 1)
O randint só trabalha com inteiros ("um float não pode ser interpretado como inteiro"), e o primeiro número tem de ser o menor: de 10 até 1 é um "intervalo vazio" (empty range). Como consertar: randint(1, 6), menor primeiro; para sortear com vírgula, uniform.
seed dentro do laço: o "sorteio" que sempre dá igual
import random
for rodada in range(3):
random.seed(1)
print("Rodada", rodada + 1, "- o dado deu", random.randint(1, 6))
$ python3 erro_seed.py Rodada 1 - o dado deu 2 Rodada 2 - o dado deu 2 Rodada 3 - o dado deu 2
Sem mensagem de erro, mas o dado "viciou": a cada volta, o seed(1) recomeça a sequência do zero, e o primeiro número da semente 1 é sempre o mesmo. Como consertar: o seed, quando usado, vai uma vez só, no começo do programa, fora do laço. E num jogo de verdade, não use seed.
Referência rápida
| Escrita | O que faz |
|---|---|
random.randint(a, b) | Inteiro de a a b, com os dois |
random.randrange(a, b, passo) | Inteiro do range(a, b, passo), sem o b |
random.random() | float de 0 (incluído) a 1 (não incluído) |
random.uniform(a, b) | float entre a e b |
random.choice(seq) | Um item |
random.choices(seq, k=n) | n itens, podendo repetir |
random.choices(seq, weights=[…], k=n) | …com pesos |
random.sample(seq, n) | n itens diferentes, numa lista nova |
random.shuffle(lista) | Embaralha a própria lista; devolve None |
random.seed(N) | Fixa a semente: a mesma sequência a cada execução |
secrets.choice(seq) | Um item, de forma segura (senhas) |
| Sintoma | Causa provável |
|---|---|
IndexError: Cannot choose from an empty sequence | choice numa lista vazia |
ValueError: Sample larger than population or is negative | sample pedindo mais itens do que a lista tem |
A lista virou None; 'NoneType' object is not subscriptable | lista = random.shuffle(lista) |
TypeError: 'str' object does not support item assignment | shuffle num texto ou tupla |
TypeError: 'float' object cannot be interpreted as an integer | randint/randrange com float |
ValueError: empty range in randint(10, 1) | Pontas trocadas: o menor vem primeiro |
| O sorteio sai sempre igual | Um seed esquecido no programa, ou dentro do laço |
| O 6 nunca sai do "dado" | Usou randrange(1, 6): troque por randint(1, 6) |
Exercícios
1. O bingo
Complete para sortear uma bolinha de 1 a 75 (as duas pontas podem sair):
2. Sem repetir
Complete para sortear 3 ganhadores diferentes da lista inscritos:
3. O que sai
O que o print mostra depois de fila = random.shuffle(["a", "b", "c"]) e print(fila)?
4. Quais números random.randrange(1, 6) pode sortear?
5. Para que serve o random.seed(42)?
6. A Ana vai gerar o código de confirmação que o cliente recebe no celular. Qual módulo usar?
Missão final: a ordem das apresentações
Missão: a professora vai sortear a ordem das apresentações dos trabalhos. O programa já plantou a semente 10 (para todo mundo conferir o mesmo resultado) e mostra a lista numerada, mas esqueceu de embaralhar. Acrescente o random.shuffle no lugar certo. Com essa semente, a Duda abre e o Enzo fecha.
import random
random.seed(10)
amigos = ["Ana", "Bia", "Caio", "Duda", "Enzo"]
for posicao, nome in enumerate(amigos, start=1):
print(f"{posicao}º: {nome}")
import random
random.seed(10)
amigos = ["Ana", "Bia", "Caio", "Duda", "Enzo"]
random.shuffle(amigos)
for posicao, nome in enumerate(amigos, start=1):
print(f"{posicao}º: {nome}")
Depois de cumprir a missão, apague a linha do seed e rode várias vezes: a cada vez, uma ordem nova. (O enumerate numera os itens; aula enumerate() e zip().)
Resumo
import randomtraz os sorteios. Semseed, o resultado muda a cada execução, e isso é o esperado.randint(a, b)sorteia um inteiro com as duas pontas;randrangesegue orange(sem o fim);random()euniformdãofloat.choice: um item.choices(k=…): vários, com repetição (e comweights).sample: vários, sem repetição.shuffleembaralha a própria lista e devolveNone: nunca escrevalista = random.shuffle(lista). Texto e tupla não se embaralham.random.seed(N), uma vez no começo, faz o sorteio se repetir: bom para testes, ruim para jogos.- Para senhas e códigos secretos,
secrets, nuncarandom.