26  Modules approfondis et création de modules

Python brille par son immense bibliothèque standard : des centaines de modules prêts à l’emploi, disponibles sans installation. Au niveau Basique, vous avez survolé math, random et datetime. Ici, on approfondit ces modules et on apprend à créer les siens — une étape fondamentale pour structurer de vrais projets.

26.1 Le module math en détail

Le module math fournit les fonctions mathématiques classiques. Il doit être importé :

import math

Constantes utiles

import math

print(math.pi)         # 3.141592653589793
print(math.e)          # 2.718281828459045
print(math.inf)        # infini
print(math.nan)        # Not a Number
3.141592653589793
2.718281828459045
inf
nan

Fonctions essentielles

Fonction Effet
math.sqrt(x) Racine carrée
math.pow(x, y) x ** y (renvoie un float)
math.exp(x) e ** x
math.log(x) Logarithme népérien (ln)
math.log(x, base) Logarithme dans la base donnée
math.log10(x), math.log2(x) Log base 10 / base 2
math.floor(x) Arrondi vers le bas
math.ceil(x) Arrondi vers le haut
math.trunc(x) Troncature (vers zéro)
math.fabs(x) Valeur absolue (float)
math.gcd(a, b) PGCD (plus grand commun diviseur)
math.factorial(n) n!
import math

print("√2 =", math.sqrt(2))
print("2^10 =", math.pow(2, 10))
print("ln(e) =", math.log(math.e))
print("log10(100) =", math.log10(100))
print("floor(3.7) =", math.floor(3.7))
print("ceil(3.1)  =", math.ceil(3.1))
print("7! =", math.factorial(7))
√2 = 1.4142135623730951
2^10 = 1024.0
ln(e) = 1.0
log10(100) = 2.0
floor(3.7) = 3
ceil(3.1)  = 4
7! = 5040

Fonctions trigonométriques

Fonction Effet
math.sin(x), math.cos(x), math.tan(x) Trigonométrie (en radians)
math.asin(x), math.acos(x), math.atan(x) Arc-sinus, arc-cosinus, arc-tangente
math.radians(x), math.degrees(x) Conversion degrés ↔︎ radians
import math

angle_deg = 90
angle_rad = math.radians(angle_deg)
print(f"sin({angle_deg}°) = {math.sin(angle_rad):.4f}")
print(f"cos(π) = {math.cos(math.pi):.4f}")
sin(90°) = 1.0000
cos(π) = -1.0000
⚠️ Attention : math.sin() travaille en radians

math.sin(90) ne vaut pas 1 ! Il faut convertir : math.sin(math.radians(90)).

26.2 Le module random en détail

Pour générer des nombres aléatoires, mélanger des séquences, tirer des échantillons.

Fonctions principales

Fonction Effet
random.random() Flottant entre 0.0 (inclus) et 1.0 (exclu)
random.uniform(a, b) Flottant entre a et b
random.randint(a, b) Entier entre a et b inclus
random.randrange(a, b) Entier entre a inclus et b exclu
random.choice(seq) Élément au hasard dans une séquence
random.choices(seq, k=n) n éléments au hasard (avec remise)
random.sample(seq, k=n) n éléments distincts (sans remise)
random.shuffle(liste) Mélange la liste en place
import random

random.seed(42)         # pour reproductibilité dans la démo

print("random() :", random.random())
print("uniform(1, 10) :", random.uniform(1, 10))
print("randint(1, 6) :", random.randint(1, 6))

fruits = ["pomme", "banane", "cerise", "datte"]
print("choice :", random.choice(fruits))
print("choices (3 avec remise) :", random.choices(fruits, k=3))
print("sample (3 sans remise)  :", random.sample(fruits, k=3))

# shuffle modifie EN PLACE
nombres = [1, 2, 3, 4, 5]
random.shuffle(nombres)
print("Mélangé :", nombres)
random() : 0.6394267984578837
uniform(1, 10) : 1.2250967970040025
randint(1, 6) : 3
choice : banane
choices (3 avec remise) : ['pomme', 'cerise', 'cerise']
sample (3 sans remise)  : ['pomme', 'cerise', 'banane']
Mélangé : [2, 3, 4, 5, 1]
random.seed() pour la reproductibilité

