08 - Listes
Les exercices se font dans Thonny, dans le fichier 08_listes.py.
Cours associé : 09 - Listes .
Exercice 1 : QCM – vérification des prérequis
Pour chaque question, une seule réponse est correcte.
1. Que vaut len([3, 1, 4, 1, 5]) ?
- A. 4
- B. 5
- C. 14
- D. Erreur
Correction
Réponse : B. len() renvoie le nombre d’éléments de la liste, soit cinq. Les doublons comptent.
- A est faux : erreur de comptage (oubli d’un élément).
- C est faux : confusion entre
len()(nombre d’éléments) etsum()(somme des éléments : $3+1+4+1+5 = 14$). - D est faux :
len()s’applique parfaitement à une liste.
2. On définit L = [10, 20, 30, 40]. Que vaut L[2] ?
- A. 10
- B. 20
- C. 30
- D. 40
Correction
Réponse : C. L’indexation commence à 0 : L[0] = 10, L[1] = 20, L[2] = 30.
- A est faux : c’est
L[0]. - B est faux : c’est
L[1]. Erreur classique consistant à commencer l’indexation à 1. - D est faux : c’est
L[3].
3. Quel est l’effet de L.append(50) sur la liste L = [10, 20, 30] ?
- A.
Lvaut[50, 10, 20, 30] - B.
Lvaut[10, 20, 30, 50] - C.
Lvaut[10, 20, 50, 30] - D. Cela renvoie une nouvelle liste
[10, 20, 30, 50]sans modifierL
Correction
Réponse : B. append() ajoute un élément à la fin de la liste. La liste est modifiée en place (pas de nouvelle liste créée).
- A est faux : l’insertion au début se fait avec
L.insert(0, 50), pas avecappend. - C est faux : l’insertion à une position arbitraire se fait avec
L.insert(i, val). - D est faux :
append()modifie la liste en place et renvoieNone.
4. Que contient la liste L après l’exécution du programme suivant ?
L = []
for x in range(4):
L.append(x * 2)
- A.
[0, 2, 4, 6] - B.
[2, 4, 6, 8] - C.
[0, 1, 2, 3] - D.
[0, 2, 4, 6, 8]
Correction
Réponse : A. range(4) produit 0, 1, 2, 3. À chaque tour, on ajoute le double de x à la fin de L : 0, 2, 4, 6.
- B est faux :
range(4)commence à 0, pas à 1. Il faudraitrange(1, 5)pour obtenir[2, 4, 6, 8]. - C est faux : c’est le résultat de
L.append(x), sans la multiplication. - D est faux :
range(4)produit quatre valeurs, pas cinq.
Exercice 2 : construction et parcours d’une liste
On considère le programme suivant.
carres = []
for n in range(1, 6):
carres.append(n * n)
print(carres)
- Sans exécuter le programme, recopier et compléter le tableau suivant, qui donne le contenu de
carresà la fin de chaque tour de boucle.
| Tour | n | carres à la fin du tour |
|---|---|---|
| 1 | 1 | [1] |
| 2 | 2 | |
| 3 | ||
| 4 | ||
| 5 |
Qu’affiche la dernière ligne ? Exécuter le programme dans Thonny pour vérifier.
Modifier le programme pour qu’il construise la liste des cubes des entiers de 1 à 5, c’est-à-dire
[1, 8, 27, 64, 125].Indice
Une seule ligne du programme calcule la valeur ajoutée à la liste : c’est la seule à modifier.
On veut afficher chaque carré avec sa position dans la liste :
position 0 : 1
position 1 : 4
position 2 : 9
position 3 : 16
position 4 : 25
Compléter la boucle suivante, qui parcourt les indices de la liste, en remplaçant ... par l’élément d’indice i :
for i in range(len(carres)):
print(f"position {i} : {...}")
Indice
Dans la boucle, i est une position. L’élément situé à une position donnée s’obtient avec des crochets, comme L[0] pour le premier élément d’une liste L.
Correction
1. À chaque tour, append ajoute le carré de n à la fin de la liste.
| Tour | n | carres à la fin du tour |
|---|---|---|
| 1 | 1 | [1] |
| 2 | 2 | [1, 4] |
| 3 | 3 | [1, 4, 9] |
| 4 | 4 | [1, 4, 9, 16] |
| 5 | 5 | [1, 4, 9, 16, 25] |
2. Le programme affiche [1, 4, 9, 16, 25]. La boucle s’arrête après n = 5, car range(1, 6) s’arrête juste avant 6.
3. On remplace n * n par n * n * n :
cubes = []
for n in range(1, 6):
cubes.append(n * n * n)
print(cubes) # [1, 8, 27, 64, 125]
4. L’élément d’indice i s’écrit carres[i] :
for i in range(len(carres)):
print(f"position {i} : {carres[i]}")
len(carres) vaut 5, donc i prend les valeurs 0, 1, 2, 3 et 4 : ce sont exactement les indices de la liste.
Exercice 3 : manipulations guidées
3.1 Création et accès
Créer une liste
jourscontenant les sept jours de la semaine.Afficher le troisième jour (attention à l’indexation).
Indice
Les positions commencent à 0 : le premier jour a l’indice 0.
Remplacer
"dimanche"par"DIMANCHE".Indice
Pour remplacer un élément, on affecte une nouvelle valeur à sa position :
jours[indice] = nouvelle_valeur.Afficher la longueur de la liste.
# Compléter :
jours = [...]
Correction
jours = ["lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche"]
print(jours[2]) # "mercredi" (le 3e élément a l'indice 2)
jours[6] = "DIMANCHE" # ou jours[-1] = "DIMANCHE"
print(len(jours)) # 7
3.2 Construction par accumulation
Compléter le code suivant pour construire la liste des douze premiers nombres pairs (de 0 à 22) :
pairs = []
for i in range(___):
pairs.append(___)
print(pairs)
Indice
Il faut douze nombres, donc douze tours de boucle. Au tour i, le nombre pair à ajouter est le double de i.
Correction
pairs = []
for i in range(12):
pairs.append(i * 2)
print(pairs) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22]
Exercice 4 : exercices progressifs
4.1 Classement sportif (sport)
Le classement d’une course est : ["Alice", "Bob", "Clara", "David", "Eva"].
Afficher le(la) gagnant(e) (premier(ère) de la liste).
Afficher le(la) dernier(ère) (sans connaître la taille de la liste à l’avance).
Indice
Le dernier élément d’une liste a l’indice
-1, quelle que soit sa longueur.Bob a été disqualifié. Le retirer de la liste avec
remove()et afficher le nouveau classement.Indice
removereçoit la valeur à retirer, pas sa position :classement.remove(...).
Correction
classement = ["Alice", "Bob", "Clara", "David", "Eva"]
print(f"Gagnant(e) : {classement[0]}") # Alice
print(f"Dernier(ère) : {classement[-1]}") # Eva
classement.remove("Bob")
print(classement) # ['Alice', 'Clara', 'David', 'Eva']
Point important : classement[-1] accède au dernier élément quelle que soit la longueur de la liste.
4.2 Liste de courses (vie courante)
Écrire un programme qui demande à l’utilisateur de saisir des articles un par un (en tapant "fin" pour arrêter), puis affiche la liste complète et le nombre total d’articles.
Indice
Utiliser une boucle while : demander un premier article avec input, puis, tant que la saisie n’est pas "fin", l’ajouter à la liste et demander l’article suivant. Le nombre d’articles est la longueur de la liste.
Code à copier puis compléter
courses = []
article = input("Article (ou fin) : ")
while article != ...:
courses.append(...)
article = ...
print(f"Liste de courses : {courses}")
print(f"Nombre d'articles : {...}")
Correction
courses = []
while True:
article = input("Article (ou 'fin') : ")
if article == "fin":
break
courses.append(article)
print(f"Liste de courses ({len(courses)} articles) :")
for i, art in enumerate(courses):
print(f" {i + 1}. {art}")
4.3 Séparation pair/impair (mathématiques)
Écrire une fonction nombres_pairs(L) qui prend une liste de nombres et renvoie la liste de ses nombres pairs, puis une fonction nombres_impairs(L) qui renvoie la liste de ses nombres impairs.
print(nombres_pairs([3, 8, 12, 5, 7, 20])) # [8, 12, 20]
print(nombres_impairs([3, 8, 12, 5, 7, 20])) # [3, 5, 7]
Indice
Partir d’une liste vide, parcourir L avec une boucle for et ajouter avec append chaque élément pair. Un nombre x est pair lorsque x % 2 == 0. La fonction nombres_impairs suit le même modèle, avec le test contraire.
Code à copier puis compléter
def nombres_pairs(L):
resultat = []
for x in L:
if ...:
resultat.append(...)
return resultat
Correction
def nombres_pairs(L):
resultat = []
for x in L:
if x % 2 == 0:
resultat.append(x)
return resultat
def nombres_impairs(L):
resultat = []
for x in L:
if x % 2 != 0:
resultat.append(x)
return resultat
print(nombres_pairs([3, 8, 12, 5, 7, 20])) # [8, 12, 20]
print(nombres_impairs([3, 8, 12, 5, 7, 20])) # [3, 5, 7]
Exercice 5 : suppression des doublons
Écrire une fonction sans_doublons(L) qui prend une liste et renvoie une nouvelle liste contenant les mêmes éléments, dans le même ordre, mais sans les doublons.
print(sans_doublons([3, 1, 4, 1, 5, 9, 2, 6, 5, 3]))
# [3, 1, 4, 5, 9, 2, 6]
Indication : parcourir la liste et n’ajouter un élément à la nouvelle liste que s’il n’y figure pas déjà (tester avec not in).
Code à copier puis compléter
def sans_doublons(L):
resultat = []
for x in L:
if ...:
...
return resultat
Correction
def sans_doublons(L):
resultat = []
for x in L:
if x not in resultat:
resultat.append(x)
return resultat
print(sans_doublons([3, 1, 4, 1, 5, 9, 2, 6, 5, 3]))
# [3, 1, 4, 5, 9, 2, 6]
Remarque : le test x not in resultat parcourt la liste resultat à chaque tour de boucle.
Exercice 6 : synthèse – relevé de températures (géographie)
On dispose du relevé de températures (en °C) d’une semaine : [12.5, 14.0, 11.3, 15.8, 13.2, 9.7, 16.1].
Écrire une fonction
moyenne(L)qui calcule la moyenne d’une liste de nombres.Indice
La moyenne est la somme des éléments divisée par leur nombre. La fonction
sum(L)donne la somme des éléments deL, etlen(L)leur nombre.Écrire une fonction
au_dessus(L, seuil)qui renvoie la liste des températures strictement supérieures au seuil donné.Indice
Même modèle que
nombres_pairs(exercice 4.3) : seul le test change, icix > seuil.Écrire une fonction
indice_max(L)qui renvoie l’indice de la valeur maximale (sans utilisermax()niindex()).Indice
Garder dans une variable
i_maxla position du plus grand élément rencontré jusque-là. Au départ,i_maxvaut 0 ; on parcourt ensuite les positions suivantes et on meti_maxà jour dès queL[i]dépasseL[i_max].Code à copier puis compléter
def indice_max(L): i_max = 0 for i in range(1, len(L)): if ...: i_max = ... return i_maxUtiliser ces fonctions pour afficher la température moyenne de la semaine, les jours où il a fait plus de 14 °C et le jour le plus chaud.
Indice
Appeler chaque fonction sur la liste des températures.
indice_maxrenvoie une position, pas un jour : créer la liste des jours dans le même ordre que les températures (jours = ["lundi", "mardi", ...]), puis lire le jour situé à cette position.
Correction
def moyenne(L):
return sum(L) / len(L)
def au_dessus(L, seuil):
resultat = []
for x in L:
if x > seuil:
resultat.append(x)
return resultat
def indice_max(L):
i_max = 0
for i in range(1, len(L)):
if L[i] > L[i_max]:
i_max = i
return i_max
temps = [12.5, 14.0, 11.3, 15.8, 13.2, 9.7, 16.1]
jours = ["lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche"]
print(f"Moyenne : {round(moyenne(temps), 1)} °C")
print(f"Jours > 14 °C : {au_dessus(temps, 14)}")
i = indice_max(temps)
print(f"Jour le plus chaud : {jours[i]} ({temps[i]} °C)")
Résultat :
Moyenne : 13.2 °C
Jours > 14 °C : [15.8, 16.1]
Jour le plus chaud : dimanche (16.1 °C)
Exercice 7 : effets de bord
- Prévoir l’affichage du programme suivant, puis vérifier.
def retirer_premier(L):
L.pop(0)
def sans_premier(L):
M = []
for i in range(1, len(L)):
M.append(L[i])
return M
a = [3, 6, 9]
b = sans_premier(a)
print(f"{a} {b}")
retirer_premier(a)
print(f"{a} {b}")
Laquelle des deux fonctions a un effet de bord ? À quoi le voit-on dans son code ?
Indice
Chercher, dans le code de chaque fonction, une instruction qui modifie la liste reçue en paramètre.
Écrire une fonction
plafonner(L, m)qui remplace, dans la listeLelle-même, chaque valeur strictement supérieure àmparm, et ne renvoie rien. Écrire ensuite une fonctionplafonnee(L, m)qui renvoie une nouvelle liste plafonnée et laisseLintacte.Indice
plafonnermodifie la liste reçue : parcourir ses positions avecfor i in range(len(L))et remplacerL[i]parmlorsqu’il le dépasse.plafonneeconstruit au contraire une nouvelle liste avecappend, commesans_premier, et la renvoie.Code à copier puis compléter
def plafonner(L, m): for i in range(len(L)): if ...: L[i] = ... def plafonnee(L, m): resultat = [] for x in L: if x > m: resultat.append(...) else: resultat.append(...) return resultat
Correction
- Affichage :
[3, 6, 9] [6, 9]
[6, 9] [6, 9]
sans_premier construit une nouvelle liste M élément par élément et la renvoie : a n’est pas modifiée. retirer_premier appelle pop sur la liste reçue, qui est a elle-même : après l’appel, a a perdu son premier élément. b, liste distincte, ne change pas.
retirer_premiera un effet de bord : elle appelle une méthode qui modifie la liste (pop) et ne renvoie rien.sans_premierne modifie rien et renvoie un résultat.Les deux versions :
def plafonner(L, m):
"""Remplace dans L chaque valeur > m par m. Modifie L, ne renvoie rien."""
for i in range(len(L)):
if L[i] > m:
L[i] = m
def plafonnee(L, m):
"""Renvoie une nouvelle liste plafonnée à m ; L n'est pas modifiée."""
resultat = []
for x in L:
if x > m:
resultat.append(m)
else:
resultat.append(x)
return resultat
notes = [8, 21, 15, 23]
print(f"{plafonnee(notes, 20)} {notes}") # [8, 20, 15, 20] [8, 21, 15, 23]
plafonner(notes, 20)
print(notes) # [8, 20, 15, 20]
Exercice 8 : compréhensions de listes
Cet exercice s’appuie sur la dernière section du cours, « Construction par compréhension ».
8.1 Construire des listes
Écrire chacune des listes suivantes en une seule instruction, par compréhension.
Indice
Une compréhension s’écrit [expression for x in séquence] ; une condition éventuelle se place à la fin : [expression for x in séquence if condition]. Par exemple, [x * 10 for x in range(4)] vaut [0, 10, 20, 30].
Les entiers de 0 à 10.
Les carrés des entiers de 0 à 10.
Les entiers pairs de 0 à 20.
À partir de
mots = ["chat", "girafe", "python", "oie", "hérisson"], les mots d’au moins six caractères, écrits en majuscules.Indice
La méthode
upper()renvoie la chaîne écrite en majuscules :"chat".upper()vaut"CHAT". Dans la compréhension, l’expression met donc le mot en majuscules, et la condition porte sur sa longueur.À partir de
nombres = [4, -2, 7, 0, -9, 3], les nombres strictement positifs.
Correction
mots = ["chat", "girafe", "python", "oie", "hérisson"]
nombres = [4, -2, 7, 0, -9, 3]
print([i for i in range(11)]) # [0, 1, ..., 10]
print([i ** 2 for i in range(11)]) # [0, 1, 4, ..., 100]
print([i for i in range(0, 21, 2)]) # [0, 2, 4, ..., 20]
print([m.upper() for m in mots if len(m) >= 6]) # ['GIRAFE', 'PYTHON', 'HÉRISSON']
print([x for x in nombres if x > 0]) # [4, 7, 3]
8.2 Réécrire des fonctions
Réécrire les fonctions nombres_pairs et nombres_impairs de l’exercice 4.3, puis la fonction au_dessus de l’exercice 6 : le corps de chaque fonction tient en une seule ligne, return suivi d’une compréhension.
Indice
Dans chaque fonction, la boucle for, le test if et les append deviennent une seule compréhension avec condition : reprendre le test du if à la fin de la compréhension, après return.
Correction
def nombres_pairs(L):
return [x for x in L if x % 2 == 0]
def nombres_impairs(L):
return [x for x in L if x % 2 != 0]
def au_dessus(L, seuil):
return [x for x in L if x > seuil]
La boucle, la liste vide de départ et les appels à append() sont remplacés par une seule expression : la compréhension construit la liste et return la renvoie.
8.3 Pour aller plus loin : aplatir une liste de listes
À partir de matrice = [[1, 2, 3], [4, 5, 6]], construire par compréhension la liste [1, 2, 3, 4, 5, 6]. La compréhension contient cette fois deux for, écrits l’un après l’autre dans l’ordre des boucles imbriquées : d’abord celui de la boucle extérieure, puis celui de la boucle intérieure.
Indice
Écrire d’abord les deux boucles imbriquées qui parcourent chaque ligne de matrice, puis chaque élément de cette ligne. La compréhension reprend les deux for dans le même ordre, après l’expression x.
Correction
matrice = [[1, 2, 3], [4, 5, 6]]
print([x for ligne in matrice for x in ligne]) # [1, 2, 3, 4, 5, 6]
Les deux for se lisent dans l’ordre des boucles imbriquées : pour chaque ligne de la matrice, puis pour chaque x de cette ligne.