Python & AI Tutorials Logo
Programmation Python

14. Listes : collections ordonnées d’éléments

Jusqu’à présent dans ce livre, nous avons travaillé avec des éléments de données individuels : des nombres simples, des chaînes, et des valeurs booléennes. Mais les programmes réels ont souvent besoin de travailler avec des collections d’éléments liés — une liste de noms d’élèves, une série de relevés de température, une collection de prix de produits, ou une séquence de commandes utilisateur. La liste de Python est l’outil fondamental pour stocker et manipuler des collections ordonnées de données.

Une liste est une séquence qui peut contenir plusieurs éléments dans un ordre spécifique. Contrairement aux chaînes (qui ne peuvent contenir que des caractères), les listes peuvent contenir n’importe quel type de données : nombres, chaînes, booléens, ou même d’autres listes. Les listes sont aussi mutables, ce qui signifie que vous pouvez changer leur contenu après leur création — ajouter des éléments, en retirer, ou modifier ceux qui existent.

Dans ce chapitre, nous allons explorer comment créer des listes, accéder à leurs éléments, les modifier, et les utiliser pour résoudre des problèmes de programmation pratiques. À la fin, vous comprendrez pourquoi les listes sont l’une des structures de données les plus puissantes et les plus fréquemment utilisées en Python.

14.1) Créer des listes et accéder aux éléments

14.1.1) Créer des listes avec des crochets

La manière la plus courante de créer une liste consiste à placer des éléments entre crochets [], avec des éléments séparés par des virgules. Voici un exemple simple :

python
# Une liste de noms d’élèves
students = ["Alice", "Bob", "Charlie", "Diana"]
print(students)  # Output: ['Alice', 'Bob', 'Charlie', 'Diana']

Remarquez comment Python affiche la liste : il montre les crochets et met des guillemets autour de chaque chaîne. C’est la représentation de la liste — la manière dont Python vous montre ce qu’il y a dedans.

Les listes peuvent contenir n’importe quel type de données. Voici une liste de notes de test :

python
# Une liste de notes entières
scores = [85, 92, 78, 95, 88]
print(scores)  # Output: [85, 92, 78, 95, 88]

Vous pouvez même mélanger différents types dans la même liste, bien que ce soit moins courant en pratique :

python
# Une liste de types mixtes (moins courant mais valide)
mixed_data = ["Alice", 25, True, 3.14]
print(mixed_data)  # Output: ['Alice', 25, True, 3.14]

Une liste vide ne contient aucun élément et se crée avec seulement les crochets :

python
# Une liste vide
empty = []
print(empty)  # Output: []
print(len(empty))  # Output: 0

La fonction len(), que nous avons utilisée avec les chaînes, fonctionne aussi avec les listes — elle renvoie le nombre d’éléments dans la liste.

14.1.2) Comprendre l’ordre des listes et les positions

Les listes conservent l’ordre dans lequel vous ajoutez des éléments. Le premier élément que vous mettez reste le premier, le second reste le second, et ainsi de suite. Cet ordre est crucial parce qu’il vous permet d’accéder à des éléments spécifiques par leur position (également appelée leur index).

Python utilise un indexage à partir de zéro : le premier élément est à la position 0, le second à la position 1, et ainsi de suite. Cela peut sembler inhabituel au début, mais c’est une convention utilisée par de nombreux langages de programmation.

Liste : ['Alice', 'Bob', 'Charlie', 'Diana']

Index 0 : 'Alice'

Index 1 : 'Bob'

Index 2 : 'Charlie'

Index 3 : 'Diana'

Voyons comment cela fonctionne en pratique :

python
students = ["Alice", "Bob", "Charlie", "Diana"]
 
# Accéder au premier élève (index 0)
first_student = students[0]
print(first_student)  # Output: Alice
 
# Accéder au troisième élève (index 2)
third_student = students[2]
print(third_student)  # Output: Charlie

Remarquez que pour obtenir le troisième élève, nous utilisons l’index 2, et non 3. C’est parce que le comptage commence à 0.

14.1.3) Accéder aux éléments avec des indices positifs

Pour accéder à un élément de liste, écrivez le nom de la liste suivi de l’index entre crochets : list_name[index]. L’index doit être un entier dans la plage valide (0 à len(list) - 1).

Voici un exemple pratique avec des prix de produits :

python
# Prix des produits en dollars
prices = [19.99, 24.50, 15.75, 32.00, 8.99]
 
# Accéder à des prix spécifiques
first_price = prices[0]
last_index = len(prices) - 1  # Calculer le dernier index valide
last_price = prices[last_index]
 
print(f"First product costs: ${first_price}")  # Output: First product costs: $19.99
print(f"Last product costs: ${last_price}")    # Output: Last product costs: $8.99

Pourquoi utilisons-nous len(prices) - 1 pour le dernier index ? Parce que si une liste a 5 éléments, les indices sont 0, 1, 2, 3, 4 — le dernier index valide est toujours inférieur de 1 à la longueur.

Vous pouvez aussi utiliser des indices dans des expressions et des calculs :

python
scores = [85, 92, 78, 95, 88]
 
# Calculer la moyenne des trois premières notes
first_three_average = (scores[0] + scores[1] + scores[2]) / 3
print(f"Average of first three: {first_three_average}")  # Output: Average of first three: 85.0

14.1.4) Indices négatifs : compter depuis la fin

Python fournit une fonctionnalité pratique : les indices négatifs vous permettent d’accéder aux éléments depuis la fin de la liste. L’index -1 correspond au dernier élément, -2 à l’avant-dernier, et ainsi de suite.