Par défaut, random est initialisé avec l’heure système, donc les résultats changent à chaque exécution. En passant random.seed(n), on obtient toujours la même suite pour un même n. Utile pour :

  • Débugger un problème qui dépend de l’aléatoire.
  • Écrire des tests unitaires reproductibles.
  • Faire des démonstrations (comme dans ce cours).

En production réelle, ne pas fixer le seed (ou utiliser random.SystemRandom pour de la cryptographie).

Distinguer choices et sample

import random
random.seed(42)

urne = ["A", "B", "C"]

# choices : avec remise (doublons possibles)
print("choices k=5 :", random.choices(urne, k=5))

# sample : sans remise (tous distincts, max = len(urne))
print("sample k=3  :", random.sample(urne, k=3))
choices k=5 : ['B', 'A', 'A', 'A', 'C']
sample k=3  : ['C', 'A', 'B']
# sample avec k > len : erreur
import random
random.sample([1, 2, 3], k=5)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[7], line 3
      1 # sample avec k > len : erreur
      2 import random
----> 3 random.sample([1, 2, 3], k=5)

File ~\AppData\Local\Programs\Python\Python312\Lib\random.py:430, in Random.sample(self, population, k, counts)
    428 randbelow = self._randbelow
    429 if not 0 <= k <= n:
--> 430     raise ValueError("Sample larger than population or is negative")
    431 result = [None] * k
    432 setsize = 21        # size of a small set minus size of an empty list

ValueError: Sample larger than population or is negative

26.3 Le module datetime

Pour manipuler des dates et des heures. Trois classes principales :

  • date : une date (année, mois, jour).
  • time : une heure (heure, minute, seconde).
  • datetime : combinaison des deux.
  • timedelta : une durée (pour additionner/soustraire).

Créer et afficher une date

from datetime import date, datetime

# Date à la main
jour_j = date(2025, 12, 31)
print(jour_j)

# Aujourd'hui
aujourd_hui = date.today()
print("Aujourd'hui :", aujourd_hui)

# Datetime avec heure
rdv = datetime(2025, 12, 31, 20, 30)
print(rdv)

# Maintenant
maintenant = datetime.now()
print("Maintenant :", maintenant)
2025-12-31
Aujourd'hui : 2026-04-22
2025-12-31 20:30:00
Maintenant : 2026-04-22 15:49:07.504920

Arithmétique sur les dates avec timedelta

from datetime import date, timedelta

aujourd_hui = date.today()

# Durées
demain = aujourd_hui + timedelta(days=1)
dans_un_mois = aujourd_hui + timedelta(days=30)
hier = aujourd_hui - timedelta(days=1)

print("Aujourd'hui   :", aujourd_hui)
print("Demain        :", demain)
print("Dans un mois  :", dans_un_mois)
print("Hier          :", hier)

# Différence entre deux dates → timedelta
anniversaire = date(2025, 12, 25)
noel_prochain_delta = anniversaire - aujourd_hui
print(f"Jours jusqu'au 25 décembre : {noel_prochain_delta.days}")
Aujourd'hui   : 2026-04-22
Demain        : 2026-04-23
Dans un mois  : 2026-05-22
Hier          : 2026-04-21
Jours jusqu'au 25 décembre : -118
Arguments de timedelta

timedelta accepte days, hours, minutes, seconds, weeks, milliseconds, microseconds. Il n’y a pas de months ou years (durée variable), il faut passer par days.

Formater une date : strftime

La méthode strftime (string format time) convertit une date en chaîne selon un format :

Code Sens
%Y Année sur 4 chiffres (2025)
%y Année sur 2 chiffres (25)
%m Mois sur 2 chiffres (01-12)
%d Jour du mois sur 2 chiffres (01-31)
%H, %M, %S Heure, minute, seconde
%A, %a Jour de la semaine (long / court)
%B, %b Mois (long / court)
from datetime import datetime

maintenant = datetime(2025, 12, 31, 14, 30, 0)

print(maintenant.strftime("%d/%m/%Y"))             # 31/12/2025
print(maintenant.strftime("%d %B %Y"))             # 31 December 2025
print(maintenant.strftime("%Y-%m-%d %H:%M:%S"))    # 2025-12-31 14:30:00
print(maintenant.strftime("%A"))                   # Wednesday
31/12/2025
31 December 2025
2025-12-31 14:30:00
Wednesday
Formatage dans une f-string

On peut aussi formater une datetime directement dans une f-string (vu au chapitre 3) :

