Aide-mémoire : les tableaux et les listes

Python - ranger plusieurs valeurs dans une seule variable, puis calculer en bloc avec NumPy (Semaine 1 · Jour 4)

créer / lire modifier trancher parcourir tableaux NumPy pièges fréquents

Une liste : des cases numérotées

Une liste range plusieurs valeurs côte à côte. Chaque case a un indice qui commence à 0. On peut aussi compter à l'envers avec des indices négatifs.

"Lun"
[0]
[-4]
"Mar"
[1]
[-3]
"Mer"
[2]
[-2]
"Jeu"
[3]
[-1]
jours = ["Lun", "Mar", "Mer", "Jeu"] print(jours[0]) # Lun (première case) print(jours[-1]) # Jeu (dernière case) print(len(jours)) # 4 (nombre de cases)

L'indice 0 est la première case, l'indice -1 la dernière. len() donne la longueur ; le dernier indice valide est donc len - 1.

Créer, modifier, parcourir

La liste est modifiable : on change une case, on en ajoute, on en retire, et on la parcourt avec une boucle.

Créer une liste

[ … ] · liste vide

notes = [85, 92, 78] vide = [] # on remplira plus tard

Les éléments entre crochets, séparés par des virgules. Une liste peut contenir des nombres, des textes, etc.

Changer une case

liste[indice] = valeur

notes = [85, 92, 78] notes[1] = 100 print(notes)
[85, 100, 78]

On écrase la valeur à l'indice donné. La case doit déjà exister.

Ajouter des éléments

.append() · .insert()

notes.append(90) # à la fin notes.insert(0, 70) # à l'indice 0

append ajoute à la fin ; insert glisse une valeur à une position et décale le reste.

Retirer des éléments

.remove() · .pop() · del

notes.remove(78) # par valeur notes.pop() # retire la dernière del notes[0] # par indice

remove cherche une valeur ; pop et del visent un indice (sans argument, pop prend le dernier).

Parcourir les éléments

for élément in liste

for note in notes: print(note)

La variable prend chaque élément directement, sans toucher aux indices. Le cas le plus courant.

Parcourir avec l'indice

for i in range(len(liste))

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

Quand on a besoin du numéro de case en plus de la valeur (pour la modifier, par exemple).

Trancher : prendre un morceau

Avec liste[début:fin] on extrait une sous-liste. Comme pour range, la borne de fin est exclue.

On écritSur [10, 20, 30, 40, 50]On obtient
liste[1:3]de l'indice 1 jusqu'avant 3[20, 30]
liste[:2]du début jusqu'avant 2[10, 20]
liste[2:]de l'indice 2 jusqu'à la fin[30, 40, 50]
liste[-2:]les deux dernières[40, 50]
liste[::2]une case sur deux (pas de 2)[10, 30, 50]

Sans premier nombre, on part du début ; sans second, on va jusqu'à la fin. Le découpage crée une nouvelle liste, l'originale ne bouge pas.

Méthodes et tests utiles

Quelques fonctions et méthodes qui reviennent tout le temps. sum, min, max ne marchent que sur des listes de nombres.

On écritEffetExemple → résultat
len(liste)nombre d'élémentslen([5, 8, 2]) → 3
valeur in listeteste la présence (True / False)8 in [5, 8, 2] → True
valeur not in listeteste l'absence (True / False)3 not in [5, 8, 2] → True
liste.count(x)compte les occurrences de x[2, 2, 5].count(2) → 2
liste.index(x)indice de la 1re occurrence[5, 8, 2].index(8) → 1
liste.sort()trie sur place (modifie la liste)[3,1,2] → [1, 2, 3]
liste.reverse()inverse l'ordre sur place[1,2,3] → [3, 2, 1]
sorted(liste)renvoie une copie triée (originale intacte)sorted([3,1,2]) → [1, 2, 3]
sorted(liste, reverse=True)copie triée en ordre décroissantsorted([3,1,2], reverse=True) → [3, 2, 1]
sum(liste)additionne tous les élémentssum([5, 8, 2]) → 15
max(liste)le plus grand élémentmax([5, 8, 2]) → 8
min(liste)le plus petit élémentmin([5, 8, 2]) → 2

À distinguer : sort() modifie la liste et ne renvoie rien ; sorted() renvoie une nouvelle liste et laisse l'originale tranquille.

Les tableaux NumPy : calculer sur tout d'un coup

Une liste range les valeurs ; un tableau NumPy (array) sait calculer dessus en bloc, sans boucle, et bien plus vite. On l'utilise dès qu'on fait des maths sur beaucoup de nombres. On l'importe d'abord : import numpy as np.

