W3docs

Module random de Python

Apprenez le module random de Python : nombres aléatoires, choix pondérés, mélange de séquences, graine de reproductibilité et aléatoire cryptographique.

Le module intégré random de Python génère des nombres pseudo-aléatoires et effectue des sélections aléatoires. Il repose sur l'algorithme Mersenne Twister, qui produit des séquences pseudo-aléatoires de haute qualité adaptées aux simulations, jeux, échantillonnages et tests — mais pas à des fins sensibles sur le plan de la sécurité, telles que la génération de mots de passe ou de clés cryptographiques. Ce chapitre couvre :

  • La génération de flottants, d'entiers et de plages aléatoires
  • La sélection d'éléments aléatoires : choice, choices, sample
  • Le mélange de séquences en place avec shuffle
  • L'initialisation pour des résultats reproductibles
  • Les distributions continues : uniform, gauss, triangular
  • Quand utiliser secrets plutôt que random

Aucune installation n'est nécessaire — import random suffit.

Importation du module

import random

Tous les exemples ci-dessous supposent que cet import est disponible. Vous pouvez également importer des fonctions individuellement pour éviter le préfixe random., bien que ce préfixe permette d'identifier clairement la provenance de chaque fonction :

from random import randint, choice, shuffle

Génération de flottants aléatoires

random()

random.random() renvoie un flottant dans [0.0, 1.0) — incluant 0.0 mais n'atteignant jamais 1.0.

import random

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

La valeur change à chaque appel car le générateur fait avancer son état interne.

uniform(a, b)

random.uniform(a, b) renvoie un flottant N tel 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])

Contrairement à random(), uniform vous permet de spécifier les deux bornes de la plage, et la borne supérieure peut être renvoyée.

Génération d'entiers aléatoires

randint(a, b)

random.randint(a, b) renvoie un entier aléatoire N tel que a <= N <= b. Les deux bornes sont incluses :

import random

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

C'est la façon la plus courante de simuler des lancers de dés, des tirages de cartes ou n'importe quelle plage d'entiers discrets.

randrange(start, stop[, step])

random.randrange imite range() de Python — stop est exclu et vous pouvez spécifier un pas :

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

Lorsque vous avez besoin d'entiers aléatoires dans une plage qui ne commence pas à 0 ou qui nécessite un pas, randrange est plus expressif que randint.

getrandbits(k)

random.getrandbits(k) renvoie un entier non négatif aléatoire avec exactement k bits aléatoires :

import random

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

Cela est utile lorsque vous avez besoin d'entiers aléatoires plus grands que ceux obtenus avec randint, ou lorsque vous travaillez au niveau des bits.

Sélection dans des séquences

choice(seq)

random.choice(seq) sélectionne un élément au hasard dans une séquence non vide. Cela fonctionne avec les listes, les tuples et les chaînes de caractères :

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 séquence est vide, une IndexError est levée.

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

random.choices sélectionne k éléments avec remise (le même élément peut apparaître plusieurs fois). Vous pouvez biaiser la sélection avec 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 renvoie toujours une liste, même lorsque k=1. L'argument weights est relatif — [1, 2, 3] donne la même distribution que [10, 20, 30].

sample(population, k)

random.sample sélectionne k éléments sans remise — chaque élément ne peut apparaître qu'une seule fois dans le résultat. La séquence d'origine n'est pas modifiée :

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 est supérieur à la taille de la population, random.sample lève une ValueError :

import random

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

Comparaison rapide entre choices et sample :

choicessample
RemiseOuiNon
Résultats en doublePossibleJamais
Modifie l'originalNonNon
Supporte les poidsOuiNon (utiliser choices)

Mélange de séquences

random.shuffle(seq) mélange la liste en place et renvoie None. La liste d'origine est modifiée :

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 vous avez besoin d'une copie mélangée sans toucher à l'original, utilisez 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]

Initialisation pour des résultats reproductibles

