Un cap pour ce chapitre
Ce que vous saurez faire
- Reconnaître des caractéristiques impératives, fonctionnelles et objet.
- Comparer plusieurs solutions d’un problème.
- Justifier un choix sans déclarer un paradigme universellement supérieur.
Décrire des changements avec l’impératif
Dans une approche impérative, le programme précise une suite d’instructions qui transforment un état. Un accumulateur initialement nul peut recevoir successivement les carrés des valeurs d’une liste. Les affectations, conditions et boucles rendent explicite l’ordre des opérations.
total = 0
for x in [2, 3, 4]:
total = total + x * xCette forme est naturelle pour suivre une procédure étape par étape. Pour comprendre le résultat, on suit l’évolution de total : zéro, quatre, treize, puis vingt-neuf. Les états intermédiaires sont une aide, mais deviennent difficiles à suivre si beaucoup de variables partagées changent à plusieurs endroits.
Composer des transformations avec le fonctionnel
Une approche fonctionnelle privilégie l’expression de résultats par des fonctions et leur composition. Une fonction pure renvoie un résultat déterminé par ses arguments et n’a pas d’effet de bord observable. Elle est facile à tester isolément : les mêmes arguments donnent le même résultat dans le modèle considéré.
def carre(x):
return x * x
total = sum(carre(x) for x in [2, 3, 4])Cette expression met en avant « transformer chaque valeur puis additionner ». Python permet ce style sans être un langage exclusivement fonctionnel. Une fonction qui modifie une liste reçue n’est pas pure simplement parce qu’elle est écrite avec def.
Regrouper état et opérations avec les objets
Le paradigme objet organise des entités possédant des attributs et des méthodes. Un compteur peut conserver une valeur et proposer une méthode incrementer. Plusieurs instances partagent les mêmes règles tout en conservant des états distincts. Cette organisation convient notamment à la modélisation d’entités qui évoluent et interagissent.
Pour reprendre le même calcul de somme de carrés, un objet peut conserver le total et proposer une opération d’ajout. Chaque instance commence avec son propre total nul.
class SommeCarres:
def __init__(self):
self.total = 0
def ajouter(self, valeur):
self.total += valeur * valeur
calcul = SommeCarres()
for valeur in [2, 3, 4]:
calcul.ajouter(valeur)
print(calcul.total) # 29Un objet n’est pas seulement un dictionnaire déguisé : son interface peut exprimer les opérations autorisées et préserver des règles. Pour une pile, empiler et dépiler définissent un usage cohérent. En NSI, classes, attributs, objets et méthodes suffisent à travailler cette approche ; héritage et polymorphisme ne sont pas des exigences de cette introduction.
Choisir en fonction de la tâche
Une petite boucle de recherche peut être très claire en impératif. Une chaîne de transformations de données peut se lire naturellement en style fonctionnel. Une simulation de véhicules, de capteurs ou de joueurs peut bénéficier d’objets représentant les entités. Ces exemples donnent des raisons de choisir, pas des règles absolues.
Un même programme peut combiner plusieurs paradigmes : un objet expose une méthode dont le corps utilise une boucle et appelle une fonction pure. Le langage autorise des styles ; il ne suffit pas de connaître son nom pour classer chaque programme. Pour justifier une réponse, citez des caractéristiques observables plutôt qu’une étiquette isolée.
Choisir un style implique aussi de préciser ce qui change et ce qui reste observable. Pour comparer deux versions, fixez la même entrée, le même résultat attendu et les mêmes obligations sur la mutation. Une fonction qui renvoie la bonne somme mais efface l’entrée ne respecte pas forcément le même contrat.
Exemple suivi : trois organisations pour le même traitement
On veut totaliser les carrés des seules valeurs positives de [-2,3,0,4]. En impératif, un accumulateur part de zéro et reçoit le carré de chaque valeur vérifiant x > 0. Il devient 9 puis 25. En style fonctionnel, on exprime la transformation puis l’agrégation avec sum(x*x for x in valeurs if x > 0). Les valeurs négatives et zéro sont filtrées ; les carrés restants sont additionnés.
En objet, une instance peut conserver un total et proposer une méthode qui ajoute une mesure positive après l’avoir mise au carré. Ce choix devient utile si les mesures arrivent successivement et si plusieurs calculs indépendants coexistent. Pour un calcul unique de quatre nombres, la classe ajoute des éléments à comprendre ; elle ne garantit pas une meilleure solution. Comparez la correspondance avec le problème, l’interface, les effets observables et la facilité des tests.
| Organisation | Information mise en avant | État conservé |
|---|---|---|
| Impérative | Accumuler au fil du parcours | Total local |
| Fonctionnelle | Filtrer, transformer, agréger | Résultat calculé depuis les arguments |
| Objet | Ajouter des mesures à une instance | Total propre à chaque instance |
Exemple suivi : repérer un état caché
Une fonction reçoit x, ajoute x à une liste globale puis renvoie la somme de cette liste. Avec une liste globale vide, l’appel sur 2 renvoie 2 ; le second appel sur 2 renvoie 4. Le résultat dépend donc de l’histoire du programme. Une fonction carre(x) renvoyant x*x conserve au contraire le même résultat pour les mêmes arguments et ne modifie aucun état extérieur.
Pour rendre le premier traitement explicite, on peut recevoir une liste en paramètre et renvoyer une nouvelle liste contenant l’élément ajouté. L’appelant choisit ensuite de conserver ou non ce nouvel état. On peut aussi encapsuler l’historique dans un objet dont l’interface annonce la mutation. Les deux organisations rendent le changement identifiable, mais seule la première peut être pure si elle ne modifie pas l’entrée. La présence de def, d’une compréhension ou d’un objet ne suffit pas à conclure sans examiner les effets.
À vous de faire varier les choses
Reconnaissez le choix de conception
Classez la caractéristique dominante décrite, sans supposer que les autres paradigmes sont interdits dans le programme.
Lire les associations expliquées
- Un accumulateur est modifié à chaque tour de boucle. : Impératif
- Le raisonnement suit une succession de changements d’état.
- Une fonction pure transforme une valeur sans modifier son environnement. : Fonctionnel
- La transformation est décrite par ses arguments et son résultat.
- Chaque joueur est une instance avec son score et ses méthodes. : Objet
- Les états et opérations sont regroupés par entité.
- Une suite de fonctions transforme un tableau puis agrège les résultats. : Fonctionnel
- La composition des transformations domine cette description.
- Des instructions déplacent une case active en modifiant ses coordonnées. : Impératif
- La procédure est décrite par modifications successives.
- La classe Pile propose empiler et dépiler pour plusieurs instances. : Objet
- Une interface et des états sont portés par des objets.
- Une simulation crée deux capteurs dont les historiques évoluent séparément au moyen des mêmes méthodes. : Objet
- La classe porte les règles communes ; chaque instance conserve son état. Les méthodes peuvent contenir des boucles.
- Une fonction reçoit les mesures et renvoie leur moyenne sans modifier l’entrée ni lire une variable globale. : Fonctionnel
- Le résultat dépend des arguments et aucun effet extérieur n’est produit. Ce contrat permet un test isolé.
- Un curseur avance dans une grille et actualise ses deux coordonnées à chaque instruction. : Impératif
- La description suit l’évolution explicite d’un état. L’existence possible d’un objet grille ne change pas la caractéristique décrite.
Justifiez une classification par les caractéristiques du code, et acceptez les combinaisons de styles.
De la compréhension à l’autonomie
À vous de résoudre
Cherchez d’abord par vous-même. Vérifiez les résultats demandés, utilisez les indices si nécessaire, puis comparez votre méthode à la correction.
Retrouver l’état modifié
Dans la boucle de somme des carrés, quelle variable matérialise l’accumulation et quelles valeurs successives prend-elle ?
Indice 1
Commencez avant la première itération.
Indice 2
Ajoutez successivement 4, 9 et 16.
Comprendre la correction
La variable total vaut 0, puis 4, puis 13, puis 29. Le programme impératif décrit les modifications successives de cet accumulateur. La valeur x change aussi au fil du parcours, mais ne conserve pas le résultat cumulé.
Reconnaître une fonction pure
Comparez f(x)=x*x et une fonction qui ajoute x à une liste globale puis renvoie sa longueur. Laquelle respecte la pureté décrite ici ?
Indice 1
Une donnée extérieure est-elle modifiée ?
Indice 2
Le résultat dépend-il seulement de x ?
Comprendre la correction
La fonction carré respecte cette pureté. L’autre modifie une liste globale et son résultat dépend de son contenu antérieur. Deux appels avec le même x peuvent donc renvoyer des longueurs différentes. Le mot fonction ne suffit pas à garantir une approche pure.
Choisir une organisation
Une simulation comporte vingt capteurs, chacun avec une mesure et une opération de mise à jour. Pourquoi une classe Capteur peut-elle être utile ?
Indice 1
Distinguez règles communes et états individuels.
Indice 2
Pensez à l’interface proposée à la simulation.
Comprendre la correction
La classe regroupe les règles de mise à jour et l’interface commune ; chaque instance conserve sa propre mesure. La simulation peut manipuler plusieurs capteurs avec les mêmes opérations sans mélanger leurs états. Une autre représentation reste possible, mais cet argument justifie ici le choix objet.
Corriger une classification trop rapide
Un élève affirme qu’une méthode contenant une boucle for prouve que le programme ne peut pas être objet. Que lui répondez-vous ?
Indice 1
Le paradigme décrit une organisation à plusieurs niveaux.
Indice 2
Le corps d’une méthode doit tout de même réaliser des opérations.
Comprendre la correction
Une méthode peut utiliser des instructions impératives tout en appartenant à une organisation objet. Les paradigmes se combinent. Il faut examiner le rôle des objets, attributs et interfaces dans l’ensemble du programme plutôt que classer tout le projet d’après une seule boucle.
Problème : comparer deux contrats
A reçoit une liste et renvoie la somme des carrés positifs sans mutation. B calcule la même somme mais supprime auparavant les valeurs négatives dans la liste reçue. Sur [-2,3,0,4], donnez le résultat des deux et les contenus conservés par l’appelant. Les fonctions sont-elles interchangeables selon le contrat de A ?
Indice 1
Le résultat numérique ne décrit pas tous les effets.
Indice 2
Une autre partie du programme peut encore utiliser les valeurs négatives.
Comprendre la correction
Les deux renvoient 25. Après A, l’appelant conserve [-2,3,0,4] ; après B, il voit [3,0,4]. B viole l’absence de mutation exigée par A. Les deux traitements ne sont donc pas interchangeables selon ce contrat, même si un test vérifiant seulement le nombre retourné les jugerait identiques.
Problème : séparer deux instances
Deux objets SommeCarres, a et b, commencent avec total=0. On appelle successivement a.ajouter(2), b.ajouter(3), a.ajouter(4). Donnez les deux totaux. Pourquoi placer un même total global derrière les deux objets serait-il contraire à l’intention ? Proposez un test distinguant les versions.
Indice 1
Chaque instance conserve son propre attribut.
Indice 2
Les carrés de 2 et 4 vont uniquement dans a.
Comprendre la correction
Les totaux attendus sont 20 pour a et 9 pour b. Un total global confondrait les deux historiques et atteindrait 29 pour les deux lectures si les méthodes y accédaient. Le scénario proposé constitue déjà un test : il vérifie les deux attributs après des appels entrelacés. Une classe utile regroupe des règles communes avec des états distincts.
Problème : justifier une architecture mixte
Une simulation possède plusieurs capteurs, chacun avec son historique. Un calcul transforme une liste de mesures en moyenne, et un programme principal répète les acquisitions. Proposez une place pour les objets, les fonctions pures et les boucles. Donnez un exemple de test indépendant du temps réel.
Indice 1
Associez l’état durable aux entités.
Indice 2
Le calcul d’un indicateur peut recevoir des données déjà connues.
Comprendre la correction
Des objets peuvent porter les historiques des capteurs ; une fonction pure calcule un indicateur sur une liste sans mutation ; une boucle organise les acquisitions. Pour tester la moyenne, on peut fournir [2,4,9] et attendre 5 sans capteur réel. L’ensemble combine des paradigmes à différents niveaux. La justification porte sur les responsabilités et les dépendances, pas sur l’obligation d’un style unique.
Les erreurs qui méritent un détour
- Assimiler toute fonction à la programmation fonctionnelle.
- Une fonction peut modifier des états et être utilisée dans tous les styles.
- Chercher un paradigme meilleur dans tous les cas.
- La structure du problème et la lisibilité motivent le choix.
La fiche à garder
L’essentiel à retenir
- L’impératif décrit des changements d’état.
- Le fonctionnel privilégie des transformations et leur composition.
- L’objet regroupe état et opérations dans des entités.
Le prochain pas
Retrouver le catalogue de Terminale
Ce chapitre s’appuie sur le programme officiel de Terminale (PDF, nouvel onglet). Les explications et exercices sont proposés pour l’apprentissage.