from datetime import datetime
d = datetime(2025, 12, 31)
print(f"Jour J : {d:%d/%m/%Y}")
Jour J : 31/12/2025

Convertir une chaîne en date : strptime

Inverse de strftime : parser une chaîne pour en extraire une date.

from datetime import datetime

saisie = "31/12/2025"
dte = datetime.strptime(saisie, "%d/%m/%Y")
print(dte)
print(type(dte))
2025-12-31 00:00:00
<class 'datetime.datetime'>

Le format doit correspondre exactement à la chaîne, sinon ValueError.

from datetime import datetime
datetime.strptime("31-12-2025", "%d/%m/%Y")     # mauvais séparateur
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[13], line 2
      1 from datetime import datetime
----> 2 datetime.strptime("31-12-2025", "%d/%m/%Y")     # mauvais séparateur

File ~\AppData\Local\Programs\Python\Python312\Lib\_strptime.py:554, in _strptime_datetime(cls, data_string, format)
    551 def _strptime_datetime(cls, data_string, format="%a %b %d %H:%M:%S %Y"):
    552     """Return a class cls instance based on the input string and the
    553     format string."""
--> 554     tt, fraction, gmtoff_fraction = _strptime(data_string, format)
    555     tzname, gmtoff = tt[-2:]
    556     args = tt[:6] + (fraction,)

File ~\AppData\Local\Programs\Python\Python312\Lib\_strptime.py:333, in _strptime(data_string, format)
    331 found = format_regex.match(data_string)
    332 if not found:
--> 333     raise ValueError("time data %r does not match format %r" %
    334                      (data_string, format))
    335 if len(data_string) != found.end():
    336     raise ValueError("unconverted data remains: %s" %
    337                       data_string[found.end():])

ValueError: time data '31-12-2025' does not match format '%d/%m/%Y'

26.4 Le module statistics

Pour des calculs statistiques simples sans installer numpy.

import statistics

notes = [12, 15, 9, 17, 11, 14, 8, 18]

print("Moyenne :", statistics.mean(notes))
print("Médiane :", statistics.median(notes))
print("Mode    :", statistics.mode([1, 2, 2, 3, 3, 3]))
print("Écart-type :", round(statistics.stdev(notes), 2))
print("Variance   :", round(statistics.variance(notes), 2))
Moyenne : 13
Médiane : 13.0
Mode    : 3
Écart-type : 3.63
Variance   : 13.14
statistics.mean() vs sum()/len()

Les deux donnent la moyenne. statistics.mean() gère mieux les flottants et les types Decimal/Fraction. Pour une simple liste d’entiers, c’est équivalent à sum(liste)/len(liste).

26.5 Le module time (notion)

Pour mesurer des durées d’exécution ou faire des pauses.

import time

# Heure Unix (secondes depuis le 1er janvier 1970)
print("Timestamp :", time.time())

# Mesurer une durée
debut = time.time()
total = sum(range(1_000_000))
duree = time.time() - debut
print(f"Somme calculée en {duree*1000:.2f} ms")
Timestamp : 1776865747.6433299
Somme calculée en 11.57 ms

Pour une pause : time.sleep(secondes) — fige le programme pendant n secondes. Utile dans des scripts, boucles de polling, etc.

import time
print("Patientez...")
time.sleep(2)      # attend 2 secondes
print("Voilà !")

26.6 Créer son propre module

Un module Python est simplement un fichier .py. Tout fichier que vous écrivez peut devenir un module réutilisable !

Exemple

Créez un fichier geometrie.py :

# Fichier : geometrie.py
"""Fonctions de calculs géométriques simples."""

from math import pi


def aire_rectangle(longueur: float, largeur: float) -> float:
    """Calcule l'aire d'un rectangle."""
    return longueur * largeur


def aire_cercle(rayon: float) -> float:
    """Calcule l'aire d'un disque."""
    return pi * rayon ** 2


def perimetre_cercle(rayon: float) -> float:
    """Calcule la circonférence d'un cercle."""
    return 2 * pi * rayon

Dans un autre fichier (ou dans l’interpréteur) du même dossier :

import geometrie

print(geometrie.aire_rectangle(3, 4))
print(geometrie.aire_cercle(5))