python
students = ["Alice", "Bob", "Charlie", "Diana"]
 
# Accéder depuis la fin
last_student = students[-1]
second_to_last = students[-2]
 
print(last_student)      # Output: Diana
print(second_to_last)    # Output: Charlie

C’est particulièrement utile lorsque vous voulez le dernier élément mais ne voulez pas calculer len(list) - 1 :

python
prices = [19.99, 24.50, 15.75, 32.00, 8.99]
 
# Ces deux approches sont équivalentes
last_price_method1 = prices[len(prices) - 1]
last_price_method2 = prices[-1]
 
print(last_price_method1)  # Output: 8.99
print(last_price_method2)  # Output: 8.99

Voici comment les indices positifs et négatifs correspondent aux mêmes éléments :

Liste : ['Alice', 'Bob', 'Charlie', 'Diana']

Positifs : 0, 1, 2, 3

Négatifs : -4, -3, -2, -1

Les deux renvoient aux mêmes éléments

14.1.5) Que se passe-t-il avec des indices invalides

Si vous essayez d’accéder à un index qui n’existe pas, Python lève une IndexError :

python
students = ["Alice", "Bob", "Charlie"]
 
# AVERTISSEMENT : cette liste a les indices 0, 1, 2 (ou -3, -2, -1) - pour démonstration uniquement
# Essayer d’accéder à l’index 3 provoque une erreur
# PROBLÈME : l’index 3 n’existe pas dans une liste de 3 éléments
# print(students[3])  # IndexError: list index out of range

Cette erreur est la façon dont Python vous indique que vous avez demandé un élément qui n’est pas présent.

14.2) Indexation et slicing des listes

14.2.1) Comprendre les bases du slicing des listes

Tout comme nous pouvons découper les chaînes (comme nous l’avons appris au chapitre 5), nous pouvons découper les listes pour en extraire des portions. Un slice crée une nouvelle liste contenant un sous-ensemble des éléments de la liste d’origine. La syntaxe est list[start:stop], où start est l’index où le slice commence (inclus) et stop est là où il se termine (exclu).

python
numbers = [10, 20, 30, 40, 50, 60, 70]
 
# Obtenir les éléments de l’index 1 jusqu’à (sans inclure) l’index 4
subset = numbers[1:4]
print(subset)  # Output: [20, 30, 40]

Le slice [1:4] inclut les indices 1, 2 et 3, mais s’arrête avant l’index 4. Cette règle « stop est exclusif » est la même qu’avec le slicing des chaînes.

Voyons un exemple pratique avec des noms d’élèves :

python
students = ["Alice", "Bob", "Charlie", "Diana", "Eve", "Frank"]
 
# Obtenir les trois premiers élèves
first_three = students[0:3]
print(first_three)  # Output: ['Alice', 'Bob', 'Charlie']
 
# Obtenir les élèves de l’index 2 à 4
middle_group = students[2:5]
print(middle_group)  # Output: ['Charlie', 'Diana', 'Eve']

14.2.2) Omettre start ou stop dans les slices

Vous pouvez omettre l’index de début pour découper depuis le début, ou omettre l’index de fin pour découper jusqu’à la fin :

python
scores = [85, 92, 78, 95, 88, 91, 87]
 
# Depuis le début jusqu’à l’index 3
first_few = scores[:3]
print(first_few)  # Output: [85, 92, 78]
 
# De l’index 4 jusqu’à la fin
last_few = scores[4:]
print(last_few)  # Output: [88, 91, 87]
 
# La liste entière (du début à la fin)
all_scores = scores[:]
print(all_scores)  # Output: [85, 92, 78, 95, 88, 91, 87]

Le slice [:] crée une copie de la liste entière. C’est utile lorsque vous voulez travailler sur un doublon sans modifier l’original — nous explorerons cela davantage dans la section 14.6.

14.2.3) Utiliser des indices négatifs dans les slices

Les indices négatifs fonctionnent dans les slices de la même manière que pour l’accès à un seul élément. C’est particulièrement utile pour obtenir des éléments depuis la fin :

python
students = ["Alice", "Bob", "Charlie", "Diana", "Eve", "Frank"]
 
# Obtenir les trois derniers élèves
last_three = students[-3:]
print(last_three)  # Output: ['Diana', 'Eve', 'Frank']
 
# Obtenir tous sauf les deux derniers élèves
all_but_last_two = students[:-2]
print(all_but_last_two)  # Output: ['Alice', 'Bob', 'Charlie', 'Diana']
 
# Obtenir du troisième depuis la fin jusqu’au deuxième depuis la fin
middle_from_end = students[-3:-1]
print(middle_from_end)  # Output: ['Diana', 'Eve']

14.2.4) Slicing avec une valeur de pas

Vous pouvez ajouter un troisième paramètre pour contrôler le pas (combien d’indices sauter entre les éléments). La syntaxe complète est list[start:stop:step] :

python
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 
# Un nombre sur deux à partir de l’index 0
evens = numbers[0:10:2]
print(evens)  # Output: [0, 2, 4, 6, 8]
 
# Un nombre sur trois à partir de l’index 1
every_third = numbers[1:10:3]
print(every_third)  # Output: [1, 4, 7]

Vous pouvez aussi utiliser un pas négatif pour inverser la liste :

python
numbers = [1, 2, 3, 4, 5]
 
# Inverser la liste
reversed_numbers = numbers[::-1]
print(reversed_numbers)  # Output: [5, 4, 3, 2, 1]

Le slice [::-1] signifie « commencer à la fin, aller au début, en reculant de 1 ». C’est un idiome Python courant pour inverser des séquences.