Par défaut, le module random s'initialise à partir de l'heure système (ou os.urandom()), de sorte que chaque exécution produit des valeurs différentes. Appeler random.seed() avec une valeur fixe verrouille la séquence afin d'obtenir une sortie identique à chaque fois — indispensable pour le débogage, les tests unitaires et les simulations reproductibles :

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() accepte un entier, une chaîne de caractères, un flottant, des bytes ou None (qui réinitialise à partir du système). L'initialisation est une opération globale — elle affecte tous les appels suivants dans le même programme, il faut donc définir la graine une seule fois au début d'un bloc reproductible.

Génération de données de test reproductibles

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]

Chaque exécution avec seed(999) produit exactement la même liste, ce qui est utile pour les tests unitaires qui vérifient des valeurs spécifiques.

Distributions continues

Le module random inclut plusieurs distributions de probabilité continues, utiles dans les simulations et la modélisation statistique.

uniform(a, b)

Déjà présenté plus haut — une distribution uniforme où chaque valeur dans [a, b] est équiprobable.

triangular(low, high, mode)

Renvoie un flottant selon une distribution triangulaire où mode est la valeur la plus fréquente :

import random

random.seed(42)
# Most values cluster near 5, between 0 and 10
t = random.triangular(0, 10, 5)
print(t)  # 5.753983033817951

Utile quand vous connaissez les valeurs minimale, maximale et la plus probable, mais pas la distribution exacte — courant dans l'estimation de projets et la modélisation des risques.

gauss(mu, sigma)

Renvoie un flottant selon une distribution gaussienne (normale) de moyenne mu et d'écart-type 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) est équivalent mais thread-safe ; utilisez normalvariate dans les programmes multi-threadés.

expovariate(lambd)

Renvoie un flottant selon une distribution exponentielle, où lambd est 1 / moyenne. Utile pour modéliser le temps entre des événements (par ex. arrivées de clients, paquets réseau) :

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)

Exemples pratiques

Simulation de 60 lancers de dés

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}

Avec davantage de lancers, la distribution se rapproche de la probabilité théorique de 1/6 pour chaque face.

Constitution d'une équipe aléatoire

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)

Mot de passe aléatoire simple

Pour les contextes non sécurisés (démonstrations, jetons éphémères), random.choices convient bien :

import random
import string

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

Pour de vrais mots de passe ou jetons utilisateurs, utilisez plutôt le module secrets (voir ci-dessous).

Quand utiliser secrets plutôt que random

Le module random n'est pas cryptographiquement sécurisé. Un attaquant qui observe suffisamment de sorties peut prédire les valeurs futures. Pour tout ce qui est sensible en matière de sécurité, utilisez le module secrets (Python 3.6+), qui s'appuie sur la source d'aléatoire cryptographique du système d'exploitation :

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

Règle générale : si vous générez des jetons, des identifiants de session, des mots de passe ou toute valeur qu'un adversaire ne doit pas pouvoir deviner, utilisez secrets. Utilisez random pour tout le reste (jeux, simulations, données de test, échantillonnage).

Référence rapide

FonctionDescriptionRenvoie
random.random()Flottant dans [0.0, 1.0)float
random.uniform(a, b)Flottant dans [a, b]float
random.randint(a, b)Entier dans [a, b] (bornes incluses)int
random.randrange(start, stop[, step])Entier de range(start, stop, step)int
random.getrandbits(k)Entier non négatif avec k bits aléatoiresint
random.choice(seq)Un élément aléatoiretype de l'élément
random.choices(pop, weights, k)k éléments avec remiselist
random.sample(pop, k)k éléments sans remiselist
random.shuffle(seq)Mélange la liste en placeNone
random.seed(a)Définit la graine aléatoireNone
random.gauss(mu, sigma)Variable gaussienne (normale)float
random.normalvariate(mu, sigma)Variable normale (thread-safe)float
random.triangular(low, high, mode)Variable de distribution triangulairefloat
random.expovariate(lambd)Variable de distribution exponentiellefloat

Chapitres associés

Pratique

Pratique
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?