Aller au contenu principal

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

Bonne pratique - Index négatif

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

Bonne pratique - pop(0) vs deque

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

Bonne pratique - 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)

Bonne pratique - Compréhensions lisibles

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

Bonne pratique - sort() vs sorted()

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()

Bonne pratique - Vérifier avant 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.


Quiz de révision


Quel est l'index du dernier élément d'une liste de 5 éléments ?


Que retourne liste[2:5] si liste = [0, 1, 2, 3, 4, 5, 6] ?


Quelle méthode supprime ET retourne un élément d'une liste ?


Que fait b = a si a est une liste ?


Quelle est la syntaxe correcte d'une liste en compréhension pour les nombres pairs de 0 à 9 ?


📌 Une solution