{"id":1240,"date":"2024-12-06T08:35:00","date_gmt":"2024-12-06T04:35:00","guid":{"rendered":"https:\/\/iremi.univ-reunion.fr\/?p=1240"},"modified":"2026-02-19T10:11:03","modified_gmt":"2026-02-19T06:11:03","slug":"programmation-objet-et-types-abstraits-de-donnees-en-nsi","status":"publish","type":"post","link":"https:\/\/iremi.univ-reunion.fr\/?p=1240","title":{"rendered":"Programmation objet et types abstraits de donn\u00e9es en NSI"},"content":{"rendered":"\n<p>En NSI, la programmation objet n&rsquo;est au programme qu&rsquo;en Terminale. Toutefois, on gagne \u00e0 l&rsquo;aborder d\u00e8s la classe (!) de Premi\u00e8re, car elle simplifie certains apprentissages. Le langage choisi est Python 3, qui est pr\u00e9cis\u00e9ment un langage de programmation objet. Une progression est propos\u00e9e ici, bas\u00e9e sur la POO, pour le cours sur les donn\u00e9es structur\u00e9es (listes, tuples et dictionnaires en 1\u00e8re, piles, files, listes cha\u00een\u00e9es, arbres binaires en Tle).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Programmation objet et objets connect\u00e9s<\/h2>\n\n\n\n<p>En fait, d\u00e8s la classe de 2nde (en SNT) il est possible d&rsquo;aborder la POO, car certains objets connect\u00e9s se programment en Python, en appelant des m\u00e9thodes (de fait, les lutins de Scratch ressemblent beaucoup \u00e0 des objets). On programme de tels objets en <a href=\"https:\/\/micropython.org\/\">micropython<\/a>, sur des cartes de type Arduino (ici, une <a href=\"https:\/\/fr.wikipedia.org\/wiki\/ESP32\">ESP-32<\/a>).<\/p>\n\n\n\n<p>Sachant que la LED de la carte est sur la broche 13, on la g\u00e8re logiciellement sous forme d&rsquo;un objet <code>Pin<\/code> (broche) que l&rsquo;on importe du module <code>machine<\/code>, et qu&rsquo;on cr\u00e9e logiciellement ainsi :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; from machine import Pin\n&gt;&gt;&gt; led = Pin(13,Pin.OUT)\n&gt;&gt;&gt; dir(led)\n&#091;'__class__', 'value', 'DRIVE_0', 'DRIVE_1', 'DRIVE_2', 'DRIVE_3', 'IN', 'IRQ_FALLING', 'IRQ_RISING', 'OPEN_DRAIN', 'OUT', 'PULL_DOWN', 'PULL_UP', 'WAKE_HIGH', 'WAKE_LOW', 'board', 'init', 'irq', 'off', 'on']\n<\/code><\/pre>\n\n\n\n<p>La fonction <code>dir<\/code> donne la liste des m\u00e9thodes de la broche, et on constate qu&rsquo;il y a plusieurs constantes  (dont le nom s&rsquo;\u00e9crit en majuscules ; si seule la premi\u00e8re lettre est en majuscule, on convient qu&rsquo;il s&rsquo;agit d&rsquo;un objet), parmi lesquelles <code>OUT<\/code>, qui est un entier : <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; led.OUT\n3<\/code><\/pre>\n\n\n\n<p>Mais il y a aussi un <code>on<\/code> dont on se doute qu&rsquo;il sert \u00e0 allumer la LED, seulement<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; led.on\n&lt;bound_method&gt;<\/code><\/pre>\n\n\n\n<p>n&rsquo;allume pas la LED et pr\u00e9cise que <code>on<\/code> est une m\u00e9thode (une fonction qui n&rsquo;appartient qu&rsquo;\u00e0 la LED). Pour allumer la LED on doit appeler cette m\u00e9thode (en pr\u00e9cisant \u00e0 qui on s&rsquo;adresse, en pr\u00e9c\u00e9dant l&rsquo;appel de la m\u00e9thode du nom de la variable) avec <code>on()<\/code> :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; led.on()<\/code><\/pre>\n\n\n\n<p>Maintenant la LED est allum\u00e9e. Pour l&rsquo;\u00e9teindre on peut faire <code>led.off()<\/code> mais aussi modifier sa valeur; \u00e9gale \u00e0 1 lorsqu&rsquo;elle est allum\u00e9e et \u00e0 0 lorsqu&rsquo;elle est \u00e9teinte :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; led.value()\n1\n&gt;&gt;&gt; led.value(0)\n&gt;&gt;&gt; led.value()\n0<\/code><\/pre>\n\n\n\n<p>Ce TP a \u00e9t\u00e9 fait en Premi\u00e8re NSI mais aussi en 2nde SNT. Bien entendu, il y a des \u00e9l\u00e8ves qui se demandent pourquoi ils n&rsquo;arrivent pas \u00e0 allumer la LED \u00e0 moiti\u00e9 avec<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; led.value(0.5)\n&gt;&gt;&gt; led.value(0.000001)\n&gt;&gt;&gt; led.value()\n1<\/code><\/pre>\n\n\n\n<p>On d\u00e9couvre exp\u00e9rimentalement que <code>Pin(13)<\/code> est une sortie num\u00e9rique (elle ne peut prendre que les valeurs 0 ou 1, toute valeur non nulle \u00e9tant assimil\u00e9e \u00e0 1). Pour simuler l&rsquo;allumage graduel de la LED, il faut moduler en largeur d&rsquo;impulsions cette sortie num\u00e9rique, \u00e0 l&rsquo;aide d&rsquo;un objet PWM (Pulse Width Modulation) :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; from machine import PWM\n&gt;&gt;&gt; p = PWM(led)\n&gt;&gt;&gt; dir(p)\n&#091;'__class__', 'deinit', 'duty', 'duty_ns', 'duty_u16', 'freq', 'init']\n&gt;&gt;&gt; p.duty()\n512\n&gt;&gt;&gt; p.duty(8)<\/code><\/pre>\n\n\n\n<p>Cette fois-ci la LED est faiblement allum\u00e9e.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Cours de Premi\u00e8re NSI bas\u00e9 sur la POO<\/h2>\n\n\n\n<p>Les types au programme de Premi\u00e8re NSI sont<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>les types de base (bool\u00e9ens <code>bool<\/code>, entiers <code>int<\/code>, flottants <code>float<\/code> et cha\u00eenes de caract\u00e8res <code>str<\/code>) y compris les fonctions,<\/li>\n\n\n\n<li>les types construits (tableaux <code>list<\/code>, n-uplets <code>tuple<\/code> et dictionnaires <code>dict<\/code>).<\/li>\n<\/ul>\n\n\n\n<p>Pour v\u00e9rifier que <code>[1,2,3]<\/code> est un tableau, on peut lui appliquer la fonction <code>type<\/code> :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; tab = &#091;1,2,3]\n&gt;&gt;&gt; type(tab)\n&lt;class 'list'&gt;<\/code><\/pre>\n\n\n\n<p>ou, mieux, la fonction <code>dir<\/code> :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; dir(tab)\n&#091;'__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']<\/code><\/pre>\n\n\n\n<p>Pourquoi est-ce mieux que de chercher simplement le type de la variable ? Parce qu&rsquo;avec cet affichage, on n&rsquo;apprend pas que <code>tab<\/code> est un tableau, mais qu&rsquo;est-ce qu&rsquo;un tableau, ou plut\u00f4t qu&rsquo;est-ce qu&rsquo;on peut faire avec. Par exemple la pr\u00e9sence d&rsquo;une m\u00e9thode <code>__add__<\/code> permet d&rsquo;additionner des tableaux :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; tab + &#091;1,2]\n&#091;1, 2, 3, 1, 2]<\/code><\/pre>\n\n\n\n<p>La pr\u00e9sence d&rsquo;une m\u00e9thode <code>__len__<\/code> permet d&rsquo;utiliser la fonction <code>len<\/code> (les tableaux ont donc une longueur) :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; len(tab)\n3<\/code><\/pre>\n\n\n\n<p>Les m\u00e9thodes dont le nom commence, et finit, par un double <em>underscore<\/em> (on les appelle m\u00e9thodes <em>dunder<\/em>) sont celles que les tableaux (fac\u00e9tieusement appel\u00e9s listes en Python) h\u00e9ritent d&rsquo;autres objets, et qui ne caract\u00e9risent pas les tableaux. Les autres par contre permettent de voir qu&rsquo;on a affaire \u00e0 un objet auquel on peut ajouter quelque chose :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; tab.append(5)\n&gt;&gt;&gt; tab\n&#091;1, 2, 3, 5]<\/code><\/pre>\n\n\n\n<p>o\u00f9 l&rsquo;on peut ins\u00e9rer quelque chose :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; tab.insert(2,8)\n&gt;&gt;&gt; tab\n&#091;1, 2, 8, 3, 5]<\/code><\/pre>\n\n\n\n<p>que l&rsquo;on peut trier :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; tab.sort()\n&gt;&gt;&gt; tab\n&#091;1, 2, 3, 5, 8]<\/code><\/pre>\n\n\n\n<p>ou dont on peut retirer un \u00e9l\u00e9ment :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; tab.pop()\n8\n&gt;&gt;&gt; tab\n&#091;1, 2, 3, 5]<\/code><\/pre>\n\n\n\n<p>La fonction <code>dir<\/code> permet (en se concentrant sur les m\u00e9thodes non <em>dunder<\/em>) d&rsquo;obtenir un r\u00e9sum\u00e9 du cours (ici, sur les tableaux de Python) et, par l\u00e0, de donner plus d&rsquo;autonomie aux \u00e9l\u00e8ves en pratique Python. Le programme de Terminale stipule que<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Distinguer des structures par le jeu des m\u00e9thodes qui les caract\u00e9risent.<\/p>\n<\/blockquote>\n\n\n\n<p>Il s&rsquo;agit d&rsquo;une allusion au <a href=\"https:\/\/fr.wikipedia.org\/wiki\/Duck_typing\">duck typing<\/a> cher \u00e0 Python. On verra plus bas qu&rsquo;une bonne partie du cours de Terminale s&rsquo;appuie sur ce principe. Mais avant cela, on peut aborder des m\u00e9thodes dunder qui clarifient beaucoup de choses sur les types construits vus en Premi\u00e8re.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Mutabilit\u00e9, immuabilit\u00e9 et aliasing<\/h2>\n\n\n\n<p>Parmi les types au programme, seules les fonctions (et, en Terminale, les classes) sont appelables (<em>callables<\/em>) c&rsquo;est-\u00e0-dire que seules les fonctions poss\u00e8dent une m\u00e9thode <code>__call__<\/code> :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; &#091;o for o in &#091;str,list,tuple,dict] if '__call__' in dir(o)]\n&#091;]<\/code><\/pre>\n\n\n\n<p>Concr\u00e8tement cela signifie qu&rsquo;on ne peut utiliser les parenth\u00e8ses qu&rsquo;avec des fonctions. Si on essaye avec un tableau on a ceci :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; tab(2)\nTraceback (most recent call last):\n  File \"&lt;stdin&gt;\", line 1, in &lt;module&gt;\nTypeError: 'list' object is not callable<\/code><\/pre>\n\n\n\n<p>Pour acc\u00e9der \u00e0 un \u00e9l\u00e9ment d&rsquo;un des types construits (\u00e0 partir d&rsquo;un index ou d&rsquo;une cl\u00e9) on doit utiliser les crochets :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; tab&#091;2]\n3<\/code><\/pre>\n\n\n\n<p>La possibilit\u00e9 de lire un \u00e9l\u00e9ment d&rsquo;une collection (et donc de parcourir la collection) est la cons\u00e9quence de la pr\u00e9sence d&rsquo;une m\u00e9thode <code>__getitem__<\/code> :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; &#091;o for o in &#091;str,list,tuple,dict] if '__getitem__' in dir(o)]\n&#091;&lt;class 'str'&gt;, &lt;class 'list'&gt;, &lt;class 'tuple'&gt;, &lt;class 'dict'&gt;]<\/code><\/pre>\n\n\n\n<p>Les cha\u00eenes de caract\u00e8res et les types construits sont <em>suscriptables<\/em> : on peut utiliser la notation des crochets pour examiner l&rsquo;int\u00e9rieur de ces objets. Les fonctions par contre ne sont pas suscriptables :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; from math import *\n&gt;&gt;&gt; sin&#091;pi\/2]\nTraceback (most recent call last):\n  File \"&lt;stdin&gt;\", line 1, in &lt;module&gt;\nTypeError: 'builtin_function_or_method' object is not subscriptable\n&gt;&gt;&gt; sin(pi\/2)\n1.0<\/code><\/pre>\n\n\n\n<p>En fait, pour les tableaux, il est \u00e9galement possible d&rsquo;utiliser la notation des crochets pour modifier un des \u00e9l\u00e9ments du tableau :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; tab&#091;2] = 13\n&gt;&gt;&gt; tab\n&#091;1, 2, 13, 5]<\/code><\/pre>\n\n\n\n<p>En fait les tableaux ne sont pas seulement suscriptables, ils sont \u00e9galement <em>mutables<\/em>. Cela est d\u00fb \u00e0 leur m\u00e9thode <code>__setitem__<\/code>, ce qui fait qu&rsquo;on peut savoir quels sont les types mutables au programme de NSI :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; &#091;o for o in &#091;str,list,tuple,dict] if '__setitem__' in dir(o)]\n&#091;&lt;class 'list'&gt;, &lt;class 'dict'&gt;]<\/code><\/pre>\n\n\n\n<p>En fait, seuls les tableaux et les dictionnaires sont mutables. Les autres types (y compris les types de base) sont <em>immuables<\/em>. Cela n&rsquo;a donc pas de sens de donner une m\u00e9thode <code>append<\/code> ou <code>pop<\/code> \u00e0 un tuple. L&rsquo;int\u00e9r\u00eat des objets immuables est qu&rsquo;on peut les <em>hasher<\/em> :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; hash(tab)\nTraceback (most recent call last):\n  File \"&lt;stdin&gt;\", line 1, in &lt;module&gt;\nTypeError: unhashable type: 'list'<\/code><\/pre>\n\n\n\n<p>On verra plus bas comment simuler en Python un dictionnaire par une table de hashage, mais pour l&rsquo;instant, il est bon de savoir que les cl\u00e9s des dictionnaires doivent \u00eatre hashables, et qu&rsquo;on ne peut donc pas utiliser de tableaux ni de dictionnaires comme cl\u00e9s de dictionnaires : les cl\u00e9s doivent \u00eatre immuables pour \u00eatre hashables.<\/p>\n\n\n\n<p>La mutabilit\u00e9 des tableaux de Python pose probl\u00e8me :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; tab1 = &#091;1,2,3]\n&gt;&gt;&gt; tab2 = tab1\n&gt;&gt;&gt; tab1\n&#091;1, 2, 3]\n&gt;&gt;&gt; tab2\n&#091;1, 2, 3]\n&gt;&gt;&gt; tab2&#091;1] = 8\n&gt;&gt;&gt; tab2\n&#091;1, 8, 3]\n&gt;&gt;&gt; tab1\n&#091;1, 8, 3]<\/code><\/pre>\n\n\n\n<p>En voulant modifier <code>tab2<\/code>, on a aussi modifi\u00e9 <code>tab1<\/code>. Une solution consisterait \u00e0 travailler, non sur <code>tab1<\/code>, mais sur une copie d&rsquo;icelui :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; tab1 = &#091;1,2,3]\n&gt;&gt;&gt; tab2 = tab1.copy()\n&gt;&gt;&gt; tab2&#091;1] = 8\n&gt;&gt;&gt; tab1\n&#091;1, 2, 3]<\/code><\/pre>\n\n\n\n<p>La m\u00e9thode copy() n&rsquo;\u00e9tant pas au programme de NSI, on peut lui pr\u00e9f\u00e9rer la liste en compr\u00e9hension (qui, elle, est au programme) :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; tab1 = &#091;1,2,3]\n&gt;&gt;&gt; tab2 = &#091;x for x in tab1]\n&gt;&gt;&gt; tab2&#091;1] = 8\n&gt;&gt;&gt; tab1\n&#091;1, 2, 3]<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Cours de Terminale NSI bas\u00e9 sur la POO<\/h2>\n\n\n\n<p>En Terminale (et parfois au bac) les \u00e9l\u00e8ves ont parfois \u00e0 cr\u00e9er leurs propres objets, avec l&rsquo;instruction <code>class<\/code>. Un bon exemple d&rsquo;utilisation de cette construction est constitu\u00e9 des structures de donn\u00e9es qui sont au programme, \u00e0 savoir les piles, les files, les listes cha\u00een\u00e9es, les arbres binaires, les arbres et les graphes. Cela est tr\u00e8s proche de l&rsquo;approche du <a href=\"https:\/\/www.lri.fr\/~chris\/LivreAlgorithmique\/FroidevauxGaudelSoria.pdf\">livre de Christine Froidevaux<\/a> <em>et al<\/em>, bas\u00e9 sur une axiomatique des types abstraits de donn\u00e9s. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Les graphes<\/h3>\n\n\n\n<p>Les graphes sont plut\u00f4t compliqu\u00e9s \u00e0 programmer objet, en raison du nombre de m\u00e9thodes dont on a besoin. D&rsquo;ailleurs des modules Python sp\u00e9cialis\u00e9s (<a href=\"https:\/\/graphviz.org\/\">graphviz<\/a>, <a href=\"https:\/\/networkx.org\/\">networkx<\/a>) existent d\u00e9j\u00e0. Cependant, on peut mod\u00e9liser (voir exercice 3 du sujet jour 2 centres \u00e9trangers 2025) un sommet d&rsquo;un graphe orient\u00e9 avec<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>class Sommet:\n    def __init__(self,valeur):\n        self.valeur = valeur\n        self.enfants = &#091;]\n    def ajouter_enfant(self,sommet):\n        self.enfants.append(sommet)<\/code><\/pre>\n\n\n\n<p>Un graphe est alors une liste de sommets.<\/p>\n\n\n\n<p>Les arbres \u00e9tant des graphes particuliers (connexes sans cycle) peuvent \u00eatre mod\u00e9lis\u00e9s de la m\u00eame mani\u00e8re que les autres graphes, avec une liste d&rsquo;enfants, mais dans un arbre, chaque n\u0153ud n&rsquo;a qu&rsquo;un parent ce qui permet cette mod\u00e9lisation :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>class Noeud:\n    def __init__(self,valeur):\n        self.valeur = valeur\n        self.parent = None<\/code><\/pre>\n\n\n\n<p>le seul parent d&rsquo;un n\u0153ud \u00e9tant un n\u0153ud, sauf pour la racine qui n&rsquo;a pas de parent (d&rsquo;o\u00f9 le <code>None<\/code>). <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Les arbres binaires<\/h3>\n\n\n\n<p>Un arbre binaire a une racine et deux sous-arbres (gauche et droit) qui sont chacun soit <code>None<\/code>, soit un arbre binaire : <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>class Arbre:\n    def __init__(self,nom):\n        self.label = nom\n        self.G = None\n        self.D = None\n    def est_une_feuille(self):\n        return self.G is None and self.D is None\n    def greffe_gauche(self,greffe):\n        self.G = greffe\n    def greffe_droite(self,greffe):\n        self.D = greffe    <\/code><\/pre>\n\n\n\n<p>et pour un arbre binaire de recherche, on ajoute une m\u00e9thode de recherche (c&rsquo;est le but) et d&rsquo;insertion (de mani\u00e8re que la structure d&rsquo;arbre binaire de recherche soit un invariant) :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    def dedans(self,clef):\n        if self.label==clef:\n            return True\n        elif self.label&gt;clef and self.G is not None:\n            return self.G.dedans(clef)\n        elif self.label&lt;clef and self.D is not None:\n            return self.D.dedans(clef)\n        else:\n            return False    \n\n    def ajouter(self,clef):\n        assert not self.dedans(clef)\n        if self.label&gt;clef:\n            if self.G is None:\n                self.greffe_gauche(BST(clef))\n            else:\n                self.G.ajouter(clef)\n        elif self.label&lt;clef:\n            if self.D is None:\n                self.greffe_droite(BST(clef))\n            else:\n                self.D.ajouter(clef)\n        else:\n            self=BST(clef)    <\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Listes cha\u00een\u00e9es<\/h3>\n\n\n\n<p>Plus simples que les arbres binaires, les listes cha\u00een\u00e9es en h\u00e9ritent : selon le mod\u00e8le de Newell et Shaw (1957) une liste cha\u00een\u00e9e est un arbre binaire dans lequel chaque n\u0153ud n&rsquo;a qu&rsquo;un enfant droit :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>class Liste:\n    def __init__(self,label):\n        self.label = label\n        self.suivant = None\n    def est_final(self):\n        return self.suivant is None\n    def suite(self):\n        return self.suivant\n    def ajout(self,elt):\n        if self.est_final():\n            self.suivant = Liste(elt)\n        else:\n            self.suivant.ajout(elt)<\/code><\/pre>\n\n\n\n<p>On a essentiellement red\u00e9fini le vocabulaire, en nommant final ce qui s&rsquo;appelait feuille et suivant ce qui s&rsquo;appelait enfant droit.<\/p>\n\n\n\n<p>On peut aussi utiliser la surcharge de m\u00e9thodes pour rendre la classe plus pythonienne :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>class Liste:\n    def __init__(self,label):\n        self.label = label\n        self.suivant = None\n    def est_final(self):\n        return self.suivant is None\n    def __repr__(self):\n        if self.est_final():\n            return str(self.label)\n        else:\n            return str(self.label)+'\u2192'+self.suivant.__repr__()\n    def suite(self):\n        return self.suivant\n    def ajout(self,elt):\n        if self.est_final():\n            self.suivant = Liste(elt)\n        else:\n            self.suite().ajout(elt)\n    def __len__(self):\n        if self.est_final():\n            return 1\n        else:\n            return 1 + len(self.suite())\n    def __contains__(self,elt):\n        if self.est_final():\n            return self.label==elt\n        else:\n            return self.label==elt or elt in self.suite()<\/code><\/pre>\n\n\n\n<p>L&rsquo;utilisation de m\u00e9thodes <em>dunder<\/em> permet alors de faire ce genre de session :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; a = Liste(3)\n&gt;&gt;&gt; a.ajout(1)\n&gt;&gt;&gt; a.ajout(4)\n&gt;&gt;&gt; a\n3\u21921\u21924\n&gt;&gt;&gt; len(a)\n3\n&gt;&gt;&gt; 1 in a\nTrue<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Piles<\/h3>\n\n\n\n<p>Une pile est un objet dot\u00e9 de m\u00e9thodes d&#8217;empilement et de d\u00e9pilement, ainsi qu&rsquo;un test de vacuit\u00e9. La m\u00e9thode permettant de cr\u00e9er une pile vide n&rsquo;est autre que le <code>__init__<\/code> de Python :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>class Pile:\n    def __init__(self):\n        self.tab = &#091;]\n    def est_vide(self):\n        return self.tab == &#091;]\n    def empiler(self,elt):\n        self.tab.append(elt)\n    def depiler(self):\n        return self.tab.pop()<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Files<\/h3>\n\n\n\n<p>La classe File peut se d\u00e9finir d&rsquo;une mani\u00e8re similaire \u00e0 la classe Pile :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>class File:\n    def __init__(self):\n        self.tab = &#091;]\n    def est_vide(self):\n        return self.tab == &#091;]\n    def enfiler(self,elt):\n        self.tab.append(elt)\n    def defiler(self):\n        return self.tab.pop(0)<\/code><\/pre>\n\n\n\n<p>ou alors \u00e0 l&rsquo;aide de deux piles (au programme de Terminale NSI) :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>class File:\n    def __init__(self):\n        self.pile1 = Pile()\n        self.pile2 = Pile()\n    def est_vide(self):\n        return self.pile1.est_vide() and self.pile2.est_vide()\n    def flush(self):\n        while not self.pile1.est_vide():\n            self.pile2.empiler(self.pile1.depiler())\n    def enfiler(self,elt):\n        self.pile1.empiler(elt)\n    def defiler(self):\n        if self.pile2.est_vide():\n            self.flush()\n        return self.pile2.depiler()<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Dictionnaires<\/h3>\n\n\n\n<p>La construction des dictionnaires n&rsquo;est pas vraiment au programme, tout au plus peut-on y lire :<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Distinguer la recherche d\u2019une valeur dans une liste et dans un dictionnaire.<\/p>\n<\/blockquote>\n\n\n\n<p>Cependant, avec des \u00e9l\u00e8ves qui ont d\u00e9j\u00e0 quelque exp\u00e9rience en POO, on peut envisager de simuler les dictionnaires (y compris leur affichage) en Python :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def h(o):\n    return hash(o) % 256\n\nclass Dictionnaire:\n    def __init__(self):\n        self.clefs = &#091;None]*256\n        self.valeurs = &#091;None]*256\n    def __setitem__(self,clef,valeur):\n        self.clefs&#091;h(clef)] = clef\n        self.valeurs&#091;h(clef)] = valeur\n    def __getitem__(self,clef):\n        return self.valeurs&#091;h(clef)]\n    def __repr__(self):\n        s = '{'\n        for i in range(len(self.clefs)):\n            if self.clefs&#091;i] is not None:\n                s += str(self.clefs&#091;i])\n                s += ':'\n                s += str(self.valeurs&#091;i])\n                s += ', '\n        return s + '}'<\/code><\/pre>\n\n\n\n<p>Ce dictionnaire light de Python s&rsquo;utilise comme le vrai dictionnaire :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;&gt;&gt; dico = Dictionnaire()\n&gt;&gt;&gt; dico&#091;2] = 3\n&gt;&gt;&gt; dico&#091;5] = 8\n&gt;&gt;&gt; dico\n{2:3, 5:8, }<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Le cours complet en pdf<\/h2>\n\n\n\n<p>Afin de voir la proportion de POO dans le cours, voici celui-ci (sur les trois ann\u00e9es du lyc\u00e9e) :<\/p>\n\n\n\n<p>Cours de SNT (2nde) :<\/p>\n\n\n\n<div data-wp-interactive=\"core\/file\" class=\"wp-block-file\"><object data-wp-bind--hidden=\"!state.hasPdfPreview\" hidden class=\"wp-block-file__embed\" data=\"https:\/\/iremi.univ-reunion.fr\/wp-content\/uploads\/2024\/12\/cours_2nde.pdf\" type=\"application\/pdf\" style=\"width:100%;height:600px\" aria-label=\"Contenu embarqu\u00e9 cours_2nde.\"><\/object><a id=\"wp-block-file--media-f1108147-7115-4f98-ba5e-cb02108e0387\" href=\"https:\/\/iremi.univ-reunion.fr\/wp-content\/uploads\/2024\/12\/cours_2nde.pdf\">cours_2nde<\/a><a href=\"https:\/\/iremi.univ-reunion.fr\/wp-content\/uploads\/2024\/12\/cours_2nde.pdf\" class=\"wp-block-file__button wp-element-button\" download aria-describedby=\"wp-block-file--media-f1108147-7115-4f98-ba5e-cb02108e0387\">T\u00e9l\u00e9charger<\/a><\/div>\n\n\n\n<p>Cours de Premi\u00e8re NSI :<\/p>\n\n\n\n<div data-wp-interactive=\"core\/file\" class=\"wp-block-file\"><object data-wp-bind--hidden=\"!state.hasPdfPreview\" hidden class=\"wp-block-file__embed\" data=\"https:\/\/iremi.univ-reunion.fr\/wp-content\/uploads\/2024\/12\/cours_1re-1.pdf\" type=\"application\/pdf\" style=\"width:100%;height:600px\" aria-label=\"Contenu embarqu\u00e9 cours_1re.\"><\/object><a id=\"wp-block-file--media-f6f5cc56-5b59-42a3-a8f2-b9aab5d44063\" href=\"https:\/\/iremi.univ-reunion.fr\/wp-content\/uploads\/2024\/12\/cours_1re-1.pdf\">cours_1re<\/a><a href=\"https:\/\/iremi.univ-reunion.fr\/wp-content\/uploads\/2024\/12\/cours_1re-1.pdf\" class=\"wp-block-file__button wp-element-button\" download aria-describedby=\"wp-block-file--media-f6f5cc56-5b59-42a3-a8f2-b9aab5d44063\">T\u00e9l\u00e9charger<\/a><\/div>\n\n\n\n<p>Cours de Terminale NSI :<\/p>\n\n\n\n<div data-wp-interactive=\"core\/file\" class=\"wp-block-file\"><object data-wp-bind--hidden=\"!state.hasPdfPreview\" hidden class=\"wp-block-file__embed\" data=\"https:\/\/iremi.univ-reunion.fr\/wp-content\/uploads\/2024\/12\/cours_Tle-1.pdf\" type=\"application\/pdf\" style=\"width:100%;height:600px\" aria-label=\"Contenu embarqu\u00e9 cours_Tle.\"><\/object><a id=\"wp-block-file--media-4565ed66-1e29-4645-bdb4-05473c7b9918\" href=\"https:\/\/iremi.univ-reunion.fr\/wp-content\/uploads\/2024\/12\/cours_Tle-1.pdf\">cours_Tle<\/a><a href=\"https:\/\/iremi.univ-reunion.fr\/wp-content\/uploads\/2024\/12\/cours_Tle-1.pdf\" class=\"wp-block-file__button wp-element-button\" download aria-describedby=\"wp-block-file--media-4565ed66-1e29-4645-bdb4-05473c7b9918\">T\u00e9l\u00e9charger<\/a><\/div>\n","protected":false},"excerpt":{"rendered":"<p>En NSI, la programmation objet n&rsquo;est au programme qu&rsquo;en Terminale. Toutefois, on gagne \u00e0 l&rsquo;aborder d\u00e8s la classe (!) de Premi\u00e8re, car elle simplifie certains apprentissages. Le langage choisi est Python 3, qui est pr\u00e9cis\u00e9ment un langage de programmation objet. Une progression est propos\u00e9e ici, bas\u00e9e sur la POO, pour le cours sur les donn\u00e9es [&hellip;]<\/p>\n","protected":false},"author":6,"featured_media":1258,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9,10],"tags":[32,35,17],"coauthors":[54],"class_list":["post-1240","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-algorithmes-programmation-et-langages","category-machines-information-codage","tag-lycee","tag-nsi","tag-python"],"_links":{"self":[{"href":"https:\/\/iremi.univ-reunion.fr\/index.php?rest_route=\/wp\/v2\/posts\/1240","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/iremi.univ-reunion.fr\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/iremi.univ-reunion.fr\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/iremi.univ-reunion.fr\/index.php?rest_route=\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/iremi.univ-reunion.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1240"}],"version-history":[{"count":23,"href":"https:\/\/iremi.univ-reunion.fr\/index.php?rest_route=\/wp\/v2\/posts\/1240\/revisions"}],"predecessor-version":[{"id":1764,"href":"https:\/\/iremi.univ-reunion.fr\/index.php?rest_route=\/wp\/v2\/posts\/1240\/revisions\/1764"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/iremi.univ-reunion.fr\/index.php?rest_route=\/wp\/v2\/media\/1258"}],"wp:attachment":[{"href":"https:\/\/iremi.univ-reunion.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1240"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/iremi.univ-reunion.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1240"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/iremi.univ-reunion.fr\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1240"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/iremi.univ-reunion.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fcoauthors&post=1240"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}