# Ou, pour ne importer que certaines fonctions :
from geometrie import aire_cercle, perimetre_cercle
print(aire_cercle(5))
Règles importantes
  1. Nom du fichier = nom du module. geometrie.pyimport geometrie.
  2. Le nom de fichier doit respecter les règles des identifiants Python (pas d’espace ni de tiret).
  3. Le fichier doit être accessible : dans le même dossier, ou dans le PYTHONPATH.
  4. Par convention, une docstring de module ouvre le fichier (en haut, avant tout import).

Le bloc if __name__ == "__main__"

Quand Python exécute un fichier .py, il définit une variable spéciale __name__ :

  • Si le fichier est exécuté directement (ex: python geometrie.py) : __name__ == "__main__".
  • Si le fichier est importé comme module (ex: import geometrie) : __name__ == "geometrie".

On utilise ça pour distinguer les deux cas, et notamment écrire du code de test dans le fichier du module sans l’exécuter à l’import.

# geometrie.py

from math import pi


def aire_cercle(rayon):
    return pi * rayon ** 2


# Ce bloc ne s'exécute QUE si on lance le fichier directement
# (pas à l'import depuis un autre fichier)
if __name__ == "__main__":
    # Petits tests de démonstration
    print("Test : aire d'un cercle de rayon 5")
    print(aire_cercle(5))

Si un autre fichier fait import geometrie, les fonctions sont disponibles sans exécuter les tests. Si on lance python geometrie.py directement, les tests s’exécutent.

C’est l’idiome standard pour organiser un module Python.

26.7 La fonction dir()

dir(objet) renvoie la liste des attributs et méthodes disponibles sur un objet.

import math
print(dir(math))
['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'cbrt', 'ceil', 'comb', 'copysign', 'cos', 'cosh', 'degrees', 'dist', 'e', 'erf', 'erfc', 'exp', 'exp2', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'isqrt', 'lcm', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'nextafter', 'perm', 'pi', 'pow', 'prod', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'sumprod', 'tan', 'tanh', 'tau', 'trunc', 'ulp']
texte = "hello"
# On filtre les noms qui ne commencent pas par _ pour la lisibilité
print([m for m in dir(texte) if not m.startswith("_")])
['capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'removeprefix', 'removesuffix', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

Utile pour :

  • Découvrir les fonctions disponibles dans un module.
  • Voir les méthodes d’un type (chaîne, liste, etc.).
  • Déboguer.

Couplez avec help() pour obtenir la doc :

import math
help(math.gcd)

26.8 Les principaux modules de la bibliothèque standard

Voici une sélection des modules à connaître au niveau Opérationnel (ou à reconnaître quand on en croise) :

Module Domaine
math Mathématiques
random Aléatoire
datetime Dates et heures
statistics Statistiques de base
time Durées, pauses
os Système de fichiers, variables d’environnement
sys Interpréteur, arguments de ligne de commande
pathlib Chemins modernes (remplace os.path)
json Sérialisation/désérialisation JSON
csv Lecture/écriture de CSV
re Expressions régulières
collections Structures avancées : Counter, defaultdict, deque
itertools Outils d’itération avancée
functools Outils fonctionnels : @cache, reduce, partial

Vous les rencontrerez dans les niveaux Avancé et Expert.


🧩 Quiz 7.1 — Modules

Question 1

Que renvoie math.floor(-3.2) ?

  1. -3
  2. -4
  3. 3
  4. -3.2

b) -4floor arrondit vers le bas (vers moins l’infini), pas vers zéro. Pour une troncature vers zéro, utilisez math.trunc ou int().

import math
print(math.floor(-3.2))    # -4
print(math.trunc(-3.2))    # -3
print(int(-3.2))           # -3 (troncature)
-4
-3
-3

Question 2

Quelle fonction tire 3 éléments distincts sans remise ?

  1. random.choices(liste, k=3)
  2. random.sample(liste, k=3)
  3. random.choice(liste, 3)
  4. random.randint(0, 3)

b) random.sample(liste, k=3)choices fait avec remise (peut répéter), sample sans remise.

Question 3

Combien vaut math.sin(math.pi / 2) environ ?

  1. 0
  2. 1
  3. π/2
  4. -1

b) 1sin(π/2) = 1 (en radians).

import math
print(math.sin(math.pi / 2))
1.0

Question 4

Que s’affiche-t-il ?

from datetime import date, timedelta
d = date(2025, 1, 1)
d2 = d + timedelta(days=365)
print(d2)
  1. 2025-12-31
  2. 2026-01-01
  3. 2024-12-31
  4. Une erreur

