Les Listes en Python
Créer une liste
Une liste est une collection ordonnée et modifiable d'éléments. En Python, les listes peuvent contenir des éléments de types différents.
# Liste vide
vide = []
aussi_vide = list()
# Liste de nombres
notes = [15, 12, 18, 9, 14]
# Liste de chaines
fruits = ["pomme", "banane", "cerise"]
# Liste mixte (possible mais rarement utile)
melange = [42, "bonjour", True, 3.14]
# A partir d'un range
cinq_premiers = list(range(5)) # [0, 1, 2, 3, 4]
pairs = list(range(0, 10, 2)) # [0, 2, 4, 6, 8]
Accéder aux éléments
Indexation positive
Les éléments sont indexés à partir de 0 :
fruits = ["pomme", "banane", "cerise", "datte"]
print(fruits[0]) # pomme (premier)
print(fruits[1]) # banane
print(fruits[2]) # cerise
print(fruits[3]) # datte (dernier, index = longueur - 1)
Indexation négative
Les indices négatifs partent de la fin : -1 est le dernier élément, -2 l'avant-dernier, etc.
fruits = ["pomme", "banane", "cerise", "datte"]
print(fruits[-1]) # datte (dernier)
print(fruits[-2]) # cerise (avant-dernier)
print(fruits[-4]) # pomme (premier depuis la fin)
Slicing (découpage)
Le slicing permet d'extraire une sous-liste avec la syntaxe liste[debut:fin:pas]. La borne fin est exclue.
nombres = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(nombres[2:5]) # [2, 3, 4] (indices 2, 3, 4)
print(nombres[:4]) # [0, 1, 2, 3] (du debut a l'index 3)
print(nombres[6:]) # [6, 7, 8, 9] (de l'index 6 a la fin)
print(nombres[::2]) # [0, 2, 4, 6, 8] (un sur deux)
print(nombres[1::2]) # [1, 3, 5, 7, 9] (impairs)
print(nombres[::-1]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] (inverse)
print(nombres[2:8:3]) # [2, 5] (de 2 a 7, pas de 3)
Modifier une liste
Les listes sont mutables : on peut changer leurs elements directement.
notes = [12, 15, 9, 18, 11]
# Modifier un élément
notes[2] = 14
print(notes) # [12, 15, 14, 18, 11]
# Modifier une plage (slice)
notes[1:3] = [17, 16]
print(notes) # [12, 17, 16, 18, 11]
Méthodes des listes
Python fournit de nombreuses méthodes pour manipuler les listes.
Ajouter des éléments
fruits = ["pomme", "banane"]
fruits.append("cerise") # ajoute a la fin
print(fruits) # ["pomme", "banane", "cerise"]
fruits.insert(1, "abricot") # insere a l'index 1
print(fruits) # ["pomme", "abricot", "banane", "cerise"]
fruits.extend(["datte", "figue"]) # ajoute plusieurs éléments
print(fruits) # ["pomme", "abricot", "banane", "cerise", "datte", "figue"]
Supprimer des éléments
fruits = ["pomme", "banane", "cerise", "banane"]
fruits.remove("banane") # supprime la PREMIERE occurrence
print(fruits) # ["pomme", "cerise", "banane"]
dernier = fruits.pop() # supprime et retourne le dernier
print(dernier) # "banane"
print(fruits) # ["pomme", "cerise"]
deuxieme = fruits.pop(0) # supprime et retourne l'élément à l'index 0
print(deuxieme) # "pomme"
fruits.clear() # vide completement la liste
print(fruits) # []
Trier et inverser
nombres = [3, 1, 4, 1, 5, 9, 2, 6]
nombres.sort() # tri en place (modifie la liste)
print(nombres) # [1, 1, 2, 3, 4, 5, 6, 9]
nombres.sort(reverse=True) # tri inverse
print(nombres) # [9, 6, 5, 4, 3, 2, 1, 1]
nombres.reverse() # inverse l'ordre en place
print(nombres) # [1, 1, 2, 3, 4, 5, 6, 9]
Rechercher
fruits = ["pomme", "banane", "cerise", "banane"]
idx = fruits.index("banane") # indice de la PREMIERE occurrence
print(idx) # 1
nb = fruits.count("banane") # nombre d'occurrences
print(nb) # 2
Copier
original = [1, 2, 3]
copie = original.copy() # copie superficielle
copie.append(4)
print(original) # [1, 2, 3] (non modifié)
print(copie) # [1, 2, 3, 4]
Fonctions built-in pour les listes
notes = [12, 15, 9, 18, 11, 14]
print(len(notes)) # 6 - nombre d'él éments
print(min(notes)) # 9 - valeur minimale
print(max(notes)) # 18 - valeur maximale
print(sum(notes)) # 79 - somme des éléments
moyenne = sum(notes) / len(notes)
print(round(moyenne, 2)) # 13.17
Listes en compréhension
Les listes en compréhension permettent de créer des listes de manière concise et lisible.
# Syntaxe : [expression for element in iterable if condition]
# Sans condition
carres = [x ** 2 for x in range(6)]
print(carres) # [0, 1, 4, 9, 16, 25]
# Avec condition
pairs = [x for x in range(10) if x % 2 == 0]
print(pairs) # [0, 2, 4, 6, 8]
# Transformation de chaines
noms = ["alice", "bob", "claire"]
majuscules = [nom.upper() for nom in noms]
print(majuscules) # ["ALICE", "BOB", "CLAIRE"]
# Filtrer et transformer
notes = [12, 15, 9, 18, 11, 14]
bonnes_notes = [n for n in notes if n >= 12]
print(bonnes_notes) # [12, 15, 18, 14]
Comparaison avec la boucle équivalente :
# Avec boucle
carres = []
for x in range(6):
carres.append(x ** 2)
# Avec comprehension (equivalent, plus concis)
carres = [x ** 2 for x in range(6)]
Listes imbriquées (matrices 2D)
Une liste peut contenir d'autres listes, ce qui permet de représenter des matrices ou des tableaux 2D :
matrice = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# Acces : matrice[ligne][colonne]
print(matrice[0][0]) # 1 (ligne 0, colonne 0)
print(matrice[1][2]) # 6 (ligne 1, colonne 2)
print(matrice[2][1]) # 8 (ligne 2, colonne 1)
# Parcourir une matrice
for ligne in matrice:
for valeur in ligne:
print(valeur, end=" ")
print()
# 1 2 3
# 4 5 6
# 7 8 9
Décomposition (unpacking)
On peut "décompacter" une liste en plusieurs variables :
coordonnees = [48.8566, 2.3522]
latitude, longitude = coordonnees
print(latitude) # 48.8566
print(longitude) # 2.3522
# Unpacking avec *rest
nombres = [1, 2, 3, 4, 5]
premier, *reste = nombres
print(premier) # 1
print(reste) # [2, 3, 4, 5]
*debut, dernier = nombres
print(debut) # [1, 2, 3, 4]
print(dernier) # 5
premier, *milieu, dernier = nombres
print(premier) # 1
print(milieu) # [2, 3, 4]
print(dernier) # 5
Vérifier l'appartenance
fruits = ["pomme", "banane", "cerise"]
print("banane" in fruits) # True
print("mangue" in fruits) # False
print("mangue" not in fruits) # True
# Utilisation dans un if
if "cerise" in fruits:
print("On a des cerises !")
Copie superficielle vs copie profonde
Attention à la copie des listes imbriquées :
import copy
# Assignation : pas une copie !
a = [1, 2, 3]
b = a # b pointe vers le MÊME objet
b.append(4)
print(a) # [1, 2, 3, 4] (a aussi modifié !)
# Copie superficielle : OK pour listes simples
a = [1, 2, 3]
b = a.copy() # ou b = a[:] ou b = list(a)
b.append(4)
print(a) # [1, 2, 3] (a non modifié)
# Copie superficielle INSUFFISANTE pour listes imbriquées
a = [[1, 2], [3, 4]]
b = a.copy()
b[0].append(99)
print(a) # [[1, 2, 99], [3, 4]] (a aussi modifié !)
# Copie profonde : indépendance totale
a = [[1, 2], [3, 4]]
b = copy.deepcopy(a)
b[0].append(99)
print(a) # [[1, 2], [3, 4]] (a non modifié)
Trier avec une clé personnalisée
sorted() retourne une nouvelle liste triée sans modifier l'originale. Le paramètre key accepte une fonction :
etudiants = [("Alice", 17), ("Bob", 15), ("Claire", 19), ("David", 16)]
# Trier par note (index 1)
par_note = sorted(etudiants, key=lambda e: e[1])
print(par_note)
# [('Bob', 15), ('David', 16), ('Alice', 17), ('Claire', 19)]
# Trier par nom (index 0)
par_nom = sorted(etudiants, key=lambda e: e[0])
print(par_nom)
# [('Alice', 17), ('Bob', 15), ('Claire', 19), ('David', 16)]
# Trier des chaines sans tenir compte de la casse
mots = ["Banane", "abricot", "Cerise", "datte"]
tries = sorted(mots, key=lambda m: m.lower())
print(tries) # ['abricot', 'Banane', 'Cerise', 'datte']
Exercices pratiques
Exercice 1 : Créer une liste et accéder aux éléments
Utilisez liste[-1] plutôt que liste[len(liste)-1] pour accéder au dernier élément. C'est plus lisible et moins sujet aux erreurs. De même, liste[-2] pour l'avant-dernier est idiomatique en Python.
Exercice 2 : Modifier une liste avec append et pop
pop(0) sur une liste est lent (O(n)) car Python doit décaler tous les éléments. Si vous utilisez fréquemment des ajouts/suppressions en début de liste, utilisez collections.deque qui est optimisé pour ça (O(1)).
Exercice 3 : Slicing
Rappelez-vous que liste[debut:fin] inclut debut mais exclut fin. Pour copier une liste entière, liste[:] est un raccourci pratique. Le slice [::-1] est la façon pythonique d'inverser une liste (ou une chaîne).
Exercice 4 : Liste en compréhension (carrés)
Les listes en compréhension sont excellentes pour des transformations simples. Si votre compréhension devient trop longue ou complexe (plus d'une condition, plusieurs boucles imbriquées), préférez une boucle for classique pour la lisibilité. La règle : si ça ne tient pas sur une ligne claire, utilisez une boucle.
Exercice 5 : Trier une liste
Utilisez sort() (méthode, modifie en place) quand vous n'avez plus besoin de l'ordre original. Utilisez sorted() (fonction built-in) quand vous voulez conserver la liste originale ou trier un itérable quelconque. sorted() retourne toujours une nouvelle liste.
Exercice 6 : Trouver un élément avec index()
index() lève une ValueError si l'élément n'est pas trouvé. Avant d'appeler index(), vérifiez d'abord la présence avec if valeur in liste. Alternativement, utilisez un bloc try/except ValueError pour gérer le cas où l'élément est absent.