Le module random

Apprenez à utiliser le module random de Python.

Publié le par Gabriel Trouvé (mis à jour le )

53 minutes

Qui n'a jamais essayé de créer le jeu du nombre mystère ? Si ce n'est pas encore fait,
nous le proposons sur Docstring.

Création de jeux, data science, statistiques… l'aléatoire est présent dans de multiples domaines.
En Python, plutôt que de réinventer la roue, vous utiliserez la bibliothèque standard random.

Les fonctions incontournables

Certainement les usages les plus courants du module : générer un nombre entier aléatoire et piocher un élément dans une liste.

Tirer des nombres entiers : randint et randrange

La fonction random.randint(a, b) renvoie un entier aléatoire compris entre a et b. Les deux bornes sont incluses.

import random

# Un entier entre 1 et 10 (la borne 1 ET la borne 10 sont incluses)
print(random.randint(1, 10)) # Affiche : 7 (par exemple)
PYTHON
Un instant

Créez un compte pour exécuter ce code

Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.

Si vous devez utiliser un pas, utilisez random.randrange(start, stop, step). Notez que la borne de fin est exclue. Pour s’en souvenir, c’est le même principe que la fonction range() en Python : la valeur de fin est exclue.

import random


# Un entier pair entre 0 et 100

print(random.randrange(0, 101, 2))
PYTHON
Un instant

Créez un compte pour exécuter ce code

Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.

Piocher et mélanger des séquences

random propose de quoi s'amuser avec les séquences :

  • random.choice() pour extraire un élément au hasard
import random

utilisateurs = ["Patrick", "Sebastien", "Ely", "Ana"]

gagnant = random.choice(utilisateurs)
print(f"Le gagnant est {gagnant}")
PYTHON
Un instant

Créez un compte pour exécuter ce code

Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.

  • random.choices() permet de tirer plusieurs éléments, le même élément peut être tiré plusieurs fois. Il est même possible d'utiliser le paramètre weights qui permet d'attribuer plus ou moins de chances à certains éléments
import random

utilisateurs = ["Patrick", "Sebastien", "Ely", "Ana"]


# Patrick a ici 10 fois plus de chances d'être tiré au sort que les autres
# Tire au sort 3 utilisateurs
tirage = random.choices(utilisateurs, weights=[10, 1, 1, 1], k=3)
print(tirage)
PYTHON
Un instant

Créez un compte pour exécuter ce code

Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.

  • random.sample() pour tirer plusieurs éléments, le même élément ne peut pas être tiré plusieurs fois, donc cette fonction garantit qu'il n'y aura pas de doublon
import random

utilisateurs = ["Patrick", "Sebastien", "Ely", "Ana"]

# Tire au sort 2 utilisateurs de la liste sans doublons
echantillon = random.sample(utilisateurs, k=2)
print(echantillon)
PYTHON
Un instant

Créez un compte pour exécuter ce code

Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.

  • random.shuffle() mélange les éléments d'une liste
import random

utilisateurs = ["Patrick", "Sebastien", "Ely", "Ana"]


# Mélanger une liste
random.shuffle(utilisateurs)
print(utilisateurs)
PYTHON
Un instant

Créez un compte pour exécuter ce code

Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.

Attention

La fonction shuffle() mélange la séquence sur place. Cela veut dire qu'elle modifie la liste d'origine et renvoie None. Et donc vous me voyez venir : il n'est pas possible de mélanger une séquence immuable comme un tuple avec shuffle().

Les nombres à virgule

La fonction random.random() renvoie un nombre à virgule compris entre 0.0 et 1.0. La borne 1.0 est exclue.

import random

# Un flottant de base entre 0.0 (inclus) et 1.0 (exclu)
print(random.random())
PYTHON
Un instant

Créez un compte pour exécuter ce code

Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.

Si vous avez besoin d'une plage spécifique pour les nombres flottants, random.uniform(a, b) est là pour ça. La borne finale b peut être techniquement incluse ou exclue selon l'arrondi des nombres flottants.

import random


# Un flottant entre 2.5 et 10.0
print(random.uniform(2.5, 10.0))
PYTHON
Un instant

Créez un compte pour exécuter ce code

Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.

À noter

Le problème d'arrondi des flottants n'est pas propre à Python, mais à la représentation binaire gérée par votre processeur (voir la norme IEEE 754).

Les distributions statistiques

Pour les amateurs de statistiques, random met à notre disposition des fonctions permettant de représenter des comportements réalistes :

  • random.gauss(mu, sigma) permet de simuler des phénomènes naturels ou humains qui se regroupent autour d'une moyenne centrale. mu est la moyenne et sigma l'écart-type
import random

taille_moyenne = random.gauss(175.0, 7.0)
print(f"Taille générée : {taille_moyenne:.2f} cm")
PYTHON
Un instant

Créez un compte pour exécuter ce code

Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.

  • random.triangular() est très pratique pour faire une estimation avec un minimum, un maximum et une valeur la plus probable
import random


# Idéal quand on connaît un minimum, un maximum (bornes incluses), et la valeur la plus probable (le mode)
prix_estime = random.triangular(10, 100, 25)
print(f"Prix estimé : {prix_estime:.2f} €")
PYTHON
Un instant

Créez un compte pour exécuter ce code

Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.

  • random.expovariate(lambd) permet de modéliser le temps d'attente entre deux événements. Imaginez que Patrick vienne vous poser une question à votre bureau en moyenne toutes les 5 minutes. Réellement, il peut très bien revenir à la charge au bout de 2 minutes, puis nous laisser tranquilles pendant 10 minutes
