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.

Você vai aprender
  • 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) e sample.
  • A embaralhar uma lista com shuffle, que muda a própria lista e devolve None.
  • A repetir exatamente o mesmo sorteio com random.seed.
  • Por que o random não serve para senhas, e o módulo secrets.
  • Os erros reais: lista vazia, amostra maior que a lista, shuffle num texto, e o seed no 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çãoSorteiaExemplo 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 bUma altura entre 1,5 e 2,5 metros
random.randint(a, b)Um int de a até b, com o bO dado: randint(1, 6)
random.randrange(a, b, passo)Um int do range(a, b, passo), sem o bUm 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 fila está em outra ordem. Ele não cria uma lista nova e não devolve nada (devolve None).
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 mesma semente em outra versão do Python

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…UseCuidado
Um inteiro de 1 a 6random.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írgularandom.uniform(a, b) ou random.random()—
Um item da listarandom.choice(lista)Lista vazia dá erro
Vários itens, podendo repetirrandom.choices(lista, k=n)Aceita weights
Vários itens, sem repetirrandom.sample(lista, n)n não pode passar do tamanho da lista
Embaralhar a própria listarandom.shuffle(lista)Devolve None; só listas
Uma cópia embaralhadarandom.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 secretosecrets.choice(…)Nunca random

Quando dá errado

Sortear de uma lista vazia: 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).

Amostra maior que a lista: 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).

Guardar o resultado do 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 =.

Embaralhar um texto: 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.

O 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

EscritaO 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)
SintomaCausa provável
IndexError: Cannot choose from an empty sequencechoice numa lista vazia
ValueError: Sample larger than population or is negativesample pedindo mais itens do que a lista tem
A lista virou None; 'NoneType' object is not subscriptablelista = random.shuffle(lista)
TypeError: 'str' object does not support item assignmentshuffle num texto ou tupla
TypeError: 'float' object cannot be interpreted as an integerrandint/randrange com float
ValueError: empty range in randint(10, 1)Pontas trocadas: o menor vem primeiro
O sorteio sai sempre igualUm 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):

bolinha = random.(1, 75)

2. Sem repetir

Complete para sortear 3 ganhadores diferentes da lista inscritos:

ganhadores = random.(inscritos, 3)

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 random traz os sorteios. Sem seed, o resultado muda a cada execução, e isso é o esperado.
  • randint(a, b) sorteia um inteiro com as duas pontas; randrange segue o range (sem o fim); random() e uniform dão float.
  • choice: um item. choices(k=…): vários, com repetição (e com weights). sample: vários, sem repetição.
  • shuffle embaralha a própria lista e devolve None: nunca escreva lista = 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, nunca random.