14.2.5) Les slices ne provoquent jamais d’IndexError

Contrairement à l’accès à un seul élément, le slicing est très tolérant. Si vous spécifiez des indices hors de la plage de la liste, Python les ajuste simplement pour qu’ils correspondent :

python
numbers = [10, 20, 30, 40, 50]
 
# Demander plus que ce qui existe
extended_slice = numbers[2:100]
print(extended_slice)  # Output: [30, 40, 50]
 
# Commencer au-delà de la fin
empty_slice = numbers[10:20]
print(empty_slice)  # Output: []

Ce comportement est utile car cela signifie que vous n’avez pas à vous soucier de limites exactes lors d’un slicing — Python gère les cas limites avec élégance.

14.3) Modifier les listes et méthodes courantes des listes

14.3.1) Les listes sont mutables : changer des éléments

Contrairement aux chaînes, qui sont immuables, les listes sont mutables — vous pouvez changer leur contenu après leur création. Vous pouvez modifier des éléments individuels en affectant de nouvelles valeurs à des indices spécifiques :

python
# Commencer avec une liste de prix
prices = [19.99, 24.50, 15.75, 32.00]
print(prices)  # Output: [19.99, 24.5, 15.75, 32.0]
 
# Mettre à jour le deuxième prix (index 1)
prices[1] = 22.99
print(prices)  # Output: [19.99, 22.99, 15.75, 32.0]
 
# Mettre à jour le dernier prix avec un indexage négatif
prices[-1] = 29.99
print(prices)  # Output: [19.99, 22.99, 15.75, 29.99]

Cette mutabilité est puissante — cela signifie que vous pouvez mettre à jour des données sur place sans créer de nouvelles listes. Cependant, cela signifie aussi que vous devez faire attention aux changements involontaires, ce dont nous parlerons dans la section 14.6.

14.3.2) Ajouter des éléments avec append()

La méthode append() ajoute un seul élément à la fin d’une liste. C’est l’une des opérations sur les listes les plus fréquemment utilisées :

python
# Commencer avec un panier d’achat vide
cart = []
print(cart)  # Output: []
 
# Ajouter des éléments un par un
cart.append("Milk")
print(cart)  # Output: ['Milk']
 
cart.append("Bread")
print(cart)  # Output: ['Milk', 'Bread']
 
cart.append("Eggs")
print(cart)  # Output: ['Milk', 'Bread', 'Eggs']

Remarquez que append() modifie la liste sur place — elle ne renvoie pas une nouvelle liste. La méthode renvoie None, vous n’avez donc pas besoin d’affecter son résultat :

python
scores = [85, 92, 78]
result = scores.append(95)
 
print(scores)   # Output: [85, 92, 78, 95]
print(result)   # Output: None

14.3.3) Insérer des éléments à des positions spécifiques avec insert()

Alors que append() ajoute toujours à la fin, insert() vous permet d’ajouter un élément à n’importe quelle position. La syntaxe est list.insert(index, item) :

python
students = ["Alice", "Charlie", "Diana"]
print(students)  # Output: ['Alice', 'Charlie', 'Diana']
 
# Insérer "Bob" à l’index 1 (entre Alice et Charlie)
students.insert(1, "Bob")
print(students)  # Output: ['Alice', 'Bob', 'Charlie', 'Diana']

Lorsque vous insérez à un index, l’élément actuellement à cette position (et tous ceux qui le suivent) se décalent vers la droite :

python
numbers = [10, 20, 30, 40]
print(numbers)  # Output: [10, 20, 30, 40]
 
# Insérer 25 à l’index 2
numbers.insert(2, 25)
print(numbers)  # Output: [10, 20, 25, 30, 40]

Vous pouvez insérer au début en utilisant l’index 0 :

python
priorities = ["Medium", "Low"]
priorities.insert(0, "High")
print(priorities)  # Output: ['High', 'Medium', 'Low']

Si vous spécifiez un index au-delà de la longueur de la liste, insert() ajoute simplement l’élément à la fin (comme append()) :

python
items = [1, 2, 3]
items.insert(100, 4)
print(items)  # Output: [1, 2, 3, 4]

14.3.4) Supprimer des éléments avec remove()

La méthode remove() supprime la première occurrence d’une valeur spécifique dans la liste :

python
fruits = ["apple", "banana", "cherry", "banana", "date"]
print(fruits)  # Output: ['apple', 'banana', 'cherry', 'banana', 'date']
 
# Supprimer le premier "banana"
fruits.remove("banana")
print(fruits)  # Output: ['apple', 'cherry', 'banana', 'date']

Remarquez que seul le premier « banana » a été supprimé — le second est toujours là. Si vous essayez de supprimer une valeur qui n’existe pas, Python lève une ValueError :

python
numbers = [10, 20, 30]
# AVERTISSEMENT : tentative de suppression d’une valeur inexistante - pour démonstration uniquement
# PROBLÈME : 40 n’est pas dans la liste
# numbers.remove(40)  # ValueError: list.remove(x): x not in list

Pour éviter cette erreur, vous pouvez vérifier si l’élément existe avant de le supprimer :

python
cart = ["Milk", "Bread", "Eggs"]
item_to_remove = "Butter"
 
if item_to_remove in cart:
    cart.remove(item_to_remove)
    print(f"Removed {item_to_remove}")
else:
    print(f"{item_to_remove} not in cart")
# Output: Butter not in cart

14.3.5) Supprimer et renvoyer des éléments avec pop()

La méthode pop() supprime un élément à un index spécifique et le renvoie. Si vous ne spécifiez pas d’index, elle supprime et renvoie le dernier élément :