b) 2026-01-01 — 2025 n’est pas bissextile (365 jours), donc +365 jours mène au 1er janvier 2026.

from datetime import date, timedelta
d = date(2025, 1, 1)
print(d + timedelta(days=365))
2026-01-01

Question 5

Quelle expression convertit "15/08/2025" en objet datetime ?

  1. datetime("15/08/2025")
  2. datetime.strptime("15/08/2025", "%d/%m/%Y")
  3. datetime.strftime("15/08/2025", "%d/%m/%Y")
  4. datetime.parse("15/08/2025")

b) datetime.strptime(...)parse time : chaîne → datetime. À ne pas confondre avec strftime (format : datetime → chaîne).

Moyen mnémotechnique :

  • strpparse (lire)
  • strfformat (écrire)

Question 6

À quoi sert if __name__ == "__main__": ?

  1. À déclarer le nom principal du programme
  2. À séparer le code qui s’exécute à l’import du code qui s’exécute uniquement quand le fichier est lancé directement
  3. À créer une classe principale
  4. À définir le point d’entrée obligatoire de Python

b)__name__ vaut "__main__" quand le fichier est lancé directement, et "<nom_du_module>" quand il est importé. On met dans ce bloc les tests ou le point d’entrée du script.

Question 7

Quelle syntaxe est déconseillée ?

  1. import math
  2. from math import pi, sqrt
  3. import math as m
  4. from math import *

d) from math import * — cette forme importe tous les noms du module dans le namespace courant. Elle peut créer des conflits silencieux (une fonction sqrt locale écrasée par celle de math, par exemple) et rend le code moins lisible.

À n’utiliser qu’exceptionnellement, par exemple pour un module de constantes connues (comme tkinter.constants).


✏️ Exercice 7.1 — Module geometrie.py

Créez un fichier geometrie.py contenant :

  • aire_rectangle(l, w) — aire d’un rectangle.
  • aire_cercle(r) — aire d’un disque.
  • aire_triangle(base, hauteur) — aire d’un triangle.
  • Un bloc if __name__ == "__main__": qui teste les 3 fonctions.

Puis, dans un fichier séparé, importez ce module et utilisez ses fonctions.

Créer deux fichiers :

  1. geometrie.py — le module.
  2. main.py — qui importe et utilise geometrie.
"""Module de calculs géométriques simples."""

from math import pi


def aire_rectangle(longueur: float, largeur: float) -> float:
    """Calcule l'aire d'un rectangle."""
    return longueur * largeur


def aire_cercle(rayon: float) -> float:
    """Calcule l'aire d'un disque de rayon donné."""
    return pi * rayon ** 2


def aire_triangle(base: float, hauteur: float) -> float:
    """Calcule l'aire d'un triangle (base × hauteur / 2)."""
    return base * hauteur / 2


if __name__ == "__main__":
    print("Tests du module geometrie")
    print(f"  Rectangle 3×4 : {aire_rectangle(3, 4)}")
    print(f"  Cercle r=5    : {aire_cercle(5):.2f}")
    print(f"  Triangle 6×4  : {aire_triangle(6, 4)}")
from geometrie import aire_rectangle, aire_cercle, aire_triangle

# Salon 4m × 5m
print(f"Salon : {aire_rectangle(4, 5)} m²")

# Disque de rayon 2m
print(f"Disque : {aire_cercle(2):.2f} m²")

# Triangle de base 3m et hauteur 4m
print(f"Triangle : {aire_triangle(3, 4)} m²")

On simule les deux fichiers en définissant les fonctions directement :

from math import pi

def aire_rectangle(l, w):
    return l * w

def aire_cercle(r):
    return pi * r ** 2

def aire_triangle(b, h):
    return b * h / 2

print(f"Rectangle 3×4 : {aire_rectangle(3, 4)}")
print(f"Cercle r=5    : {aire_cercle(5):.2f}")
print(f"Triangle 6×4  : {aire_triangle(6, 4)}")
Rectangle 3×4 : 12
Cercle r=5    : 78.54
Triangle 6×4  : 12.0

✏️ Exercice 7.2 — Simulation de lancers de dé

Avec le module random, simulez 1 000 lancers d’un dé à 6 faces et affichez combien de fois chaque face est sortie. Vérifiez que la distribution est raisonnablement uniforme (environ 167 par face).

import random

# Simuler 1000 lancers et compter chaque face
...

