W3docs

Módulo random de Python

Aprende el módulo random de Python: genera números aleatorios, haz selecciones ponderadas, baraja secuencias, usa semillas para reproducibilidad y aleatoriedad criptográfica.

El módulo random integrado de Python genera números pseudoaleatorios y realiza selecciones aleatorias. Se basa en el algoritmo Mersenne Twister, que produce secuencias pseudoaleatorias de alta calidad adecuadas para simulaciones, juegos, muestreo y pruebas — pero no para propósitos sensibles a la seguridad como la generación de contraseñas o claves criptográficas. Este capítulo cubre:

  • Generación de floats, enteros y rangos aleatorios
  • Selección de elementos aleatorios: choice, choices, sample
  • Barajado de secuencias en el lugar con shuffle
  • Uso de semillas para resultados reproducibles
  • Distribuciones continuas: uniform, gauss, triangular
  • Cuándo usar secrets en lugar de random

No se necesita instalación — basta con import random.

Importar el módulo

import random

Todos los ejemplos a continuación asumen que esta importación está en el ámbito. También puedes importar funciones individuales para evitar el prefijo random., aunque el prefijo deja claro de dónde proviene cada función:

from random import randint, choice, shuffle

Generar floats aleatorios

random()

random.random() devuelve un float en [0.0, 1.0) — incluye 0.0 pero nunca alcanza 1.0.

import random

print(random.random())  # e.g. 0.6394267984578837
print(random.random())  # e.g. 0.025010755222666936

El valor cambia en cada llamada porque el generador avanza su estado interno.

uniform(a, b)

random.uniform(a, b) devuelve un 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])

A diferencia de random(), uniform te permite especificar ambos extremos del rango, y el límite superior puede ser devuelto.

Generar enteros aleatorios

randint(a, b)

random.randint(a, b) devuelve un entero aleatorio N tal que a <= N <= b. Ambos extremos son inclusivos:

import random

random.seed(42)
die = random.randint(1, 6)
print(die)  # 6

Esta es la forma más común de simular tiradas de dados, robos de cartas o cualquier rango entero discreto.

randrange(start, stop[, step])

random.randrange imita range() de Python — stop es exclusivo y puedes especificar un paso:

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))   # 15

Cuando necesitas enteros aleatorios de un rango que no comienza en 0, o que requiere un paso, randrange es más expresivo que randint.

getrandbits(k)

random.getrandbits(k) devuelve un entero no negativo aleatorio con exactamente k bits aleatorios:

import random

random.seed(42)
print(random.getrandbits(8))   # 163 (an integer in 0..255)
print(random.getrandbits(16))  # an integer in 0..65535

Esto es útil cuando necesitas enteros aleatorios más grandes que los que se obtienen con randint, o cuando trabajas a nivel de bits.

Elegir de secuencias

choice(seq)

random.choice(seq) elige un elemento aleatorio de una secuencia no vacía. Funciona con listas, tuplas y 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)

Si la secuencia está vacía, se lanza un IndexError.

choices(population, weights=None, k=1)

random.choices elige k elementos con reemplazo (el mismo elemento puede aparecer más de una vez). Puedes sesgar la selección con 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 siempre devuelve una lista, incluso cuando k=1. El argumento weights es relativo — [1, 2, 3] produce la misma distribución que [10, 20, 30].

sample(population, k)

random.sample elige k elementos sin reemplazo — cada elemento solo puede aparecer una vez en el resultado. No modifica la secuencia 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]

Si k es mayor que el tamaño de la población, random.sample lanza un ValueError:

import random

try:
    random.sample([1, 2, 3], 5)
except ValueError as e:
    print(e)  # Sample larger than population or is negative

choices vs sample de un vistazo:

choicessample
ReemplazoNo
Resultados duplicadosPosibleNunca
Modifica el originalNoNo
Admite pesosNo (usa choices)

Barajar secuencias

random.shuffle(seq) baraja la lista en el lugar y devuelve None. La lista original es 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)

Si necesitas una copia barajada sin tocar el original, usa 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]