python
scores = [85, 92, 78, 95, 88]
 
# Supprimer et récupérer la dernière note
last_score = scores.pop()
print(f"Removed: {last_score}")  # Output: Removed: 88
print(scores)  # Output: [85, 92, 78, 95]
 
# Supprimer et récupérer la note à l’index 1
second_score = scores.pop(1)
print(f"Removed: {second_score}")  # Output: Removed: 92
print(scores)  # Output: [85, 78, 95]

C’est utile lorsque vous devez traiter des éléments d’une liste un par un :

python
tasks = ["Write code", "Test code", "Deploy code"]
 
while len(tasks) > 0:
    current_task = tasks.pop(0)  # Retirer depuis le début
    print(f"Working on: {current_task}")
 
# Output:
# Working on: Write code
# Working on: Test code
# Working on: Deploy code
 
print(tasks)  # Output: []

14.3.6) Étendre des listes avec extend()

La méthode extend() ajoute tous les éléments d’une autre liste (ou de n’importe quel itérable) à la fin de la liste actuelle :

python
primary_colors = ["red", "blue", "yellow"]
secondary_colors = ["green", "orange", "purple"]
 
# Ajouter toutes les couleurs secondaires aux couleurs primaires
primary_colors.extend(secondary_colors)
print(primary_colors)
# Output: ['red', 'blue', 'yellow', 'green', 'orange', 'purple']

C’est différent de append(), qui ajouterait la liste entière comme un seul élément :

python
colors1 = ["red", "blue"]
colors2 = ["green", "orange"]
 
# Utiliser append (ajoute la liste comme un seul élément)
colors1.append(colors2)
print(colors1)  # Output: ['red', 'blue', ['green', 'orange']]
 
# Utiliser extend (ajoute chaque élément individuellement)
colors3 = ["red", "blue"]
colors3.extend(colors2)
print(colors3)  # Output: ['red', 'blue', 'green', 'orange']

14.3.7) Trier des listes avec sort() et sorted()

Python fournit deux façons de trier des listes. La méthode sort() trie la liste sur place (en modifiant l’original) :

python
scores = [78, 95, 85, 92, 88]
scores.sort()
print(scores)  # Output: [78, 85, 88, 92, 95]

Pour trier dans l’ordre décroissant, utilisez le paramètre reverse :

python
scores = [78, 95, 85, 92, 88]
scores.sort(reverse=True)
print(scores)  # Output: [95, 92, 88, 85, 78]

La fonction sorted() (que nous explorerons davantage au chapitre 38) crée une nouvelle liste triée sans modifier l’original :

python
original = [78, 95, 85, 92, 88]
sorted_scores = sorted(original)
 
print(original)       # Output: [78, 95, 85, 92, 88]
print(sorted_scores)  # Output: [78, 85, 88, 92, 95]

Le tri fonctionne aussi avec des chaînes, en utilisant l’ordre alphabétique :

python
names = ["Charlie", "Alice", "Diana", "Bob"]
names.sort()
print(names)  # Output: ['Alice', 'Bob', 'Charlie', 'Diana']

14.3.8) Inverser des listes avec reverse()

La méthode reverse() inverse la liste sur place :

python
numbers = [1, 2, 3, 4, 5]
numbers.reverse()
print(numbers)  # Output: [5, 4, 3, 2, 1]

C’est différent d’un tri en ordre inverse — reverse() se contente de retourner l’ordre actuel, quel qu’il soit :

python
mixed = [3, 1, 4, 1, 5]
mixed.reverse()
print(mixed)  # Output: [5, 1, 4, 1, 3]

Souvenez-vous que vous pouvez aussi inverser une liste en utilisant le slicing : list[::-1]. La différence est que le slicing crée une nouvelle liste, tandis que reverse() modifie l’original.

14.3.9) Trouver des éléments avec index() et count()

La méthode index() renvoie la position de la première occurrence d’une valeur :

python
students = ["Alice", "Bob", "Charlie", "Diana", "Bob"]
 
# Trouver où se trouve "Charlie"
position = students.index("Charlie")
print(f"Charlie is at index {position}")  # Output: Charlie is at index 2
 
# Trouver le premier "Bob"
bob_position = students.index("Bob")
print(f"Bob is at index {bob_position}")  # Output: Bob is at index 1

Si la valeur n’existe pas, index() lève une ValueError :

python
students = ["Alice", "Bob", "Charlie"]
# AVERTISSEMENT : tentative de recherche d’une valeur inexistante - pour démonstration uniquement
# PROBLÈME : 'Eve' n’est pas dans la liste
# position = students.index("Eve")  # ValueError: 'Eve' is not in list

La méthode count() renvoie le nombre de fois où une valeur apparaît :

python
numbers = [1, 2, 3, 2, 4, 2, 5]
twos = numbers.count(2)
print(f"The number 2 appears {twos} times")  # Output: The number 2 appears 3 times
 
# count peut renvoyer 0 si l’élément n’existe pas
sixes = numbers.count(6)
print(f"The number 6 appears {sixes} times")  # Output: The number 6 appears 0 times

14.3.10) Vider tous les éléments avec clear()

La méthode clear() supprime tous les éléments d’une liste, en la laissant vide :

python
cart = ["Milk", "Bread", "Eggs", "Butter"]
print(cart)  # Output: ['Milk', 'Bread', 'Eggs', 'Butter']
 
cart.clear()
print(cart)  # Output: []
print(len(cart))  # Output: 0

C’est équivalent à affecter une liste vide, mais clear() est plus explicite quant à l’intention.

