Les listes
Informatique — Python, chapitre 3
Une variable retient une valeur. Pour en retenir mille — les revenus d’un échantillon, les années d’une série — il faut une structure qui les rassemble. En Python, c’est la liste.
Elle occupe la place qu’a le vecteur en R, avec une différence majeure : elle n’est pas vectorisée. Multiplier une liste par 2 ne double pas ses valeurs. C’est précisément ce manque qui justifiera NumPy au chapitre 8.
3.1 Créer une liste
3.1.1 Une liste accepte tous les types
Cette souplesse distingue Python de R, où un vecteur convertit tout au type le plus général. Ici, chaque élément garde son type — et le prix de cette souplesse est la lenteur du calcul, que NumPy corrigera.
3.2 Extraire
3.2.1 Par position
Les règles sont exactement celles des chaînes du chapitre précédent.
3.2.2 Les tranches
v = [4, 8, 15]
print(v[10]) # IndexError
print(v[1:10]) # renvoie [8, 15], sans se plaindreUn indice hors limites déclenche une erreur ; une tranche hors limites s’arrête simplement où la liste s’arrête.
C’est commode, mais cela masque parfois un bug : une tranche qui renvoie moins d’éléments que prévu ne le signale pas.
3.3 Modifier
3.3.1 Une liste se modifie sur place
C’est la différence essentielle avec les chaînes.
3.3.2 Ajouter et retirer
append et extend ne font pas la même chose
a = [1, 2]
a.append([3, 4]) # [1, 2, [3, 4]] : un seul element ajoute
b = [1, 2]
b.extend([3, 4]) # [1, 2, 3, 4] : deux elements ajoutesappend ajoute un élément, quel qu’il soit — même une liste entière. extend ajoute chaque élément d’un ensemble.
Essayez les deux dans la console : le résultat est très différent.
3.3.3 Les méthodes qui ne renvoient rien
None, le piège du débutant
v = v.append(16) # v vaut maintenant None : la liste est perdueLes méthodes qui modifient une liste — append, extend, insert, remove, sort, reverse — travaillent sur place et renvoient None.
Écrivez v.append(16) seul, sans affectation. C’est l’inverse exact des chaînes du chapitre 2, où il fallait impérativement réaffecter.
3.4 Trier
sorted renvoie, sort modifie. Retenez la règle générale : en Python, une fonction renvoie une valeur, une méthode de liste modifie souvent sur place.
L’argument key reçoit une fonction indiquant sur quoi trier. lambda x: x[1] est une fonction anonyme — « prends l’élément, renvoie sa deuxième composante ». Le chapitre 6 y revient.
3.5 Le piège de la copie
C’est le point le plus important du chapitre, et celui qui coûte le plus cher quand on l’ignore.
b = a ne copie pas, il donne un second nom
a et b désignent le même objet en mémoire. Modifier l’un modifie l’autre, puisqu’il n’y en a qu’un.
Pour obtenir une vraie copie :
b = a.copy() # ou : b = a[:] ou b = list(a)Ce comportement vaut pour tous les objets modifiables de Python : listes, dictionnaires, et les tableaux NumPy du chapitre 8. Il est à l’origine de bugs particulièrement déroutants, où une variable change sans qu’aucune ligne ne semble la toucher.
3.6 Les compréhensions de liste
C’est l’écriture la plus caractéristique de Python, et la plus élégante.
La lecture se fait de gauche à droite : pour chaque x de v, garde x * 2. Avec un if à la fin, on filtre.
C’est ainsi qu’on compense l’absence de vectorisation : [x * 2 for x in v] remplace le v * 2 de R.
Une compréhension doit rester lisible. Dès qu’elle comporte deux for imbriqués et un if, la boucle explicite du chapitre suivant est préférable.
Le critère est simple : si vous devez la relire deux fois pour la comprendre, écrivez une boucle.
3.7 Calculer sur une liste
mean ?
Python de base n’a pas de fonction moyenne : ce n’est pas un langage statistique. Le module statistics en fournit une, mais lente.
import statistics
print(statistics.mean(v))
print(statistics.stdev(v))Pour de vrais calculs, on emploie NumPy — d’où le plan de ce cours, qui aborde le langage d’abord et les bibliothèques ensuite.
3.8 Le tuple, une liste qu’on ne peut pas modifier
Le tuple sert quand un groupe de valeurs forme un tout qui ne doit pas changer — des coordonnées, un couple clé-valeur. Il permet aussi l’affectation multiple, très employée pour récupérer les résultats multiples d’une fonction.
À vous
À partir d’une liste de notes, calculez la moyenne, la liste des notes supérieures ou égales à 10, et le nombre de reçus — sans écrire de boucle explicite.
moyenne = sum(notes) / len(notes)
print(f"moyenne : {moyenne:.2f}")
recues = [n for n in notes if n >= 10]
print(recues)
print(f"{len(recues)} recus sur {len(notes)}")
print(f"taux : {len(recues) / len(notes):.1%}")Les compréhensions remplacent ici trois boucles. Comparez avec ce que R écrirait — notes[notes >= 10] — et vous mesurerez ce que la vectorisation apporte, et ce que NumPy viendra rétablir.
Ce qu’il faut retenir
| Écriture | Effet |
|---|---|
[4, 8, 15] |
créer une liste |
v[0], v[-1] |
premier, dernier — on compte depuis 0 |
v[1:4] |
tranche — borne de fin exclue |
v[0] = 100 |
modifier — une liste est modifiable, une chaîne non |
append, insert, extend, remove, pop |
ajouter et retirer |
| méthodes de liste | modifient sur place et renvoient None |
sorted(v) / v.sort() |
renvoie une copie triée / trie sur place |
b = a.copy() |
vraie copie — b = a n’en est pas une |
[x * 2 for x in v] |
compréhension : construire une liste en une ligne |
[x for x in v if x > 15] |
compréhension filtrante |
sum, len, max, min |
calculer — pas de mean natif |
(45.2, 8.4) |
tuple : une liste immuable |
Le chapitre suivant formalise ce que les compréhensions faisaient discrètement : la boucle, qui répète un traitement.