# Afficher le résultat
for face, nombre in sorted(compteur.items()):
    print(f"Face {face} : {nombre} fois")
import random

random.seed(42)

compteur = {i: 0 for i in range(1, 7)}
for _ in range(1000):
    face = random.randint(1, 6)
    compteur[face] += 1

for face, nombre in sorted(compteur.items()):
    print(f"Face {face} : {nombre} fois")
Face 1 : 166 fois
Face 2 : 172 fois
Face 3 : 162 fois
Face 4 : 165 fois
Face 5 : 160 fois
Face 6 : 175 fois

Une alternative plus Pythonique qu’on verra mieux en Partie 3 :

import random
from collections import Counter

random.seed(42)

lancers = random.choices([1, 2, 3, 4, 5, 6], k=1000)
compteur = Counter(lancers)

for face in sorted(compteur):
    print(f"Face {face} : {compteur[face]} fois")
Face 1 : 151 fois
Face 2 : 178 fois
Face 3 : 151 fois
Face 4 : 173 fois
Face 5 : 169 fois
Face 6 : 178 fois

✏️ Exercice 7.3 — Jours jusqu’à une date

Écrivez une fonction jours_restants(date_cible) qui renvoie le nombre de jours entre aujourd’hui et une date cible (au format "JJ/MM/AAAA"). Si la date est passée, renvoyez un nombre négatif.

from datetime import date, datetime

def jours_restants(date_cible_str):
    ...

print(jours_restants("31/12/2025"))
print(jours_restants("01/01/2020"))
from datetime import date, datetime

def jours_restants(date_cible_str):
    """Renvoie le nombre de jours jusqu'à la date cible.

    Arguments:
        date_cible_str: date au format "JJ/MM/AAAA".

    Renvoie:
        Nombre de jours (int). Négatif si la date est passée.
    """
    cible = datetime.strptime(date_cible_str, "%d/%m/%Y").date()
    delta = cible - date.today()
    return delta.days

# Tests (le résultat dépend de la date du jour)
print(f"Jusqu'au 31/12/2030 : {jours_restants('31/12/2030')} jours")
print(f"Jusqu'au 01/01/2020 : {jours_restants('01/01/2020')} jours (négatif)")
Jusqu'au 31/12/2030 : 1714 jours
Jusqu'au 01/01/2020 : -2303 jours (négatif)

✏️ Exercice 7.4 — Statistiques sur une simulation

Simulez 100 lancers de deux dés à 6 faces, stockez la somme dans une liste. Calculez avec statistics :

  • La moyenne.
  • La médiane.
  • L’écart-type.
  • Le mode (somme la plus fréquente).
import random
import statistics

random.seed(42)

# Simuler 100 lancers de 2 dés, enregistrer les sommes
sommes = []
...

# Afficher les stats
import random
import statistics

random.seed(42)

sommes = []
for _ in range(100):
    d1 = random.randint(1, 6)
    d2 = random.randint(1, 6)
    sommes.append(d1 + d2)

print(f"Moyenne : {statistics.mean(sommes):.2f}")
print(f"Médiane : {statistics.median(sommes)}")
print(f"Écart-type : {statistics.stdev(sommes):.2f}")
print(f"Mode : {statistics.mode(sommes)}")
Moyenne : 7.00
Médiane : 7.0
Écart-type : 2.34
Mode : 7
  • Moyenne théorique : 7 (3.5 + 3.5).
  • Mode théorique : 7 (somme la plus probable avec 2 dés).
  • Médiane théorique : 7.

Avec 100 lancers, on s’approche de ces valeurs sans forcément les atteindre exactement.


À retenir

Points clés du chapitre
  1. La bibliothèque standard Python est immense : math, random, datetime, statistics, time, os, sys, json, csv, etc.
  2. math.sin() attend des radians, pas des degrés.
  3. math.floor() arrondit vers le bas (et donc floor(-3.2) == -4).
  4. random.choices → avec remise, random.sample → sans remise, random.shuffle → en place.
  5. datetime pour les dates + timedelta pour les durées (arithmétique).
  6. strftime = format (datetime → str), strptime = parse (str → datetime).
  7. Un module = un fichier .py importable. Placez le code de test dans if __name__ == "__main__":.
  8. dir(obj) liste les attributs/méthodes ; help(obj) affiche la doc.
  9. Évitez from module import * qui pollue le namespace.

← Chapitre précédent : Logique booléenneChapitre suivant : Algorithmes →