14.4) Supprimer des éléments de liste avec del

14.4.1) Utiliser del pour supprimer des éléments par index

L’instruction del peut supprimer des éléments de liste à des indices spécifiques :

python
students = ["Alice", "Bob", "Charlie", "Diana", "Eve"]
print(students)  # Output: ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve']
 
# Supprimer l’élément à l’index 2
del students[2]
print(students)  # Output: ['Alice', 'Bob', 'Diana', 'Eve']

Contrairement à pop(), del ne renvoie pas la valeur supprimée — elle la supprime simplement. C’est utile lorsque vous voulez retirer un élément mais n’avez pas besoin de l’utiliser :

python
scores = [85, 92, 78, 95, 88]
 
# Supprimer la note la plus faible (à l’index 2)
del scores[2]
print(scores)  # Output: [85, 92, 95, 88]

Vous pouvez aussi utiliser des indices négatifs avec del :

python
tasks = ["Task 1", "Task 2", "Task 3", "Task 4"]
 
# Supprimer la dernière tâche
del tasks[-1]
print(tasks)  # Output: ['Task 1', 'Task 2', 'Task 3']

14.4.2) Supprimer des slices avec del

L’instruction del peut retirer des slices entiers en une seule fois :

python
numbers = [10, 20, 30, 40, 50, 60, 70]
print(numbers)  # Output: [10, 20, 30, 40, 50, 60, 70]
 
# Supprimer les éléments de l’index 2 à 4 (indices 2, 3, 4)
del numbers[2:5]
print(numbers)  # Output: [10, 20, 60, 70]

C’est particulièrement utile pour supprimer des plages d’éléments :

python
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 
# Retirer les trois premiers éléments
del data[:3]
print(data)  # Output: [4, 5, 6, 7, 8, 9, 10]
 
# Retirer les deux derniers éléments
del data[-2:]
print(data)  # Output: [4, 5, 6, 7, 8]

Vous pouvez même supprimer un élément sur deux en utilisant le slicing avec pas :

python
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 
# Supprimer un élément sur deux
del numbers[::2]
print(numbers)  # Output: [1, 3, 5, 7, 9]

14.4.3) Comparer del, remove(), et pop()

Clarifions quand utiliser chaque méthode de suppression :

python
# Liste exemple pour comparaison
items = ["apple", "banana", "cherry", "date", "elderberry"]
 
# Utiliser remove() quand vous connaissez la VALEUR à supprimer
items_copy1 = items.copy()
items_copy1.remove("cherry")  # Supprime le premier "cherry"
print(items_copy1)  # Output: ['apple', 'banana', 'date', 'elderberry']
 
# Utiliser pop() quand vous connaissez l’INDEX et avez besoin de la valeur
items_copy2 = items.copy()
removed_item = items_copy2.pop(2)  # Supprime et renvoie l’élément à l’index 2
print(f"Removed: {removed_item}")  # Output: Removed: cherry
print(items_copy2)  # Output: ['apple', 'banana', 'date', 'elderberry']
 
# Utiliser del quand vous connaissez l’INDEX mais n’avez pas besoin de la valeur
items_copy3 = items.copy()
del items_copy3[2]  # Retire simplement l’élément à l’index 2
print(items_copy3)  # Output: ['apple', 'banana', 'date', 'elderberry']

14.5) Parcourir des listes avec des boucles for

14.5.1) Parcours de base d’une liste

L’une des opérations les plus courantes avec les listes consiste à traiter chaque élément dans l’ordre. La boucle for (que nous avons apprise au chapitre 12) est parfaite pour cela :

python
students = ["Alice", "Bob", "Charlie", "Diana"]
 
# Traiter chaque élève
for student in students:
    print(f"Hello, {student}!")
 
# Output:
# Hello, Alice!
# Hello, Bob!
# Hello, Charlie!
# Hello, Diana!

La variable de boucle (student dans ce cas) prend chaque valeur de la liste, une à une, dans l’ordre. Vous pouvez donner à cette variable n’importe quel nom significatif :

python
scores = [85, 92, 78, 95, 88]
 
# Calculer et afficher la note (grade) de chaque score
for score in scores:
    if score >= 90:
        grade = "A"
    elif score >= 80:
        grade = "B"
    else:
        grade = "C"
    print(f"Score {score} is a {grade}")
 
# Output:
# Score 85 is a B
# Score 92 is a A
# Score 78 is a C
# Score 95 is a A
# Score 88 is a B

14.5.2) Traiter des éléments correspondants de plusieurs listes

Parfois, vous devez travailler avec des données liées stockées dans des listes séparées. Nous apprendrons la fonction zip() en détail au chapitre 38, mais voici un aperçu rapide de la façon dont elle peut aider à traiter des éléments correspondants :

python
# Nous apprendrons zip() au chapitre 38, mais pour l’instant voici un exemple simple
students = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]
 
# Traiter les paires correspondantes
for student, score in zip(students, scores):
    print(f"{student} scored {score}")
 
# Output:
# Alice scored 85
# Bob scored 92
# Charlie scored 78

La fonction zip() associe des éléments de plusieurs listes, ce qui est utile lorsque vous avez des données liées dans des listes séparées. Nous explorerons cela ainsi que d’autres outils d’itération en profondeur au chapitre 38.

14.6) Copier des listes et éviter les références partagées

14.6.1) Comprendre les références de liste

Lorsque vous affectez une liste à une variable, Python ne crée pas une copie de la liste — il crée une référence vers le même objet liste en mémoire. Cela signifie que plusieurs variables peuvent référencer la même liste :

