08 - Listes
Définition
Une liste est une structure de données qui permet de stocker plusieurs valeurs dans une seule variable, les unes à la suite des autres. Pensez à une liste de courses, une liste de notes ou un classement sportif : c’est le même principe en Python.
Une liste en Python possède les propriétés suivantes :
- elle peut contenir un nombre quelconque d’éléments (y compris zéro) ;
- les éléments sont ordonnés : chacun a une position (un indice) ;
- les éléments peuvent être de types différents (entiers, chaînes, etc.) ;
- elle est modifiable (on peut ajouter, supprimer ou remplacer des éléments).
Création d’une liste
On crée une liste en plaçant les éléments entre crochets [], séparés par des virgules :
# Une liste de prénoms
prenoms = ["Alice", "Bob", "Charlie", "Diana"]
# Une liste de notes
notes = [15, 12, 18, 14, 16]
# Une liste vide
panier = []
print(prenoms)
print(notes)
['Alice', 'Bob', 'Charlie', 'Diana']
[15, 12, 18, 14, 16]
On peut aussi créer une liste à partir d’une autre séquence avec la fonction list() :
lettres = list("Python")
print(lettres)
['P', 'y', 't', 'h', 'o', 'n']
Accès aux éléments par indice
Chaque élément est repéré par son indice, c’est-à-dire sa position dans la liste. Le premier élément est à l’indice 0, le deuxième à l’indice 1, et ainsi de suite.
prenoms = ["Alice", "Bob", "Charlie", "Diana"]
print(prenoms[0]) # premier élément
print(prenoms[2]) # troisième élément
print(prenoms[-1]) # dernier élément
Alice
Charlie
Diana
Les indices négatifs permettent de compter à partir de la fin : -1 pour le dernier, -2 pour l’avant-dernier, etc.
Attention : un indice hors limites provoque une erreur.
prenoms = ["Alice", "Bob", "Charlie", "Diana"]
print(prenoms[10]) # IndexError: list index out of range
Longueur d’une liste
La fonction len() renvoie le nombre d’éléments d’une liste :
notes = [15, 12, 18, 14, 16]
print(len(notes))
5
Les indices valides vont donc de 0 à len(L) - 1.
Modifier un élément
Les listes sont mutables : on peut modifier un élément en le réaffectant par son indice.
notes = [15, 12, 18, 14, 16]
print(notes)
notes[1] = 14 # on corrige la deuxième note
print(notes)
[15, 12, 18, 14, 16]
[15, 14, 18, 14, 16]
Parcourir une liste
Parcours par élément (méthode usuelle)
fruits = ["pomme", "banane", "cerise", "mangue"]
for fruit in fruits:
print(f"J'aime les {fruit}s")
J'aime les pommes
J'aime les bananes
J'aime les cerises
J'aime les mangues
Parcours par indice
fruits = ["pomme", "banane", "cerise", "mangue"]
for i in range(len(fruits)):
print(f"Fruit n°{i} : {fruits[i]}")
Fruit n°0 : pomme
Fruit n°1 : banane
Fruit n°2 : cerise
Fruit n°3 : mangue
Parcours avec enumerate()
La fonction enumerate() fournit à la fois l’indice et l’élément :
fruits = ["pomme", "banane", "cerise", "mangue"]
for i, fruit in enumerate(fruits):
print(f"Fruit n°{i} : {fruit}")
Méthodes principales
Ajouter des éléments
couleurs = ["rouge", "vert"]
couleurs.append("bleu") # ajoute à la fin
print(couleurs)
couleurs.insert(1, "jaune") # insère à l'indice 1
print(couleurs)
['rouge', 'vert', 'bleu']
['rouge', 'jaune', 'vert', 'bleu']
Supprimer des éléments
couleurs = ["rouge", "jaune", "vert", "bleu"]
couleurs.remove("jaune") # supprime par valeur
print(couleurs)
dernier = couleurs.pop() # retire et renvoie le dernier
print(dernier)
print(couleurs)
['rouge', 'vert', 'bleu']
bleu
['rouge', 'vert']
Autres méthodes utiles
| Méthode | Description | Exemple |
|---|---|---|
L.append(x) | Ajoute x à la fin | notes.append(17) |
L.insert(i, x) | Insère x à l’indice i | notes.insert(0, 20) |
L.pop() | Retire et renvoie le dernier élément | notes.pop() |
L.remove(x) | Retire la première occurrence de x | notes.remove(12) |
L.sort() | Trie la liste en place | notes.sort() |
L.reverse() | Inverse l’ordre des éléments | notes.reverse() |
L.index(x) | Renvoie l’indice de la première occurrence de x | notes.index(18) |
L.count(x) | Compte le nombre d’occurrences de x | notes.count(14) |
Important : append(), sort(), reverse() et remove() modifient la liste en place et ne renvoient rien (None). Il ne faut donc pas écrire L = L.sort().
Opérations sur les listes
# Concaténation avec +
a = [1, 2, 3]
b = [4, 5]
print(a + b)
# Répétition avec *
print([0] * 5)
# Test d'appartenance avec in
print(3 in a)
print(7 in a)
[1, 2, 3, 4, 5]
[0, 0, 0, 0, 0]
True
False
Fonctions utiles sur les listes
notes = [15, 12, 18, 14, 16]
print(len(notes)) # nombre d'éléments : 5
print(min(notes)) # minimum : 12
print(max(notes)) # maximum : 18
print(sum(notes)) # somme : 75
print(sum(notes) / len(notes)) # moyenne : 15.0
Attention : copie et référence
En Python, une liste est un objet mutable. Quand on écrit b = a, on ne crée pas une copie de la liste : on crée un second nom qui désigne la même liste en mémoire. Toute modification via b affecte aussi a, et inversement.
a = [1, 2, 3]
b = a # b et a désignent la même liste
b[0] = 99
print(a)
print(b)
[99, 2, 3]
[99, 2, 3]
On dit que a et b sont des alias : deux noms pour le même objet. C’est un piège fréquent.
Pour créer une vraie copie indépendante, on utilise l’une des méthodes suivantes :
a = [1, 2, 3]
b = a.copy() # méthode 1 : la méthode copy()
c = list(a) # méthode 2 : le constructeur list()
d = a[:] # méthode 3 : le slicing complet
b[0] = 99
print(a) # a n'est pas modifié
print(b) # seul b est modifié
[1, 2, 3]
[99, 2, 3]
À retenir : = crée un alias, pas une copie. Pour copier une liste, il faut utiliser copy(), list() ou [:].
Effets de bord : listes et fonctions
Quand on passe une liste à une fonction, la fonction reçoit un alias de la liste, pas une copie. Si elle modifie la liste (ajout, suppression, affectation L[i] = ...), la modification est visible par l’appelant après l’appel : on dit que la fonction a un effet de bord.
def ajouter_zero(L):
L.append(0)
notes = [12, 15]
ajouter_zero(notes)
print(notes)
[12, 15, 0]
Au contraire, réaffecter le paramètre ne touche pas la liste de l’appelant : L = [] fait pointer le nom local L vers une nouvelle liste, et notes continue de désigner l’ancienne.
def vider(L):
L = []
notes = [12, 15]
vider(notes)
print(notes)
[12, 15]
Deux styles de fonctions existent, et il faut choisir l’un ou l’autre et l’indiquer dans la docstring :
- une fonction qui modifie en place la liste reçue et ne renvoie rien, comme
L.sort()ouL.append(); - une fonction sans effet de bord qui renvoie une nouvelle liste et laisse son argument intact, comme
sorted(L).
def doubler_en_place(L):
"""Double chaque élément de L. Modifie L, ne renvoie rien."""
for i in range(len(L)):
L[i] = 2 * L[i]
def doubler(L):
"""Renvoie une nouvelle liste dont les éléments sont les doubles de ceux de L. L n'est pas modifiée."""
resultat = []
for x in L:
resultat.append(2 * x)
return resultat
Les effets de bord sont une source classique de bugs : une liste modifiée « à distance » par une fonction appelée ailleurs dans le programme. Quand une fonction doit travailler sur une copie, on la crée explicitement avec L[:] ou list(L).
Construction par compréhension
Prérequis : cette section utilise la boucle
for, présentée dans le chapitre 05 (Boucles). Si vous n’avez pas encore vu les boucles, vous pouvez revenir à cette section plus tard.
La compréhension de liste permet de créer une liste à partir d’une expression et d’un itérable, en une seule ligne. La syntaxe est la suivante : [expression for variable in itérable].
# Les carrés des nombres de 0 à 9
carres = [x ** 2 for x in range(10)]
print(carres)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
On peut ajouter une condition de filtrage avec if :
# Les nombres pairs entre 0 et 19
pairs = [x for x in range(20) if x % 2 == 0]
print(pairs)
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
Autre exemple : extraire les initiales d’une liste de prénoms.
prenoms = ["Alice", "Bob", "Charlie", "Diana"]
initiales = [p[0] for p in prenoms]
print(initiales)
['A', 'B', 'C', 'D']
Résumé
| Concept | Syntaxe | Exemple |
|---|---|---|
| Création | [e1, e2, ...] | [15, 12, 18] |
| Accès | L[i] | notes[0] → 15 |
| Longueur | len(L) | len(notes) → 3 |
| Ajout | L.append(x) | notes.append(17) |
| Parcours | for x in L | for n in notes |
| Copie | L.copy() ou L[:] | b = a.copy() |
| Compréhension | [expr for x in L] | [x**2 for x in range(5)] |
| Appartenance | x in L | 15 in notes → True |