Semillas para resultados reproducibles

Por defecto, el módulo random se inicializa con la hora del sistema (o os.urandom()), por lo que cada ejecución produce valores diferentes. Llamar a random.seed() con un valor fijo bloquea la secuencia para obtener un resultado idéntico cada vez — esencial para depuración, pruebas unitarias y simulaciones reproducibles:

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']))  # c

random.seed() acepta un entero, una string, un float, bytes o None (que reinicia la semilla desde el sistema). La inicialización con semilla es una operación global — afecta todas las llamadas posteriores en el mismo programa, por lo que debes establecer la semilla una sola vez al inicio de un bloque reproducible.

Generación de datos de prueba reproducibles

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 ejecución con seed(999) produce exactamente la misma lista, lo que resulta útil para pruebas unitarias que comprueban valores específicos.

Distribuciones continuas

El módulo random incluye varias distribuciones de probabilidad continuas, útiles en simulaciones y modelado estadístico.

uniform(a, b)

Ya cubierto anteriormente — una distribución plana donde cada valor en [a, b] es igualmente probable.

triangular(low, high, mode)

Devuelve un float de una distribución triangular donde mode es el valor más frecuente:

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 cuando conoces el mínimo, el máximo y el valor más probable pero no la distribución exacta — común en estimación de proyectos y modelado de riesgos.

gauss(mu, sigma)

Devuelve un float de una distribución gaussiana (normal) con media mu y desviación estándar 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) es equivalente pero seguro para hilos; usa normalvariate en programas con múltiples hilos.

expovariate(lambd)

Devuelve un float de una distribución exponencial, donde lambd es 1 / media. Útil para modelar el tiempo entre eventos (por ejemplo, llegadas de clientes, paquetes de red):

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)

Ejemplos prácticos

Simular 60 tiradas 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}

Con más tiradas, la distribución se aproxima a la probabilidad teórica de 1/6 para cada cara.

Elegir un equipo aleatorio

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)

Contraseña aleatoria simple

Para contextos sin seguridad (demos, tokens descartables), random.choices funciona bien:

import random
import string

random.seed(42)
chars = string.ascii_letters + string.digits
password = ''.join(random.choices(chars, k=12))
print(password)  # NbrnTP3fAbnF

Para contraseñas o tokens de usuario reales, usa el módulo secrets en su lugar (ver más abajo).

Cuándo usar secrets en lugar de random

El módulo random no es criptográficamente seguro. Un atacante que observe suficiente salida puede predecir valores futuros. Para cualquier cosa sensible a la seguridad, usa el módulo secrets (Python 3.6+), que obtiene valores de la fuente aleatoria criptográfica del sistema operativo:

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...'

Regla general: si estás generando tokens, IDs de sesión, contraseñas o cualquier valor que un adversario no debe poder adivinar, usa secrets. Usa random para todo lo demás (juegos, simulaciones, datos de prueba, muestreo).

Referencia rápida

FunciónDescripciónDevuelve
random.random()Float en [0.0, 1.0)float
random.uniform(a, b)Float en [a, b]float
random.randint(a, b)Entero en [a, b] (ambos inclusivos)int
random.randrange(start, stop[, step])Entero de range(start, stop, step)int
random.getrandbits(k)Entero no negativo con k bits aleatoriosint
random.choice(seq)Un elemento aleatoriotipo del elemento
random.choices(pop, weights, k)k elementos con reemplazolist
random.sample(pop, k)k elementos sin reemplazolist
random.shuffle(seq)Baraja la lista en el lugarNone
random.seed(a)Establece la semilla aleatoriaNone
random.gauss(mu, sigma)Variante gaussiana (normal)float
random.normalvariate(mu, sigma)Variante normal (segura para hilos)float
random.triangular(low, high, mode)Variante de distribución triangularfloat
random.expovariate(lambd)Variante de distribución exponencialfloat

Capítulos relacionados

Práctica

Práctica
Which function picks elements without replacement (each item can appear only once in the result)?
Which function picks elements without replacement (each item can appear only once in the result)?
Was this page helpful?