python
original = [1, 2, 3]
reference = original  # Les deux variables pointent vers la MÊME liste
 
# Modifier via une variable affecte l’autre
reference.append(4)
print(original)   # Output: [1, 2, 3, 4]
print(reference)  # Output: [1, 2, 3, 4]

Ce comportement peut surprendre si vous vous attendez à ce que reference soit une copie indépendante. Voyons pourquoi c’est important :

python
# Scénario : vous voulez suivre les changements dans un panier d’achat
cart = ["Milk", "Bread"]
backup = cart  # Tenter de sauvegarder l’état original
 
# Ajouter plus d’articles
cart.append("Eggs")
cart.append("Butter")
 
# Vérifier la "sauvegarde"
print(backup)  # Output: ['Milk', 'Bread', 'Eggs', 'Butter']

La sauvegarde a changé aussi ! C’est parce que backup et cart sont deux noms pour le même objet liste.

Variable : cart

Objet liste : ⦗'Milk', 'Bread', 'Eggs', 'Butter'⦘

Variable : backup

14.6.2) Créer des copies indépendantes avec le slicing

Pour créer une véritable copie indépendante, utilisez le slicing avec [:] :

python
original = [1, 2, 3]
copy = original[:]  # Crée une NOUVELLE liste avec le même contenu
 
# Modifier la copie n’affecte pas l’original
copy.append(4)
print(original)  # Output: [1, 2, 3]
print(copy)      # Output: [1, 2, 3, 4]

Maintenant, corrigeons notre exemple de panier d’achat :

python
cart = ["Milk", "Bread"]
backup = cart[:]  # Créer une copie indépendante
 
# Ajouter plus d’articles au panier
cart.append("Eggs")
cart.append("Butter")
 
# La sauvegarde reste inchangée
print(cart)    # Output: ['Milk', 'Bread', 'Eggs', 'Butter']
print(backup)  # Output: ['Milk', 'Bread']

14.6.3) Créer des copies avec la méthode copy()

Les listes ont aussi une méthode copy() qui fait la même chose que [:] :

python
original = [10, 20, 30]
copy = original.copy()
 
copy.append(40)
print(original)  # Output: [10, 20, 30]
print(copy)      # Output: [10, 20, 30, 40]

À la fois [:] et copy() créent des copies superficielles, dont nous discuterons ensuite.

14.6.4) La limitation de la copie superficielle

À la fois [:] et copy() créent des copies superficielles. Cela signifie qu’elles copient la structure de la liste, mais si la liste contient d’autres objets mutables (comme d’autres listes), ces objets internes sont toujours partagés :

python
# Une liste contenant des listes
original = [[1, 2], [3, 4], [5, 6]]
copy = original[:]
 
# Modifier la structure de la liste externe est indépendant
copy.append([7, 8])
print(original)  # Output: [[1, 2], [3, 4], [5, 6]]
print(copy)      # Output: [[1, 2], [3, 4], [5, 6], [7, 8]]
 
# Mais modifier une liste interne affecte les deux !
copy[0].append(99)
print(original)  # Output: [[1, 2, 99], [3, 4], [5, 6]]
print(copy)      # Output: [[1, 2, 99], [3, 4], [5, 6], [7, 8]]

Pourquoi cela se produit-il ? Parce que la copie superficielle crée une nouvelle liste externe, mais les listes internes restent des références partagées :

liste externe original

Liste interne : ⦗1, 2, 99⦘

Liste interne : ⦗3, 4⦘

Liste interne : ⦗5, 6⦘

liste externe copy

Liste interne : ⦗7, 8⦘

Pour des structures imbriquées, vous auriez besoin d’une copie profonde, que nous apprendrons lorsque nous explorerons le module copy dans des chapitres ultérieurs. Pour l’instant, sachez que les copies superficielles fonctionnent parfaitement pour des listes d’éléments immuables (nombres, chaînes, tuples), mais demandent de la prudence avec des structures mutables imbriquées.

14.6.5) Quand les références partagées sont utiles

Parfois, vous voulez que plusieurs variables fassent référence à la même liste. C’est utile lorsque vous devez modifier une liste depuis différentes parties de votre code :

python
# Une fonction qui modifie une liste sur place
def add_bonus_points(scores, bonus):
    for i in range(len(scores)):
        scores[i] = scores[i] + bonus
 
# La liste d’origine est modifiée
student_scores = [85, 92, 78]
add_bonus_points(student_scores, 5)
print(student_scores)  # Output: [90, 97, 83]

Cela fonctionne parce que la fonction reçoit une référence vers la liste d’origine, pas une copie. Nous explorerons cela davantage lorsque nous étudierons les fonctions en détail dans la Partie V.

14.7) Utiliser enumerate() lors du parcours des listes

14.7.1) Le besoin d’avoir à la fois l’index et la valeur

Parfois, lors de l’itération sur une liste, vous avez besoin à la fois de l’index et de la valeur. Une approche consiste à utiliser range(len(list)) :

python
students = ["Alice", "Bob", "Charlie", "Diana"]
 
for i in range(len(students)):
    print(f"Student {i}: {students[i]}")
 
# Output:
# Student 0: Alice
# Student 1: Bob
# Student 2: Charlie
# Student 3: Diana

Cela fonctionne, mais ce n’est pas très élégant. Vous devez utiliser students[i] pour accéder à chaque valeur, ce qui est moins lisible que de parcourir directement les valeurs.

14.7.2) Utiliser enumerate() pour un code plus propre

La fonction enumerate() fournit une meilleure solution. Elle renvoie à la fois l’index et la valeur pour chaque élément :

