Gérer le hasard avec la bibliothèque standard Python : random (choix, échantillonnage, mélange, reproductibilité)

Série 04 – Génération de nombres aléatoires et mélange de données

« Choisir un élément au hasard », « mélanger », « sélectionner plusieurs éléments sans répétition », « attribuer des probabilités différentes ». Ces fonctions apparaissent fréquemment dans les jeux, la génération de données de test, les simulations simples ou la division de jeux de données.

Truc de casino du magicien

Le module random de la bibliothèque standard Python permet de répondre à ces besoins avec un code court. Il convient toutefois de noter que random n’est pas adapté aux besoins de sécurité.


1. La nature « aléatoire » produite par random

random génère des pseudo‑nombres aléatoires (PRNG). Plutôt que des nombres réellement imprévisibles, il crée une séquence qui semble aléatoire à partir d’un état interne.

  • Avec le même état initial (seed), le flux de résultats est identique.
  • Cela facilite le débogage et les expériences reproductibles.
  • En revanche, dans les scénarios où un attaquant peut deviner l’état, random n’est pas approprié (voir secrets plus loin).

2. Nombres aléatoires de base : tirer des nombres

2.1 Nombre décimal entre 0 et 1 : random()

import random

x = random.random()
print(x)  # 0.0 <= x < 1.0

2.2 Plage d’entiers : randint(a, b) / randrange()

import random

print(random.randint(1, 6))   # 1~6 (inclus)
print(random.randrange(0, 10, 2))  # 0,2,4,6,8
  • randint(a, b) inclut a et b
  • randrange(start, stop, step) suit la règle de range (stop exclu)

2.3 Nombre décimal dans une plage : uniform(a, b)

import random

print(random.uniform(1.5, 3.5))

3. Sélection dans une collection : choix, échantillonnage, mélange

3.1 Choisir un élément : choice()

import random

items = ["rock", "paper", "scissors"]
print(random.choice(items))

3.2 Sélectionner plusieurs éléments sans répétition : sample()

import random

nums = list(range(1, 46))
picked = random.sample(nums, k=6)  # 6 sans répétition
print(picked)
  • sample() ne modifie pas l’original
  • Pas de répétition

3.3 Mélanger une liste : shuffle() (en place)

import random

deck = list(range(10))
random.shuffle(deck)
print(deck)
  • shuffle() modifie la liste in‑place.
  • Pour garder l’original, utilisez sample() pour créer une copie mélangée.
import random

deck = list(range(10))
shuffled = random.sample(deck, k=len(deck))
print(deck)
print(shuffled)

4. Choix pondéré : choices()

« Fréquemment, rarement » est utile pour créer des sélections avec des probabilités différentes.

import random

items = ["common", "rare", "legendary"]
weights = [85, 14, 1]  # proportions

result = random.choices(items, weights=weights, k=10)
print(result)
  • choices() autorise par défaut la répétition.
  • weights peut être des probabilités (0‑1) ou des proportions.

5. Reproduire les résultats : seed()

En donnant le même seed, le flux de résultats est identique. Utile pour les tests.

import random

random.seed(42)
print(random.randint(1, 100))
print(random.randint(1, 100))

Même si plusieurs fonctions sont mélangées, l’ordre d’appel reste déterminé.

Note : seed() affecte l’état global. Dans de grands projets, il est plus sûr de créer une instance random.Random() séparée.


6. Utiliser un RNG local au lieu de l’état global : random.Random()

Vous pouvez isoler l’état du RNG sans toucher l’état global.

import random

rng = random.Random(42)  # RNG local
print(rng.randint(1, 100))
print(rng.randint(1, 100))

Cette approche est particulièrement utile dans les bibliothèques ou lorsqu’on partage le même module.


7. Nombres aléatoires pour la sécurité : secrets

random est prévisible. Pour les jetons, codes d’authentification ou liens de réinitialisation, utilisez secrets.

import secrets

token = secrets.token_urlsafe(16)
print(token)
  • secrets est conçu pour tirer des nombres à partir d’une source sécurisée du système.

8. Exemples de motifs courants

8.1 Tirer un ou plusieurs éléments aléatoires d’une liste

import random

users = ["u1", "u2", "u3", "u4", "u5"]
print(random.choice(users))        # 1
print(random.sample(users, k=2))   # 2 sans répétition

8.2 Mélanger les données et prendre la partie avant

import random

data = list(range(100))
random.shuffle(data)
train = data[:80]
test = data[80:]

8.3 Roulette simple pondérée

import random

prizes = ["A", "B", "C", "D"]
weights = [1, 3, 10, 86]  # D le plus fréquent
print(random.choices(prizes, weights=weights, k=1)[0])

9. Conclusion

random regroupe les opérations de choix aléatoire dans une API compacte.

  • Choisir un élément : choice
  • Sélection sans répétition : sample
  • Mélanger : shuffle
  • Choix pondéré : choices
  • Reproductibilité : seed ou random.Random()
  • Nombres aléatoires sécurisés : secrets

Dans la prochaine partie, nous explorerons d’autres modules de la bibliothèque standard, comme statistics ou math, pour manipuler les nombres.


Articles connexes :