▸ Le langage Fortran, taillé pour la science, introduit le tableau indexé : une rangée de cases qu'on appelle par leur numéro de position plutôt qu'une à une.
▸ 70 ans plus tard, c'est exactement ce que fait la list de Python et le array de NumPy.
▸ L'index n'est pas un « rang » mais un décalage depuis le début : le 1er élément est à 0 case du départ. Dijkstra a défendu ce choix en 1982.
▸ D'où le réflexe Python qui surprend tout le monde : la première case porte le numéro 0. 😅
On relève la température de 5 fioles. Avec ce qu'on connaît, on crée une variable par mesure :
Cinq variables séparées, ça va. Mais on ne peut pas les parcourir, ni en ajouter une 6e sans réécrire du code. Il faut un contenant unique.
Une liste, c'est une rangée de cases numérotées. Le nom mesures désigne toute la rangée ; chaque case garde sa position.
Une liste peut contenir des nombres, du texte (["lun", "mar"]), des bool… et même être vide au départ : mesures = [], qu'on remplira plus tard.
Pour lire une seule case, on écrit le nom suivi de son index entre crochets. mesures[2] allume la case n° 2 et renvoie sa valeur : 7. Une case à la fois.
| On écrit | La case allumée | Valeur obtenue |
|---|---|---|
| mesures[0] | la 1re case | 12 |
| mesures[1] | la 2e case | 19 |
| mesures[4] | la 5e (dernière) case | 15 |
| mesures[5] | ❌ il n'y a pas de case 5 | IndexError |
Cinq éléments → des index de 0 à 4. Demander mesures[5] provoque une erreur IndexError : on dépasse le bout de la rangée. Le dernier index vaut toujours longueur − 1.
Python accepte les index négatifs : mesures[-1] est le dernier élément (15), mesures[-2] l'avant-dernier. Pratique pour attraper la fin sans connaître la longueur.
Une liste est vivante : on remplace une case avec mesures[0] = 99, on compte ses éléments avec len(mesures), et mesures.append(30) ajoute une case à la fin.
range(len(mesures)) → 0, 1, 2, 3, 4Le corps print(mesures[position]) est exactement le même des deux côtés. La boucle ne fait que faire varier position de 0 à 4 à notre place : c'est le range du Jour 3 qui fournit les index, len(mesures) donne la bonne borne.
À chaque tour, mesure prend la valeur de la case suivante. Après la dernière, la liste est épuisée : la boucle s'arrête.
Quand on veut juste les valeurs, une à une. Le plus simple et le plus lisible.
Quand on a besoin du numéro de la case en plus de la valeur (pour numéroter, comparer des positions…).
range(len(mesures)) fabrique les index 0, 1, 2, 3, 4 : la boucle (Jour 3) et la liste (Jour 4) travaillent ensemble. Réflexe : si tu n'as pas besoin de la position, prends la forme de gauche.
+= sur une liste ?Au Jour 1, compteur += 1 ajoutait à un nombre. += marche aussi sur une liste - mais attention : sur une liste, += fait .extend(), pas .append(). Il fusionne une autre liste.
Même résultat ici - mais += attend une liste : il faut les crochets autour de l'élément. C'est .extend() déguisé, pas .append(). Et c'est là que les pièges commencent…
+=+= parcourt ce qu'on lui donne (comme .extend()). Un 4 tout seul n'est pas parcourable → erreur. Une chaîne, elle, est parcourable… alors il ajoute chaque lettre ! Mais pourquoi une chaîne se parcourt lettre par lettre ? 👉
mot[0] → "P"mot[-1] → "N"len(mot) → 6Une chaîne est une séquence de caractères, exactement comme une liste : index, [-1], len - tout marche pareil. Une seule différence : une chaîne est figée (on ne peut pas faire mot[0] = "X").
Une chaîne se parcourt comme une liste : for lettre in mot. C'est exactement ça que faisait mots += "ch" - parcourir la chaîne lettre par lettre. 💡 Pour ajouter une chaîne entière comme un seul élément : mots.append("ch") ou mots += ["ch"].
| Méthode | Ce qu'elle fait | Exemple → résultat |
|---|---|---|
| .append(x) | ajoute x à la fin | [10, 20].append(30) → [10, 20, 30] |
| .insert(i, x) | insère x à la position i | [10, 30].insert(1, 20) → [10, 20, 30] |
| .remove(x) | retire la 1re occurrence de x (par valeur) | [10, 20, 30].remove(20) → [10, 30] |
| .pop() | retire et renvoie le dernier | [10, 20, 30].pop() → renvoie 30 |
| .pop(i) | retire et renvoie l'élément de position i | [10, 20, 30].pop(0) → renvoie 10 |
| .extend([…]) | ajoute tous les éléments (c'est le +=) | [10].extend([20, 30]) → [10, 20, 30] |
append, insert, remove, extend modifient la liste en place (ils ne renvoient rien). pop est le seul qui renvoie la valeur retirée - pratique pour la récupérer en l'enlevant. Repère : insert/pop visent une position, remove vise une valeur.
in et not inin répond par True ou False à la question « est-ce que c'est dans la liste ? ». not in demande l'inverse. C'est la façon la plus courte de chercher.
Très souvent dans un if : if 7 in mesures: … C'est le raccourci pour chercher (on verra au Jour 5 comment le faire « à la main » avec une boucle). Bonus : dans une chaîne, in trouve aussi des morceaux de mots.
sorted(), sum(), max()…À côté des méthodes (liste.append()), Python a des fonctions qui prennent la liste entre parenthèses et renvoient un résultat sans la modifier.
| Fonction | Ce qu'elle fait | Exemple → résultat |
|---|---|---|
| sorted(liste) | renvoie une copie triée (l'originale intacte) | sorted([3, 1, 2]) → [1, 2, 3] |
| sum(liste) | additionne tous les éléments | sum([3, 1, 2]) → 6 |
| max(liste) | le plus grand | max([3, 1, 2]) → 3 |
| min(liste) | le plus petit | min([3, 1, 2]) → 1 |
| len(liste) | combien d'éléments | len([3, 1, 2]) → 3 |
Repère la syntaxe : fonction(liste) (parenthèses) ≠ liste.méthode() (point). Piège classique : sorted(liste) renvoie une copie triée, alors que liste.sort() trie en place et ne renvoie rien (None). sum/min/max ne marchent que sur des nombres.
| On écrit | Ce que ça fait d'un coup | Résultat |
|---|---|---|
| mesures[-1] | le dernier élément, sans compter | 15 |
| mesures[::-1] | la liste à l'envers | [15, 22, 7, 19, 12] |
| debut, fin = paire | ranger plusieurs valeurs en une ligne | décompactage |
| sum(mesures) | le total, sans écrire de boucle | 75 |
| 19 in mesures | la valeur est-elle présente ? | True |
| list(range(1, 6)) | fabriquer une liste de nombres | [1, 2, 3, 4, 5] |
Avec enumerate(mesures) dans un for, tu obtiens la position ET la valeur en même temps. Et sum, max, min calculent total, maximum et minimum sans aucune boucle.
▸ En une seule ligne, on fabrique une liste à partir d'une autre :
carres = [mesure**2 for mesure in mesures]
▸ On peut même filtrer : [mesure for mesure in mesures if mesure >= 15] ne garde que les grandes valeurs. Le raccourci préféré des pros.
▸ copie = mesures[:] crée une vraie copie, indépendante.
▸ Mais copie = mesures ne copie rien : c'est un 2e nom sur la même liste. Modifier l'une modifie l'autre ! Le piège classique de tous les débutants. 😱
Pour doubler chaque mesure d'une liste, il faut une boucle et tout recopier. Et multiplier deux listes terme à terme ? Encore une boucle.
Pour des milliers de mesures en physique ou en chimie, c'est lent et verbeux.
import numpy as np donne le tableau (array) : on calcule sur tout le tableau d'un coup, sans boucle.
mesures * 2 double les 1000 valeurs en une ligne, et très vite. C'est l'outil de toutes les sciences.
| On écrit | Ce que ça fabrique | Résultat |
|---|---|---|
| np.array([12, 19, 7]) | une liste → un tableau | [12 19 7] |
| np.zeros(5) | 5 cases à zéro | [0. 0. 0. 0. 0.] |
| np.ones(3) | 3 cases à un | [1. 1. 1.] |
| np.arange(0, 10, 2) | comme range, en tableau | [0 2 4 6 8] |
| np.linspace(0, 1, 5) | 5 valeurs régulières de 0 à 1 | [0. 0.25 0.5 0.75 1.] |
zeros et ones préparent un tableau à remplir plus tard. arange est le range de NumPy. linspace (le préféré des sciences) découpe un intervalle en N points également espacés - parfait pour un axe de graphique.
Le tableau applique l'opération à chaque case en même temps : pas de boucle, pas d'append. C'est ce qu'on appelle le calcul vectorisé - le cœur de NumPy, et bientôt de tes graphiques.
Dans Jupyter / Colab, écris le nom de la variable en dernière ligne d'une cellule : elle s'affiche toute seule, sans print. Et l'explorateur de variables montre une liste comme un tableau qu'on peut parcourir.
Avec fioles = [12, 19, 7, 22, 15], devine avant d'exécuter :