python
students = ["Alice", "Bob", "Charlie", "Diana"]
 
for index, student in enumerate(students):
    print(f"Student {index}: {student}")
 
# Output:
# Student 0: Alice
# Student 1: Bob
# Student 2: Charlie
# Student 3: Diana

La syntaxe for index, value in enumerate(list) dépaquette chaque paire produite par enumerate(). C’est bien plus lisible que d’utiliser range(len()).

14.7.3) Démarrer enumerate() à un nombre différent

Par défaut, enumerate() commence à compter à 0. Vous pouvez spécifier un autre nombre de départ avec le paramètre start :

python
students = ["Alice", "Bob", "Charlie", "Diana"]
 
# Commencer à compter à 1 au lieu de 0
for position, student in enumerate(students, start=1):
    print(f"Position {position}: {student}")
 
# Output:
# Position 1: Alice
# Position 2: Bob
# Position 3: Charlie
# Position 4: Diana

C’est utile lorsque vous voulez afficher une numérotation adaptée aux humains (commençant à 1) plutôt qu’un indexage adapté aux programmeurs (commençant à 0).

Exemples pratiques avec enumerate()

Voici un exemple pratique qui affiche un menu numéroté :

python
menu_items = ["New Game", "Load Game", "Settings", "Quit"]
 
print("Main Menu:")
for number, item in enumerate(menu_items, start=1):
    print(f"{number}. {item}")
 
# Output:
# Main Menu:
# 1. New Game
# 2. Load Game
# 3. Settings
# 4. Quit

14.7.4) Modifier des listes avec enumerate()

Vous pouvez utiliser enumerate() lorsque vous devez modifier des éléments de liste en fonction de leur position :

python
# Ajouter un bonus basé sur la position aux scores
scores = [85, 92, 78, 95, 88]
 
for index, score in enumerate(scores):
    # Le premier élève reçoit 5 points de bonus, le deuxième reçoit 4, etc.
    bonus = 5 - index
    if bonus > 0:
        scores[index] = score + bonus
 
print(scores)  # Output: [90, 96, 81, 97, 89]

14.8) Modèles courants avec les listes : recherche, filtrage et agrégation de données

14.8.1) Rechercher des éléments dans des listes

L’une des tâches les plus courantes consiste à vérifier si une liste contient un élément spécifique. L’opérateur in (que nous avons appris au chapitre 7) rend cela simple :

python
students = ["Alice", "Bob", "Charlie", "Diana"]
 
# Vérifier si un élève est dans la liste
if "Charlie" in students:
    print("Charlie is enrolled")  # Output: Charlie is enrolled
 
if "Eve" not in students:
    print("Eve is not enrolled")  # Output: Eve is not enrolled

Pour trouver la position d’un élément, utilisez la méthode index() (couverte dans la section 14.3.9), mais rappelez-vous de vérifier d’abord que l’élément existe :

python
scores = [85, 92, 78, 95, 88]
target_score = 95
 
if target_score in scores:
    position = scores.index(target_score)
    print(f"Score {target_score} found at index {position}")
    # Output: Score 95 found at index 3
else:
    print(f"Score {target_score} not found")

14.8.2) Trouver les valeurs maximale et minimale

Les fonctions intégrées de Python max() et min() fonctionnent avec les listes :

python
scores = [85, 92, 78, 95, 88, 91, 76]
 
highest_score = max(scores)
lowest_score = min(scores)
 
print(f"Highest score: {highest_score}")  # Output: Highest score: 95
print(f"Lowest score: {lowest_score}")    # Output: Lowest score: 76

14.8.3) Calculer des agrégats : somme, moyenne et nombre

Calculer des totaux et des moyennes est une opération fondamentale sur les listes :

python
scores = [85, 92, 78, 95, 88, 91, 76, 89]
 
# Calculer le total et la moyenne
total = sum(scores)
count = len(scores)
average = total / count
 
print(f"Total: {total}")        # Output: Total: 694
print(f"Count: {count}")        # Output: Count: 8
print(f"Average: {average:.2f}")  # Output: Average: 86.75

Voici un exemple pratique qui calcule le total d’un panier :

python
cart_items = ["Milk", "Bread", "Eggs", "Butter", "Cheese"]
prices = [3.99, 2.49, 4.99, 5.49, 6.99]
 
# Calculer le coût total
total_cost = sum(prices)
item_count = len(cart_items)
 
print(f"Items in cart: {item_count}")
print(f"Total cost: ${total_cost:.2f}")
 
# Output:
# Items in cart: 5
# Total cost: $23.95

14.9) Mutabilité des listes et truthiness dans les conditions

14.9.1) Comprendre la mutabilité des listes en pratique

Nous avons vu tout au long de ce chapitre que les listes sont mutables — elles peuvent être modifiées après leur création. Cette mutabilité est ce qui rend les listes si puissantes pour stocker et manipuler des collections de données. Consolidons notre compréhension avec un exemple complet :

python
# Commencer avec une liste de tâches vide
tasks = []
print(f"Initial tasks: {tasks}")  # Output: Initial tasks: []
 
# Ajouter des tâches
tasks.append("Write code")
tasks.append("Test code")
tasks.append("Deploy code")
print(f"After adding: {tasks}")
# Output: After adding: ['Write code', 'Test code', 'Deploy code']
 
# Insérer une tâche urgente au début
tasks.insert(0, "Review requirements")
print(f"After inserting: {tasks}")
# Output: After inserting: ['Review requirements', 'Write code', 'Test code', 'Deploy code']
 
