2026-06-18 19:03:42 +02:00
# TP : Créer son premier package Python - MathTools
2026-01-17 23:10:49 +01:00
> **Thème** : Modularité, documentation et tests
---
## Contexte
En 2026, Python reste le langage le plus populaire au monde grâce à son écosystème de packages. Des millions de développeurs partagent leur code via PyPI (Python Package Index).
Dans ce TP, vous allez créer votre propre **mini-package** : une bibliothèque d'outils mathématiques appelée **MathTools** . Vous apprendrez à :
- Structurer un projet en modules
- Documenter proprement avec des docstrings
- Tester automatiquement avec doctest
- Créer un point d'entrée principal
---
## Partie 1 : Structure du projet
### Organisation des fichiers
Créez la structure de dossiers suivante :
```
mathtools/
├── __init__.py
├── geometrie.py
├── statistiques.py
├── conversion.py
└── main.py
```
### Le fichier `__init__.py`
Ce fichier spécial indique à Python que le dossier est un **package** . Il peut rester vide ou contenir des imports.
```python
# mathtools/__init__.py
"""
MathTools - Une bibliothèque d'outils mathématiques.
Modules disponibles :
- geometrie : calculs géométriques (aire, périmètre, volume)
- statistiques : calculs statistiques (moyenne, médiane, écart-type)
- conversion : conversions d'unités (température, distance, poids)
"""
__version__ = "1.0.0"
__author__ = "Votre Nom"
```
---
## Partie 2 : Module géométrie
### Exercice 1 : Créer le module `geometrie.py`
Implémentez les fonctions suivantes avec leur **docstring** et **doctest** :
```python
# mathtools/geometrie.py
"""Module de calculs géométriques."""
import math
import doctest
def aire_rectangle ( longueur , largeur ):
"""
Calcule l'aire d'un rectangle.
:param longueur: (float) la longueur du rectangle
:param largeur: (float) la largeur du rectangle
:return: (float) l'aire du rectangle
:CU: longueur > 0 et largeur > 0
Exemple:
>>> aire_rectangle(5, 3)
15
>>> aire_rectangle(2.5, 4)
10.0
"""
# À compléter
pass
def aire_cercle ( rayon ):
"""
Calcule l'aire d'un cercle.
:param rayon: (float) le rayon du cercle
:return: (float) l'aire du cercle
:CU: rayon > 0
Exemple:
>>> round(aire_cercle(1), 4)
3.1416
>>> round(aire_cercle(2), 4)
12.5664
"""
# À compléter
pass
def perimetre_rectangle ( longueur , largeur ):
"""
Calcule le périmètre d'un rectangle.
Exemple:
>>> perimetre_rectangle(5, 3)
16
"""
# À compléter (ajoutez la docstring complète)
pass
def volume_sphere ( rayon ):
"""
Calcule le volume d'une sphère.
Formule : V = (4/3) * π * r³
Exemple:
>>> round(volume_sphere(1), 4)
4.1888
"""
# À compléter (ajoutez la docstring complète)
pass
def hypotenuse ( a , b ):
"""
Calcule l'hypoténuse d'un triangle rectangle.
Utilise le théorème de Pythagore : c² = a² + b²
Exemple:
>>> hypotenuse(3, 4)
5.0
>>> hypotenuse(5, 12)
13.0
"""
# À compléter
pass
if __name__ == "__main__" :
doctest . testmod ( verbose = True )
```
---
## Partie 3 : Module statistiques
### Exercice 2 : Créer le module `statistiques.py`
```python
# mathtools/statistiques.py
"""Module de calculs statistiques."""
import doctest
def moyenne ( liste ):
"""
Calcule la moyenne d'une liste de nombres.
:param liste: (list) une liste de nombres
:return: (float) la moyenne
:CU: liste non vide
Exemple:
>>> moyenne([10, 20, 30])
20.0
>>> moyenne([15, 18, 12, 9])
13.5
"""
# À compléter
pass
def mediane ( liste ):
"""
Calcule la médiane d'une liste de nombres.
La médiane est la valeur centrale d'une liste triée.
:param liste: (list) une liste de nombres
:return: (float) la médiane
:CU: liste non vide
Exemple:
>>> mediane([1, 2, 3, 4, 5])
3
>>> mediane([1, 2, 3, 4])
2.5
"""
# À compléter
pass
def variance ( liste ):
"""
Calcule la variance d'une liste de nombres.
Variance = moyenne des carrés des écarts à la moyenne.
Exemple:
>>> variance([2, 4, 4, 4, 5, 5, 7, 9])
4.0
"""
# À compléter
pass
def ecart_type ( liste ):
"""
Calcule l'écart-type d'une liste de nombres.
Écart-type = racine carrée de la variance.
Exemple:
>>> ecart_type([2, 4, 4, 4, 5, 5, 7, 9])
2.0
"""
# À compléter
pass
def minimum ( liste ):
"""
Retourne le minimum d'une liste (sans utiliser min()).
Exemple:
>>> minimum([5, 2, 8, 1, 9])
1
"""
# À compléter
pass
def maximum ( liste ):
"""
Retourne le maximum d'une liste (sans utiliser max()).
Exemple:
>>> maximum([5, 2, 8, 1, 9])
9
"""
# À compléter
pass
if __name__ == "__main__" :
doctest . testmod ( verbose = True )
```
---
## Partie 4 : Module conversion
### Exercice 3 : Créer le module `conversion.py`
```python
# mathtools/conversion.py
"""Module de conversions d'unités."""
import doctest
# --- Températures ---
def celsius_vers_fahrenheit ( celsius ):
"""
Convertit des degrés Celsius en Fahrenheit.
Formule : F = C × 9/5 + 32
Exemple:
>>> celsius_vers_fahrenheit(0)
32.0
>>> celsius_vers_fahrenheit(100)
212.0
>>> celsius_vers_fahrenheit(-40)
-40.0
"""
# À compléter
pass
def fahrenheit_vers_celsius ( fahrenheit ):
"""
Convertit des degrés Fahrenheit en Celsius.
Formule : C = (F - 32) × 5/9
Exemple:
>>> fahrenheit_vers_celsius(32)
0.0
>>> fahrenheit_vers_celsius(212)
100.0
"""
# À compléter
pass
# --- Distances ---
def km_vers_miles ( km ):
"""
Convertit des kilomètres en miles.
1 mile = 1.60934 km
Exemple:
>>> round(km_vers_miles(10), 2)
6.21
"""
# À compléter
pass
def miles_vers_km ( miles ):
"""
Convertit des miles en kilomètres.
Exemple:
>>> round(miles_vers_km(10), 2)
16.09
"""
# À compléter
pass
# --- Poids ---
def kg_vers_livres ( kg ):
"""
Convertit des kilogrammes en livres.
1 livre = 0.453592 kg
Exemple:
>>> round(kg_vers_livres(1), 2)
2.2
"""
# À compléter
pass
# --- Informatique ---
def octets_vers_kilo ( octets ):
"""
Convertit des octets en kilooctets (1 Ko = 1024 octets).
Exemple:
>>> octets_vers_kilo(2048)
2.0
"""
# À compléter
pass
def bits_vers_octets ( bits ):
"""
Convertit des bits en octets (1 octet = 8 bits).
Exemple:
>>> bits_vers_octets(64)
8.0
"""
# À compléter
pass
if __name__ == "__main__" :
doctest . testmod ( verbose = True )
```
---
## Partie 5 : Programme principal
### Exercice 4 : Créer `main.py`
Ce fichier sera le point d'entrée de votre package. Il propose un menu interactif.
```python
# mathtools/main.py
"""Programme principal de MathTools."""
from geometrie import *
from statistiques import *
from conversion import *
def menu ():
"""Affiche le menu principal."""
print ( " \n " + "=" * 40 )
print ( " MATHTOOLS v1.0.0" )
print ( "=" * 40 )
print ( "1. Géométrie" )
print ( "2. Statistiques" )
print ( "3. Conversions" )
print ( "0. Quitter" )
print ( "=" * 40 )
def menu_geometrie ():
"""Sous-menu géométrie."""
print ( " \n --- GÉOMÉTRIE ---" )
print ( "1. Aire d'un rectangle" )
print ( "2. Aire d'un cercle" )
print ( "3. Hypoténuse" )
print ( "0. Retour" )
choix = input ( "Votre choix : " )
if choix == "1" :
l = float ( input ( "Longueur : " ))
L = float ( input ( "Largeur : " ))
print ( f "Aire = { aire_rectangle ( l , L ) } " )
elif choix == "2" :
r = float ( input ( "Rayon : " ))
print ( f "Aire = { round ( aire_cercle ( r ), 4 ) } " )
elif choix == "3" :
a = float ( input ( "Côté a : " ))
b = float ( input ( "Côté b : " ))
print ( f "Hypoténuse = { hypotenuse ( a , b ) } " )
def menu_statistiques ():
"""Sous-menu statistiques."""
print ( " \n --- STATISTIQUES ---" )
print ( "Entrez vos valeurs séparées par des espaces :" )
valeurs = input ( "> " )
liste = [ float ( x ) for x in valeurs . split ()]
print ( f "Moyenne : { moyenne ( liste ) } " )
print ( f "Médiane : { mediane ( liste ) } " )
print ( f "Min : { minimum ( liste ) } " )
print ( f "Max : { maximum ( liste ) } " )
def menu_conversions ():
"""Sous-menu conversions."""
print ( " \n --- CONVERSIONS ---" )
print ( "1. Celsius → Fahrenheit" )
print ( "2. Fahrenheit → Celsius" )
print ( "3. Km → Miles" )
print ( "0. Retour" )
choix = input ( "Votre choix : " )
if choix == "1" :
c = float ( input ( "Température en °C : " ))
print ( f " { c } °C = { celsius_vers_fahrenheit ( c ) } °F" )
elif choix == "2" :
f = float ( input ( "Température en °F : " ))
print ( f " { f } °F = { fahrenheit_vers_celsius ( f ) } °C" )
elif choix == "3" :
km = float ( input ( "Distance en km : " ))
print ( f " { km } km = { round ( km_vers_miles ( km ), 2 ) } miles" )
def main ():
"""Boucle principale."""
while True :
menu ()
choix = input ( "Votre choix : " )
if choix == "1" :
menu_geometrie ()
elif choix == "2" :
menu_statistiques ()
elif choix == "3" :
menu_conversions ()
elif choix == "0" :
print ( "Au revoir !" )
break
else :
print ( "Choix invalide." )
if __name__ == "__main__" :
main ()
```
---
## Partie 6 : Tests et validation
### Exercice 5 : Tester tous les modules
Exécutez chaque module pour vérifier que tous les doctests passent :
```bash
cd mathtools
python geometrie.py
python statistiques.py
python conversion.py
```
Tous les tests doivent afficher `ok` .
### Exercice 6 : Utiliser le package
Dans un nouveau fichier `test_mathtools.py` situé **en dehors** du dossier mathtools :
```python
# test_mathtools.py
from mathtools.geometrie import aire_cercle , hypotenuse
from mathtools.statistiques import moyenne , ecart_type
from mathtools.conversion import celsius_vers_fahrenheit
# Tests
print ( "Aire cercle r=5 :" , round ( aire_cercle ( 5 ), 2 ))
print ( "Hypoténuse 3,4 :" , hypotenuse ( 3 , 4 ))
print ( "Moyenne [10,20,30] :" , moyenne ([ 10 , 20 , 30 ]))
print ( "20°C en Fahrenheit :" , celsius_vers_fahrenheit ( 20 ))
```
---
## Bonus : Documentation avancée
### Générer une documentation HTML
Installez `pydoc` (inclus avec Python) et générez la doc :
```bash
python -m pydoc -w mathtools.geometrie
python -m pydoc -w mathtools.statistiques
```
Cela génère des fichiers HTML consultables dans un navigateur.
### Ajouter des assertions
Améliorez vos fonctions avec des vérifications :
```python
def aire_cercle ( rayon ):
assert rayon > 0 , "Le rayon doit être strictement positif"
return math . pi * rayon ** 2
```
---
## Résumé des notions
| Concept | Application dans ce TP |
|---------|------------------------|
| Module | Fichier .py contenant des fonctions |
| Package | Dossier avec `__init__.py` |
| Import | `from module import fonction` |
| Docstring | Documentation des fonctions |
| Doctest | Tests dans la documentation |
| `__name__` | Permet d'exécuter un module seul |
---
## Pour aller plus loin
- **pytest** : Framework de tests plus puissant que doctest
- **Sphinx** : Générateur de documentation professionnelle
- **PyPI** : Publier son package pour le monde entier
- **pip** : Installer des packages depuis PyPI
---
2026-07-02 15:01:24 +02:00
Auteurs : Florian Mathieu, Enzo Frémeaux, Timothée Decoster
2026-01-17 23:10:49 +01:00
Licence CC BY NC
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.