Semaine 1 · Jour 4 · 420-SN1

LISTES & TABLEAUX

0
1
2
3
4
Une seule variable pour ranger toute une collection de valeurs
🧑‍🚀 EN SAVOIR PLUS · UN PEU D'HISTOIRE

Ranger des nombres en file, une vieille idée

Fortran · 1957

01234

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.

Pourquoi compter à partir de 0 ?

+0 +1 décalage

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. 😅

Le problème : 5 variables qui se ressemblent

On relève la température de 5 fioles. Avec ce qu'on connaît, on crée une variable par mesure :

mesure1 = 12 mesure2 = 19 mesure3 = 7 mesure4 = 22 mesure5 = 15
et pour 1000 fioles ? 1000 noms de variables ? Impossible à parcourir avec une boucle.

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.

La solution : une seule liste

mesures = [12, 19, 7, 22, 15]
1 nom contient les 5 valeurs, dans l'ordre, prêtes à parcourir.
12
0
19
1
7
2
22
3
15
4

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.

Anatomie d'une liste

mesures = [12, 19, 7, 22, 15]
[ ]
les crochets ouvrent et ferment la liste
,
la virgule sépare chaque élément
12, 19, 7…
les éléments : autant qu'on veut, dans l'ordre
mesures
le nom de la liste entière

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.

Accéder à UN élément : son numéro de case

mesures[2]7
12
0
19
1
7
2
22
3
15
4

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.

Le réflexe Python : on commence à 0

On écritLa case alluméeValeur obtenue
mesures[0]la 1re case12
mesures[1]la 2e case19
mesures[4]la 5e (dernière) case15
mesures[5]❌ il n'y a pas de case 5IndexError

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.

Compter depuis la fin : les index négatifs

12
0-5
19
1-4
7
2-3
22
3-2
15
4-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.

Modifier, mesurer, agrandir

# changer une case mesures[0] = 99 print(mesures) # combien d'éléments ? print(len(mesures))
[99, 19, 7, 22, 15] 5
# ajouter au bout mesures.append(30) print(mesures) print(len(mesures))
[99, 19, 7, 22, 15, 30] 6

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.

Parcourir avec une variable position

DÉROULÉ on change position à la main
position = 0 print(mesures[position]) position = 1 print(mesures[position]) position = 2 print(mesures[position]) position = 3 print(mesures[position]) position = 4 print(mesures[position])
EN BOUCLE range fait varier position (Jour 3 !)
for position in range(len(mesures)): print(mesures[position])
range(len(mesures)) → 0, 1, 2, 3, 4

Le 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.

Le fil du parcours, tour par tour

for mesure in mesures: print("fiole :", mesure)
Tour
mesure
La case visitée
Ce qui s'affiche
1
12
mesures[0]
fiole : 12
2
19
mesures[1]
fiole : 19
3
7
mesures[2]
fiole : 7
4
22
mesures[3]
fiole : 22
5
15
mesures[4]
fiole : 15

À 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.

Deux façons de parcourir une liste

for élément in liste

Quand on veut juste les valeurs, une à une. Le plus simple et le plus lisible.

for mesure in mesures: print(mesure)
for position in range(len(liste))

Quand on a besoin du numéro de la case en plus de la valeur (pour numéroter, comparer des positions…).

for position in range(len(mesures)): print(position, mesures[position])

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.

Et le += 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.

.append(4) ajoute UN élément
nombres = [1, 2, 3] nombres.append(4) print(nombres) # [1, 2, 3, 4] ✅
+= [4] fusionne une liste
nombres = [1, 2, 3] nombres += [4] print(nombres) # [1, 2, 3, 4] ✅

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…

⚠️ Deux pièges du +=

SANS crochets ça plante
nombres = [1, 2, 3] nombres += 4
TypeError: 'int' object is not iterable
une CHAÎNE elle éclate 😱
mots = ["a", "b"] mots += "ch" print(mots)
['a', 'b', 'c', 'h'] 😱

+= 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 ? 👉

Une chaîne est un tableau de lettres

mot = "PYTHON"
P
0
Y
1
T
2
H
3
O
4
N
5
mot[0]"P"
mot[-1]"N"
len(mot)6

Une 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").

Parcourir une chaîne, lettre par lettre

mot = "ALLO" for lettre in mot: print(lettre)
A L L O

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émo : les méthodes d'une liste

MéthodeCe qu'elle faitExemple → 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.

Est-ce là-dedans ? in et not in

in 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.

dans une liste cherche un élément
mesures = [12, 19, 7] 7 in mesures # True ✅ 99 in mesures # False 99 not in mesures # True
dans une chaîne cherche une sous-chaîne
"a" in "chat" # True "z" in "chat" # False "ch" in "chat" # True 😯 # une sous-chaîne, pas # juste une lettre !

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.

Les fonctions : 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.

FonctionCe qu'elle faitExemple → 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émentssum([3, 1, 2]) → 6
max(liste)le plus grandmax([3, 1, 2]) → 3
min(liste)le plus petitmin([3, 1, 2]) → 1
len(liste)combien d'élémentslen([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.

💡 TRUCS DE PRO · LES RACCOURCIS QUI FONT GAGNER DU TEMPS

Les gestes que connaissent les pros

On écritCe que ça fait d'un coupRésultat
mesures[-1]le dernier élément, sans compter15
mesures[::-1]la liste à l'envers[15, 22, 7, 19, 12]
debut, fin = paireranger plusieurs valeurs en une lignedécompactage
sum(mesures)le total, sans écrire de boucle75
19 in mesuresla 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 SAVOIR PLUS · DEUX OUTILS PUISSANTS

Fabriquer une liste, copier une liste

La compréhension de liste

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.

Le piège de la copie

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. 😱

🔢 LE TABLEAU DES SCIENTIFIQUES · NUMPY

Quand la liste devient un tableau de calcul

Le problème des listes

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.

La réponse : NumPy

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.

Les générateurs de tableau de NumPy

On écritCe que ça fabriqueRé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.

La magie : calculer sur tout le tableau d'un coup

LISTE il faut une boucle
celsius = [0, 20, 37] fahrenheit = [] for temperature in celsius: fahrenheit.append(temperature * 9/5 + 32)
TABLEAU NUMPY une ligne
celsius = np.array([0, 20, 37]) fahrenheit = celsius * 9/5 + 32 # [ 32. 68. 98.6]

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.

💡 TRUC DE PRO · VOIR UNE LISTE SANS S'ARRACHER LES YEUX

Afficher proprement une liste ou un tableau

print() brut tout sur une ligne
print(grille)
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
en grille alignée et lisible
print(np.array(grille))
[[1 2 3] [4 5 6] [7 8 9]]

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.

À TOI DE JOUER

Avec fioles = [12, 19, 7, 22, 15], devine avant d'exécuter :

fioles[1] → ?
fioles[-1] → ?
len(fioles) → ?
code.experimentations.xyz/calepins/semaine-1-jour-4-listes-tableaux/

AU TRAVAIL !

0
1
2
Séance 1-4 : une variable, une rangée de cases, et NumPy pour calculer sur tout d'un coup
⤺ Refermer le diaporama