# Terminer et supprimer la première tâche
completed = tasks.pop(0)
print(f"Completed: {completed}")  # Output: Completed: Review requirements
print(f"Remaining: {tasks}")
# Output: Remaining: ['Write code', 'Test code', 'Deploy code']
 
# Modifier une tâche
tasks[1] = "Test code thoroughly"
print(f"After modifying: {tasks}")
# Output: After modifying: ['Write code', 'Test code thoroughly', 'Deploy code']

14.9.2) Mutabilité vs immutabilité : listes vs chaînes

Il est important de comprendre la différence entre les listes mutables et les chaînes immuables. Avec les chaînes, les opérations créent de nouvelles chaînes plutôt que de modifier l’originale :

python
# Les chaînes sont immuables
text = "hello"
text.upper()  # Crée une nouvelle chaîne, ne change pas l’original
print(text)  # Output: hello (unchanged)
 
# Pour "changer" une chaîne, vous devez réaffecter
text = text.upper()
print(text)  # Output: HELLO
 
# Les listes sont mutables
numbers = [1, 2, 3]
numbers.append(4)  # Modifie la liste sur place
print(numbers)  # Output: [1, 2, 3, 4] (changed)

Cette différence affecte la façon dont vous travaillez avec ces types :

python
# Les opérations sur les chaînes nécessitent une réaffectation
name = "alice"
name = name.capitalize()  # Il faut réaffecter pour voir le changement
print(name)  # Output: Alice
 
# Les opérations sur les listes modifient sur place
scores = [85, 92, 78]
scores.append(95)  # Pas besoin de réaffectation
print(scores)  # Output: [85, 92, 78, 95]

14.9.3) Utiliser des listes dans des contextes booléens

Les listes ont une valeur de vérité : une liste vide est considérée comme False, et toute liste non vide est considérée comme True. C’est utile dans les instructions conditionnelles :

python
# Une liste vide est falsy
empty_cart = []
if empty_cart:
    print("Cart has items")
else:
    print("Cart is empty")  # Output: Cart is empty
 
# Une liste non vide est truthy
cart_with_items = ["Milk", "Bread"]
if cart_with_items:
    print("Cart has items")  # Output: Cart has items

Ce modèle est couramment utilisé pour vérifier si une liste contient des éléments avant de la traiter :

python
students = ["Alice", "Bob", "Charlie"]
 
if students:
    print(f"We have {len(students)} students")
    for student in students:
        print(f"  - {student}")
else:
    print("No students enrolled")
 
# Output:
# We have 3 students
#   - Alice
#   - Bob
#   - Charlie

14.9.4) Modèle pratique : traiter jusqu’à ce que ce soit vide

La valeur de vérité des listes permet un modèle utile pour traiter des éléments jusqu’à ce qu’une liste soit vide :

python
# Traiter des tâches jusqu’à ce qu’il n’en reste plus
tasks = ["Task 1", "Task 2", "Task 3"]
 
while tasks:  # Continuer tant que la liste n’est pas vide
    current_task = tasks.pop(0)
    print(f"Processing: {current_task}")
 
print("All tasks completed!")
 
# Output:
# Processing: Task 1
# Processing: Task 2
# Processing: Task 3
# All tasks completed!

14.9.5) Vérifier les listes vides : explicite vs implicite

Il y a deux façons de vérifier si une liste est vide :

python
items = []
 
# Vérification implicite (Pythonic)
if not items:
    print("List is empty")  # Output: List is empty
 
# Vérification explicite (également valide)
if len(items) == 0:
    print("List is empty")  # Output: List is empty

La vérification implicite (if not items:) est généralement préférée en Python car elle est plus concise et fonctionne avec tout type de collection. Cependant, les deux approches sont correctes et vous verrez les deux dans du code réel.

14.9.6) Mutabilité et comportement des fonctions

Lorsque vous passez une liste à une fonction (que nous explorerons en détail dans la Partie V), la fonction reçoit une référence vers le même objet liste. Cela signifie que la fonction peut modifier la liste originale :

python
def add_item(shopping_list, item):
    shopping_list.append(item)
    print(f"Added {item}")
 
# La liste originale est modifiée
cart = ["Milk", "Bread"]
print(f"Before: {cart}")  # Output: Before: ['Milk', 'Bread']
 
add_item(cart, "Eggs")     # Output: Added Eggs
print(f"After: {cart}")    # Output: After: ['Milk', 'Bread', 'Eggs']

Ce comportement est différent des types immuables comme les chaînes et les nombres, où la valeur originale ne peut pas être modifiée par une fonction. Comprendre cette distinction est crucial pour écrire des programmes corrects.


Les listes sont l’une des structures de données les plus fondamentales et polyvalentes de Python. Elles fournissent une collection ordonnée et mutable qui peut grandir et rétrécir selon les besoins, ce qui les rend parfaites pour stocker et traiter des séquences de données liées. Vous avez appris à créer des listes, accéder à leurs éléments via l’indexation et le slicing, les modifier avec diverses méthodes, les parcourir efficacement, et comprendre leur nature mutable.

Les modèles que nous avons explorés — recherche, filtrage, agrégation, et transformation de données — constituent la base du travail avec des collections en Python. Au fur et à mesure que vous continuerez à apprendre, vous découvrirez des façons encore plus puissantes de travailler avec des listes, notamment les compréhensions de listes (chapitre 35) et des techniques d’itération avancées (chapitres 36-37). Mais les fondamentaux que vous avez maîtrisés dans ce chapitre vous serviront tout au long de votre parcours de programmation en Python.


© 2025. Primesoft Co., Ltd.
support@primesoft.ai