Loading
Loading
Ce thème de terminale aborde les grands styles de programmation — impératif, fonctionnel et objet — et met l'accent sur la PROGRAMMATION ORIENTÉE OBJET (classes, attributs, méthodes, instances, constructeur \_\_init\_\_ et encapsulation) ainsi que sur la MISE AU POINT des programmes : spécifier une fonction (préconditions, postconditions, documentation), écrire des jeux de tests, utiliser des assertions et gérer des exceptions. L'idée directrice : tous les langages usuels étant Turing-complets, choisir un paradigme relève du style et de la structuration, et un programme se conçoit avec son contrat puis s'éprouve méthodiquement par les tests.
5sectionsca. 27min de lecture4compétencesNiveauBase 1 · Standard 3 · Approfondissement 1Vérifié · 06/2026
Lesetiefe: Approfondi
Schriftgröße: Standard
Trois paradigmes pour un même problème : sommer une liste
Le style FONCTIONNEL : une définition récursive, sans variable mutable
La même tâche (sommer une liste) s'exprime sans boucle ni accumulateur : élément neutre 0 sur la liste vide, puis composition « tête + somme du reste ». À comparer avec la version impérative à accumulateur.
Choisir un paradigme, c'est choisir un style d'organisation
Pour chacun des trois extraits suivants, donner le paradigme dominant et justifier en citant l'indice décisif. (A) « s = 0 ; for x in L: s = s + x ; return s ». (B) « def somme(L): return 0 if L == [] else L[0] + somme(L[1:]) ». (C) « p = Pile() ; p.empiler(3) ; p.empiler(7) ; print(p.total()) ».
Une variable d'état "s" est initialisée puis modifiée à chaque tour d'une boucle for : on décrit pas à pas COMMENT obtenir le résultat en faisant évoluer l'état. Indice décisif : la boucle qui met à jour une variable.
La fonction somme s'appelle elle-même, sans aucune variable mutable ni effet de bord ; le résultat est une composition « L[0] + somme(L[1:]) » avec le cas de base 0 sur la liste vide. Indice décisif : récursivité d'une fonction pure.
On crée une instance p d'une classe Pile, puis on appelle des MÉTHODES (empiler, total) sur cet objet, qui encapsule ses données. Indice décisif : un objet sur lequel on appelle des méthodes avec la notation p.methode().
Les trois extraits calculent la même somme : ils sont équivalents en pouvoir d'expression (tous les langages usuels sont Turing-complets). Le choix entre eux est un choix de style et de structuration.
Résultat : (A) impératif (boucle qui met à jour l'état s) ; (B) fonctionnel (fonction récursive pure, sans effet de bord) ; (C) objet (méthodes appelées sur une instance). Les trois résolvent le même problème : la différence est de style, pas de puissance de calcul.
Erreurs fréquentes
Révision active
On donne trois fonctions Python qui calculent toutes la factorielle de n : (1) une version avec une boucle for et une variable f mise à jour ; (2) une version récursive « fact(n) = 1 si n=0, sinon n*fact(n-1) » sans variable mutable ; (3) une classe Compteur munie d'une méthode factorielle() appelée sur une instance. Pour chacune, nommer le paradigme dominant et justifier en une phrase en citant l'indice décisif dans le code.
Rappel actif
Rappelle-toi les points clés — puis révèle.
Sources : Programme de spécialité NSI — classe terminale (voie générale), BO spécial n° 8 du 25 juillet 2019 (Ministère de l'Éducation nationale) · Numérique et sciences informatiques — programmes et ressources, voie générale (Éduscol) (Éduscol — Ministère de l'Éducation nationale)
La « carte d'identité » d'une classe : attributs et méthodes
Instancier : du moule (classe) à l'exemplaire (objet)
L'appel CompteBancaire("Ada", 100) déclenche __init__ avec self = le nouvel objet ; les affectations self.titulaire = … et self.solde = … fixent l'état initial de l'instance c.
Le constructeur __init__ et le rôle de self
Écrire une classe CompteBancaire avec : les attributs titulaire et solde ; un constructeur \_\_init\_\_(self, titulaire, solde_initial) ; une méthode deposer(self, montant) qui augmente le solde ; une méthode retirer(self, montant) qui diminue le solde si possible. Créer ensuite le compte de « Ada » avec un solde initial de 100, déposer 50, retirer 30, puis donner le solde final.
On écrit « class CompteBancaire: » puis « def __init__(self, titulaire, solde_initial): » qui crée self.titulaire = titulaire et self.solde = solde_initial. self reçoit automatiquement le nouvel objet.
deposer(self, montant) fait self.solde = self.solde + montant. retirer(self, montant) ne diminue le solde que si montant <= self.solde (sinon il refuse l'opération). Chaque méthode agit sur l'attribut via self.
c = CompteBancaire('Ada', 100) crée l'objet (solde 100). c.deposer(50) porte le solde à 150. c.retirer(30) le ramène à 120 (30 <= 150, l'opération est autorisée).
On lit l'attribut de l'objet : c.solde vaut 120. La classe (moule) a produit un objet c (exemplaire) dont les méthodes ont fait évoluer l'état.
Résultat : Après c = CompteBancaire('Ada', 100), c.deposer(50) puis c.retirer(30), l'attribut c.solde vaut 120. La classe est le moule, c est l'instance, deposer/retirer sont des méthodes qui modifient l'attribut solde via self.
Erreurs fréquentes
Révision active
Écrire en Python une classe Rectangle dotée des attributs largeur et hauteur, d'un constructeur \_\_init\_\_(self, largeur, hauteur) qui les initialise, et de deux méthodes aire(self) et perimetre(self) qui renvoient respectivement l'aire et le périmètre. Créer ensuite un rectangle 4 × 3 et vérifier que aire() vaut 12 et perimetre() vaut 14.
Rappel actif
Rappelle-toi les points clés — puis révèle.
Sources : Programme de spécialité NSI — classe terminale (voie générale), BO spécial n° 8 du 25 juillet 2019 (Ministère de l'Éducation nationale) · Numérique et sciences informatiques — programmes et ressources, voie générale (Éduscol) (Éduscol — Ministère de l'Éducation nationale)
Un moule, plusieurs instances : des objets distincts
Appeler une méthode : la liaison automatique de self
La notation pointée b.norme() est équivalente à appeler la fonction de la classe en lui passant b comme premier argument self. C'est pourquoi on n'écrit jamais soi-même b.norme(b).
Exemple de calcul réalisé par une méthode (point (3 ; 4))
La méthode norme lit les attributs x et y de l'objet et renvoie la distance à l'origine. Pour b = Point(3, 4), elle vaut 5.
Attribut sans parenthèses, méthode avec parenthèses
La classe Point(x, y) possède une méthode norme(self) renvoyant la distance à l'origine. (a) Instancier b = Point(3, 4) et c = Point(6, 8). (b) Calculer b.norme() et c.norme(). (c) Donner b.x. (d) Après b.x = 0, la valeur de c.x change-t-elle ?
b = Point(3, 4) crée un objet d'attributs b.x = 3 et b.y = 4. c = Point(6, 8) crée un AUTRE objet d'attributs c.x = 6 et c.y = 8. Deux instances indépendantes.
b.norme() exécute norme(self) avec self = b : racine de 3^2 + 4^2 = 25, soit 5. c.norme() avec self = c : racine de 6^2 + 8^2 = 100, soit 10.
b.x est un accès en lecture à la donnée x de l'objet b : il vaut 3. Pas de parenthèses : c'est une valeur, pas un appel.
b et c sont deux objets distincts, chacun avec son propre attribut x. L'affectation b.x = 0 ne modifie que l'objet b ; c.x reste égal à 6.
Résultat : (a) deux objets indépendants. (b) b.norme() = 5 et c.norme() = 10. (c) b.x = 3. (d) Non : c.x reste 6, car b et c sont des instances distinctes possédant chacune leur propre état.
Erreurs fréquentes
Révision active
On dispose d'une classe Point(x, y) munie d'une méthode norme(self) qui renvoie la distance à l'origine. (a) Instancier deux points b = Point(3, 4) et c = Point(6, 8). (b) Donner la valeur de b.norme() et de c.norme(). (c) Que renvoie b.x ? (d) Après l'instruction b.x = 0, la valeur de c.x est-elle modifiée ? Justifier.
Rappel actif
Rappelle-toi les points clés — puis révèle.
Sources : Programme de spécialité NSI — classe terminale (voie générale), BO spécial n° 8 du 25 juillet 2019 (Ministère de l'Éducation nationale) · Numérique et sciences informatiques — programmes et ressources, voie générale (Éduscol) (Éduscol — Ministère de l'Éducation nationale)
Le contrat d'une fonction : précondition, fonction, postcondition
Le contrat d'une fonction : précondition → fonction → postcondition
Si l'appelant garantit la précondition x >= 0, la fonction garantit en retour la postcondition « r positif et r au carré égal à x ». Hors précondition, aucune garantie.
On veut une fonction quotient_reste(a, b) qui renvoie le couple (q, r) du quotient et du reste de la division euclidienne de a par b, pour a et b entiers. (a) Donner la précondition. (b) Donner la postcondition liant a, b, q et r. (c) Rédiger un docstring Python conforme.
La division euclidienne n'a de sens que si le diviseur n'est pas nul. On impose donc, à la charge de l'appelant : a et b entiers, et b différent de 0 (on prendra ici b > 0 pour fixer le signe du reste).
La fonction garantit que le couple renvoyé reconstitue a et que le reste est dans le bon intervalle : a = b*q + r avec 0 <= r < b. C'est une propriété vérifiable (testable par assertion).
Sous l'en-tête def quotient_reste(a, b):, on place une chaîne triple décrivant le QUOI : « Renvoie (q, r) tels que a = b*q + r et 0 <= r < b. Precondition : a entier, b entier strictement positif. » Le docstring est la spécification écrite, lisible par help().
Pour a = 17, b = 5 : q = 3, r = 2. On vérifie la postcondition : 5*3 + 2 = 17 et 0 <= 2 < 5. Le contrat est tenu.
Résultat : Précondition : a, b entiers avec b > 0. Postcondition : a = b*q + r et 0 <= r < b. Le docstring décrit le résultat (le QUOI) et les hypothèses, sans détailler l'algorithme. Exemple : quotient_reste(17, 5) = (3, 2), conforme au contrat.
Erreurs fréquentes
Révision active
Spécifier puis documenter (par un docstring) une fonction indice_max(L) qui renvoie l'indice d'un plus grand élément d'une liste de nombres L. Préciser la précondition (que faut-il imposer à L pour que la question ait un sens ?), la postcondition (quelle propriété l'indice renvoyé vérifie-t-il ?), et le comportement choisi en cas d'égalité entre plusieurs maximums.
Rappel actif
Rappelle-toi les points clés — puis révèle.
Sources : Programme de spécialité NSI — classe terminale (voie générale), BO spécial n° 8 du 25 juillet 2019 (Ministère de l'Éducation nationale) · Numérique et sciences informatiques — programmes et ressources, voie générale (Éduscol) (Éduscol — Ministère de l'Éducation nationale)
Le cycle de mise au point : spécifier, coder, tester, corriger
Sémantique d'une assertion de test
Une assertion compare le résultat f(e) au résultat attendu s : si l'égalité est vraie le programme poursuit, sinon il s'arrête en signalant l'échec — exactement ce qu'on veut pendant la mise au point.
Un bon jeu de tests : nominal, limite, erreur
Assertion qui échoue et rattrapage d'exception (try/except)
On veut racine_entiere(n) qui, pour un entier n >= 0, renvoie le plus grand entier r tel que r*r <= n (partie entière de la racine carrée). (a) Donner la spécification (pré/postcondition). (b) Écrire un jeu de tests par assertions (nominal, limite, erreur). (c) Une première version oublie le cas n = 0 et tombe en boucle infinie ; expliquer comment le jeu de tests le révèle et comment lever une exception sur une entrée négative.
Précondition (appelant) : n est un entier et n >= 0. Postcondition (fonction) : le résultat r vérifie rr <= n < (r+1)(r+1), c'est-à-dire r est la partie entière de la racine de n.
racine_entiere(9) doit valoir 3 (3^2 = 9 <= 9 < 16), racine_entiere(10) doit valoir 3 (9 <= 10 < 16), racine_entiere(15) doit valoir 3, racine_entiere(16) doit valoir 4.
Limites : racine_entiere(0) == 0 et racine_entiere(1) == 1 (frontières). Erreur : racine_entiere(-4) viole la précondition ; on attend qu'elle LÈVE une exception, ce qu'on teste avec try/except.
Le cas limite racine_entiere(0) fait tourner la boucle infinie de la première version : l'assertion ne renvoie jamais de résultat, le bug est localisé sur n = 0. On corrige (initialisation/condition d'arrêt) et on protège la précondition : « if n < 0: raise ValueError('n doit etre >= 0') », qu'on rattrape par try/except au point d'appel.
Résultat : La spécification fixe r tel que r^2 <= n < (r+1)^2 pour n >= 0. Le jeu de tests nominal/limite/erreur — notamment le cas limite n = 0 — fait apparaître la boucle infinie de la première version et la localise ; on corrige la condition d'arrêt, puis on lève une ValueError sur n < 0, rattrapée par un bloc try/except. Les tests conservés assurent la non-régression.
Erreurs fréquentes
Révision active
On dispose d'une fonction moyenne(L) censée renvoyer la moyenne des éléments d'une liste de nombres. (a) Écrire un jeu de tests par assertions couvrant un cas nominal, un cas limite (liste à un seul élément) et un cas d'erreur (liste vide). (b) Proposer un comportement raisonnable sur la liste vide (lever une exception) et écrire un bloc try/except qui l'utilise sans faire planter le programme. (c) Indiquer un bug classique que ces tests permettraient de détecter.
Rappel actif
Rappelle-toi les points clés — puis révèle.
Sources : Programme de spécialité NSI — classe terminale (voie générale), BO spécial n° 8 du 25 juillet 2019 (Ministère de l'Éducation nationale) · Numérique et sciences informatiques — programmes et ressources, voie générale (Éduscol) (Éduscol — Ministère de l'Éducation nationale)
Références et sources
Ministère de l'Éducation nationale
Éduscol — Ministère de l'Éducation nationale