ajout de tous les cours et TP préparés cet été
This commit is contained in:
320
Paradigmes/Corrige_Exercice.md
Normal file
320
Paradigmes/Corrige_Exercice.md
Normal file
@@ -0,0 +1,320 @@
|
||||
# Corrigé de l'exercice — Cuisson des pâtes
|
||||
|
||||
---
|
||||
|
||||
## Énoncé
|
||||
|
||||
Nous voulons faire cuire des pâtes. Écrire la recette sous forme de code Python selon trois paradigmes différents.
|
||||
|
||||
---
|
||||
|
||||
## Version impérative
|
||||
|
||||
Liste d'instructions étape par étape, avec modification d'état.
|
||||
|
||||
```python
|
||||
# Version impérative : liste d'instructions étape par étape
|
||||
|
||||
def cuire_pates_imperatif():
|
||||
"""Fait cuire des pâtes de manière impérative."""
|
||||
|
||||
# État initial
|
||||
eau = "froide"
|
||||
pates = "crues"
|
||||
sel = False
|
||||
|
||||
# Étape 1 : Remplir la casserole
|
||||
print("Remplissage de la casserole...")
|
||||
quantite_eau = 1.5 # litres
|
||||
|
||||
# Étape 2 : Faire chauffer l'eau
|
||||
print("Chauffage de l'eau...")
|
||||
eau = "chaude"
|
||||
|
||||
# Étape 3 : Attendre l'ébullition
|
||||
print("Attente de l'ébullition...")
|
||||
eau = "bouillante"
|
||||
|
||||
# Étape 4 : Saler l'eau
|
||||
print("Ajout du sel...")
|
||||
sel = True
|
||||
|
||||
# Étape 5 : Ajouter les pâtes
|
||||
print("Ajout des pâtes...")
|
||||
pates = "en cuisson"
|
||||
|
||||
# Étape 6 : Attendre le temps de cuisson
|
||||
temps_cuisson = 10 # minutes
|
||||
print(f"Cuisson pendant {temps_cuisson} minutes...")
|
||||
|
||||
# Étape 7 : Égoutter
|
||||
print("Égouttage des pâtes...")
|
||||
pates = "cuites"
|
||||
|
||||
print(f"Résultat : pâtes {pates}")
|
||||
return pates
|
||||
|
||||
|
||||
# Exécution
|
||||
resultat = cuire_pates_imperatif()
|
||||
```
|
||||
|
||||
**Caractéristiques :**
|
||||
- Modification d'état (variables `eau`, `pates`, `sel`)
|
||||
- Instructions séquentielles
|
||||
- Effets de bord (print)
|
||||
|
||||
---
|
||||
|
||||
## Version fonctionnelle
|
||||
|
||||
Une fonction pure qui prend un état et retourne un nouvel état, sans modification.
|
||||
|
||||
```python
|
||||
# Version fonctionnelle : fonctions pures et composition
|
||||
|
||||
def remplir_casserole(etat):
|
||||
"""Retourne un nouvel état avec la casserole remplie."""
|
||||
return {**etat, "eau": "froide", "quantite_eau": 1.5}
|
||||
|
||||
|
||||
def chauffer_eau(etat):
|
||||
"""Retourne un nouvel état avec l'eau chauffée."""
|
||||
return {**etat, "eau": "chaude"}
|
||||
|
||||
|
||||
def faire_bouillir(etat):
|
||||
"""Retourne un nouvel état avec l'eau bouillante."""
|
||||
return {**etat, "eau": "bouillante"}
|
||||
|
||||
|
||||
def saler(etat):
|
||||
"""Retourne un nouvel état avec le sel ajouté."""
|
||||
return {**etat, "sel": True}
|
||||
|
||||
|
||||
def ajouter_pates(etat):
|
||||
"""Retourne un nouvel état avec les pâtes en cuisson."""
|
||||
return {**etat, "pates": "en cuisson"}
|
||||
|
||||
|
||||
def cuire(etat, duree):
|
||||
"""Retourne un nouvel état après cuisson."""
|
||||
return {**etat, "temps_cuisson": duree, "pates": "cuites"}
|
||||
|
||||
|
||||
def egoutter(etat):
|
||||
"""Retourne un nouvel état avec les pâtes égouttées."""
|
||||
return {**etat, "egouttees": True}
|
||||
|
||||
|
||||
# Composition de fonctions
|
||||
def cuire_pates_fonctionnel(etat_initial):
|
||||
"""
|
||||
Fait cuire des pâtes de manière fonctionnelle.
|
||||
Chaque étape retourne un nouvel état sans modifier l'ancien.
|
||||
"""
|
||||
etat = remplir_casserole(etat_initial)
|
||||
etat = chauffer_eau(etat)
|
||||
etat = faire_bouillir(etat)
|
||||
etat = saler(etat)
|
||||
etat = ajouter_pates(etat)
|
||||
etat = cuire(etat, 10)
|
||||
etat = egoutter(etat)
|
||||
return etat
|
||||
|
||||
|
||||
# Version encore plus fonctionnelle avec reduce
|
||||
import functools
|
||||
|
||||
def cuire_pates_reduce(etat_initial):
|
||||
"""Version avec reduce pour composer les fonctions."""
|
||||
etapes = [
|
||||
remplir_casserole,
|
||||
chauffer_eau,
|
||||
faire_bouillir,
|
||||
saler,
|
||||
ajouter_pates,
|
||||
lambda e: cuire(e, 10),
|
||||
egoutter
|
||||
]
|
||||
return functools.reduce(lambda etat, f: f(etat), etapes, etat_initial)
|
||||
|
||||
|
||||
# Exécution
|
||||
etat_initial = {"pates": "crues", "sel": False}
|
||||
resultat = cuire_pates_fonctionnel(etat_initial)
|
||||
print(f"État final : {resultat}")
|
||||
|
||||
# Vérification : l'état initial n'a pas été modifié
|
||||
print(f"État initial préservé : {etat_initial}")
|
||||
```
|
||||
|
||||
**Caractéristiques :**
|
||||
- Pas de modification d'état (immutabilité)
|
||||
- Fonctions pures (même entrée → même sortie)
|
||||
- Composition de fonctions
|
||||
- L'état initial n'est jamais modifié
|
||||
|
||||
---
|
||||
|
||||
## Version orientée objet
|
||||
|
||||
Une classe `Pates` avec des attributs et une méthode `cuire()`.
|
||||
|
||||
```python
|
||||
# Version orientée objet : classe Pates avec méthode cuire()
|
||||
|
||||
class Casserole:
|
||||
"""Représente une casserole pour la cuisson."""
|
||||
|
||||
def __init__(self):
|
||||
self.eau = None
|
||||
self.temperature = "froide"
|
||||
self.sel = False
|
||||
|
||||
def remplir(self, quantite=1.5):
|
||||
"""Remplit la casserole d'eau."""
|
||||
self.eau = quantite
|
||||
print(f"Casserole remplie avec {quantite}L d'eau")
|
||||
|
||||
def chauffer(self):
|
||||
"""Chauffe l'eau jusqu'à ébullition."""
|
||||
self.temperature = "chaude"
|
||||
print("Chauffage en cours...")
|
||||
self.temperature = "bouillante"
|
||||
print("L'eau bout !")
|
||||
|
||||
def saler(self):
|
||||
"""Ajoute du sel dans l'eau."""
|
||||
self.sel = True
|
||||
print("Sel ajouté")
|
||||
|
||||
|
||||
class Pates:
|
||||
"""Représente des pâtes à cuire."""
|
||||
|
||||
def __init__(self, type_pates="spaghetti", quantite=500):
|
||||
self.type = type_pates
|
||||
self.quantite = quantite # en grammes
|
||||
self.etat = "crues"
|
||||
self.temps_cuisson = 0
|
||||
|
||||
def cuire(self, casserole, duree=10):
|
||||
"""
|
||||
Fait cuire les pâtes dans une casserole.
|
||||
|
||||
:param casserole: (Casserole) la casserole à utiliser
|
||||
:param duree: (int) temps de cuisson en minutes
|
||||
"""
|
||||
# Vérifications
|
||||
if casserole.eau is None:
|
||||
raise ValueError("La casserole doit contenir de l'eau !")
|
||||
if casserole.temperature != "bouillante":
|
||||
raise ValueError("L'eau doit être bouillante !")
|
||||
|
||||
print(f"Ajout de {self.quantite}g de {self.type} dans la casserole")
|
||||
self.etat = "en cuisson"
|
||||
|
||||
print(f"Cuisson pendant {duree} minutes...")
|
||||
self.temps_cuisson = duree
|
||||
|
||||
self.etat = "cuites"
|
||||
print(f"Les {self.type} sont cuites !")
|
||||
|
||||
def egoutter(self):
|
||||
"""Égoutte les pâtes."""
|
||||
if self.etat != "cuites":
|
||||
raise ValueError("Les pâtes doivent être cuites avant d'être égouttées !")
|
||||
print("Égouttage des pâtes...")
|
||||
self.etat = "prêtes"
|
||||
|
||||
def __str__(self):
|
||||
return f"Pates({self.type}, {self.quantite}g, état={self.etat})"
|
||||
|
||||
|
||||
# Exécution
|
||||
def preparer_pates_oo():
|
||||
"""Prépare des pâtes en utilisant la POO."""
|
||||
|
||||
# Création des objets
|
||||
casserole = Casserole()
|
||||
pates = Pates("fusilli", 400)
|
||||
|
||||
print(f"Début : {pates}")
|
||||
|
||||
# Préparation de la casserole
|
||||
casserole.remplir(2.0)
|
||||
casserole.chauffer()
|
||||
casserole.saler()
|
||||
|
||||
# Cuisson des pâtes
|
||||
pates.cuire(casserole, duree=12)
|
||||
pates.egoutter()
|
||||
|
||||
print(f"Fin : {pates}")
|
||||
return pates
|
||||
|
||||
|
||||
resultat = preparer_pates_oo()
|
||||
```
|
||||
|
||||
**Caractéristiques :**
|
||||
- Encapsulation (attributs et méthodes regroupés)
|
||||
- Objets avec état interne
|
||||
- Interactions entre objets (Pates et Casserole)
|
||||
- Méthodes qui modifient l'état de l'objet
|
||||
|
||||
---
|
||||
|
||||
## Tableau comparatif
|
||||
|
||||
| Aspect | Impératif | Fonctionnel | Orienté Objet |
|
||||
|--------|-----------|-------------|---------------|
|
||||
| **État** | Variables modifiées | États immuables | Attributs d'objets |
|
||||
| **Données** | Variables simples | Dictionnaires/tuples | Objets |
|
||||
| **Actions** | Instructions séquentielles | Fonctions composées | Méthodes |
|
||||
| **Modification** | Sur place | Nouvel état retourné | Via méthodes |
|
||||
| **Réutilisabilité** | Faible | Moyenne | Forte |
|
||||
| **Testabilité** | Difficile | Facile | Moyenne |
|
||||
|
||||
---
|
||||
|
||||
## Bonus : Version lambda
|
||||
|
||||
```python
|
||||
# Version ultra-fonctionnelle avec lambdas et reduce
|
||||
|
||||
import functools
|
||||
|
||||
# Chaque étape est une lambda qui transforme l'état
|
||||
etapes = [
|
||||
lambda e: {**e, "eau": 1.5},
|
||||
lambda e: {**e, "temperature": "bouillante"},
|
||||
lambda e: {**e, "sel": True},
|
||||
lambda e: {**e, "pates": "en cuisson"},
|
||||
lambda e: {**e, "temps": 10, "pates": "cuites"},
|
||||
lambda e: {**e, "egouttees": True}
|
||||
]
|
||||
|
||||
# Composition avec reduce
|
||||
cuire_pates_lambda = lambda etat: functools.reduce(
|
||||
lambda e, f: f(e),
|
||||
etapes,
|
||||
etat
|
||||
)
|
||||
|
||||
# Exécution
|
||||
resultat = cuire_pates_lambda({"pates": "crues"})
|
||||
print(resultat)
|
||||
# {'pates': 'cuites', 'eau': 1.5, 'temperature': 'bouillante',
|
||||
# 'sel': True, 'temps': 10, 'egouttees': True}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Auteurs : Florian Mathieu, Enzo Frémeaux, Thimothée Decooster
|
||||
|
||||
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>.
|
||||
Reference in New Issue
Block a user