Depuis une liste

np.array([ … ])

import numpy as np notes = np.array([85, 92, 78]) print(notes)
[85 92 78]

On part d'une liste Python et on la transforme en tableau. À l'affichage, pas de virgules entre les valeurs : c'est le signe d'un tableau NumPy.

Tableaux tout faits

np.zeros · np.ones · np.arange · np.linspace

np.zeros(3) # [0. 0. 0.] np.ones(3) # [1. 1. 1.] np.arange(0, 10, 2) # [0 2 4 6 8] np.linspace(0, 1, 5) # [0. 0.25 0.5 0.75 1.]

arange = comme range (fin exclue). linspace(a, b, n) = n valeurs régulières de a à b, bornes incluses. Parfait pour un axe de graphique.

Lire et trancher

tableau[indice] · tableau[début:fin]

notes[0] # 85 (comme une liste) notes[-1] # 78 notes[1:3] # [92 78] len(notes) # 3

Indices, tranches et len fonctionnent exactement comme sur une liste. Rien de nouveau à apprendre de ce côté.

Calculer en bloc, sans boucle

La grande force de NumPy : une opération s'applique à chaque élément en même temps (on dit « vectorisé »). Là où une liste demanderait une boucle, le tableau fait tout d'un coup.

Opérer sur tout le tableau

tableau + nombre · tableau * nombre

notes = np.array([85, 92, 78]) print(notes + 5) print(notes / 100)
[90 97 83] [0.85 0.92 0.78]

Le calcul touche chaque case. Avec une liste, notes + 5 serait une erreur : ça, c'est le pouvoir du tableau.

Deux tableaux ensemble

tableau1 + tableau2 (même taille)

prix = np.array([10, 20, 30]) quantite = np.array([2, 1, 4]) print(prix * quantite)
[ 20 20 120]

Case par case : 10×2, 20×1, 30×4. Les deux tableaux doivent avoir la même longueur.

Statistiques d'un coup

.sum() · .mean() · .std() · np.median()

notes.sum() # 255 (somme) notes.mean() # 85.0 (moyenne) notes.min() # 78 notes.max() # 92 notes.std() # écart-type np.median(notes) # 85.0 (médiane)

mean (moyenne) et std (écart-type) n'existent pas sur une liste Python : c'est tout l'intérêt de NumPy. Attention : la médiane n'est pas une méthode (notes.median() n'existe pas), c'est la fonction np.median(notes).

Filtrer selon une condition

tableau[ condition ]

notes = np.array([85, 52, 78, 40]) print(notes >= 60) print(notes[notes >= 60])
[ True False True False] [85 78]

La condition donne un tableau de True/False, puis on le met entre crochets pour ne garder que les cases vraies. Très pratique pour trier des données.

Trier le tableau

np.sort(tableau) · tableau.sort()

notes = np.array([85, 52, 78]) print(np.sort(notes)) # copie triée print(np.sort(notes)[::-1]) # ordre décroissant notes.sort() # trie sur place
[52 78 85] [85 78 52]

np.sort(tableau) renvoie une copie triée ; tableau.sort() modifie le tableau et ne renvoie rien (comme pour une liste). Pas de reverse=True : on inverse avec [::-1].

Les pièges qui font perdre du temps

Cinq erreurs qui reviennent tout le temps avec les listes et les tableaux.

Les indices commencent à 0

jours = ["Lun", "Mar", "Mer"] jours[1] # "Mar", PAS "Lun"

La première case est [0]. Pour 3 éléments, les indices valides sont 0, 1, 2.

Dépasser la dernière case

jours[3] # IndexError : seulement 0,1,2

Le dernier indice valide est len(liste) - 1. Au-delà, c'est une erreur. Utilise [-1] pour la dernière.

sort() ne renvoie rien

triee = notes.sort() # triee vaut None ! notes.sort() # ✓ la liste est triée en place

sort() change la liste directement. Pour récupérer une copie triée, utilise sorted(notes).

Deux noms, une seule liste

b = a # même liste, deux noms b.append(9) # a change aussi ! b = a.copy() # ✓ vraie copie indépendante

Affecter une liste ne la duplique pas : les deux noms pointent la même. Pour une copie réelle, a.copy() ou a[:].

Liste + nombre ne marche pas

notes = [85, 92] notes + 5 # TypeError ! np.array(notes) + 5 # ✓ [90 97]

Le calcul en bloc n'existe que sur un tableau NumPy. Sur une liste, + demande une autre liste (et la colle au bout au lieu d'additionner).