import random

# On veut simuler une attente moyenne de 5 minutes.
# lambd représente la fréquence : 1 visite de Patrick / 5 minutes
temps_attente = random.expovariate(1 / 5.0) 
print(f"Patrick revient poser une question dans {temps_attente:.2f} min")
# Par exemple : 
# - Patrick revient poser une question dans 3.45 min
# - Patrick revient poser une question dans 7.89 min
PYTHON
Un instant

Créez un compte pour exécuter ce code

Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.

À noter

Pourquoi 1 / 5.0 ? Le paramètre lambd correspond à la fréquence. On s'attend à voir Patrick en moyenne toutes les 5 minutes, alors sa fréquence d'apparition est de 1 divisée par 5 minutes.

  • random.binomialvariate(n, p), la petite nouvelle arrivée avec Python 3.12, permet de compter les réussites. Imaginez Patrick en pleine partie de fléchettes : vous avez 10 tirs (n), et il touche le centre dans 70 % des cas (p). La fonction va simuler la partie de Patrick
import random


# Simule le nombre de succès sur "n" essais avec une probabilité "p"
# Le résultat est toujours inclus entre 0 et n (les deux bornes incluses).
# Par exemple : lancer 10 fois une pièce truquée qui tombe sur pile 70% du temps
succes = random.binomialvariate(n=10, p=0.7)
print(f"Nombre de piles obtenus : {succes}")
PYTHON
Un instant

Créez un compte pour exécuter ce code

Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.

Reproductibilité et gestion de l'état

En fait, avec random, on ne parle pas de "vrai" hasard, mais de pseudo-aléatoire. Les algorithmes partent d'une graine (seed) pour générer une séquence mathématique qui ressemble au hasard. Par défaut, la graine change à chaque exécution car elle est basée sur l'heure système.

Figer le hasard avec random.seed()

Il est possible de figer la graine pour ne pas avoir un résultat qui change à chaque exécution.

import random

# On force la graine à une valeur précise
random.seed(42)
print(random.randint(1, 100)) # Affiche : 82
print(random.randint(1, 100)) # Affiche : 15

# Si on réinitialise avec la même graine, on obtiendra EXACTEMENT la même séquence
random.seed(42)
print(random.randint(1, 100)) # Affiche : 82 (Encore !)
print(random.randint(1, 100)) # Affiche : 15 (Encore !)
PYTHON
Un instant

Créez un compte pour exécuter ce code

Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.

Le chiffre 42 n'a aucun lien intuitif avec 82 ou 15 ; c'est juste le résultat d'une suite de calculs mathématiques complexes.

Attention

Dans un de mes précédents articles sur le module unittest, nous avons vu comment utiliser les mocks.

Pourquoi s'embêter avec un mock si random.seed(a) permet de prédire le test ?

Le mock court-circuite la fonction, et random.randint ne sera jamais exécutée. random.seed(a) permet de figer l'algorithme complet.

Pour résumer : le mock force à réfléchir aux valeurs importantes, le seed permet de déléguer le choix des valeurs à l'algorithme.

Sauvegarder l'état en cours

Il faut savoir que random utilise l'algorithme Mersenne Twister pour produire des nombres pseudo-aléatoires.

Imaginez-le comme un livre dont toutes les pages sont déjà écrites, puisque l'algorithme est déterministe, défini par sa graine (seed) initiale. Dès que vous utilisez une fonction comme random, Python lit la page courante et avance d'une page pour le prochain tirage.

Vous pouvez utiliser un marque-page à un endroit précis via getstate(). La fonction setstate() permet de revenir à cet état.

import random

# On glisse notre marque-page
etat_actuel = random.getstate()

print("--- Premier tirage ---")
print(random.random()) # Affiche par exemple 0.123...
print(random.randint(1, 10)) # Affiche par exemple 7

# On recharge notre état de départ (on revient à la position du marque-page)
random.setstate(etat_actuel)

print("--- Retour dans le passé ---")
print(random.random()) # Affiche EXACTEMENT 0.123...
print(random.randint(1, 10)) # Affiche EXACTEMENT 7
PYTHON

random ne doit pas être utilisé pour les mots de passe

L'algorithme de Mersenne Twister est déterministe. C'est-à-dire que l'algorithme suit une suite d'instructions mathématiques qui ne laisse pas de place au "vrai" hasard. On pourrait théoriquement prédire les nombres suivants. Il ne faut donc jamais utiliser random pour générer des mots de passe ou des jetons par exemple.

À noter

Pour la sécurité, Python recommande d'utiliser le module natif secrets.

L'astuce arrivée avec Python 3.13

On va terminer avec une petite astuce. Depuis Python 3.13, il est possible d'utiliser random depuis le terminal pour faire des tirages sans même ouvrir un script.

# Tirer une chaîne de caractères au sort
python -m random --choice "Patrick" "Sebastien" "Ely"

# Tirer un entier au hasard (entre 1 et le nombre donné, bornes incluses)
python -m random --integer 100
SHELL
random depuis le terminal

random depuis le terminal

Bravo, tu es prêt à passer à la suite

Rechercher sur le site

Inscris-toi à Docstring

Pour commencer ton apprentissage.

Tu as déjà un compte ? Connecte-toi.