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) et sum() (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. L vaut [50, 10, 20, 30]
  • B. L vaut [10, 20, 30, 50]
  • C. L vaut [10, 20, 50, 30]
  • D. Cela renvoie une nouvelle liste [10, 20, 30, 50] sans modifier L
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 avec append.
  • 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 renvoie None.

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 faudrait range(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)
  1. 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.
Tourncarres à la fin du tour
11[1]
22
3
4
5
  1. Qu’affiche la dernière ligne ? Exécuter le programme dans Thonny pour vérifier.

  2. 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.

  3. 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.

Tourncarres à la fin du tour
11[1]
22[1, 4]
33[1, 4, 9]
44[1, 4, 9, 16]
55[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

  1. Créer une liste jours contenant les sept jours de la semaine.

  2. Afficher le troisième jour (attention à l’indexation).

    Indice

    Les positions commencent à 0 : le premier jour a l’indice 0.

  3. Remplacer "dimanche" par "DIMANCHE".

    Indice

    Pour remplacer un élément, on affecte une nouvelle valeur à sa position : jours[indice] = nouvelle_valeur.

  4. 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"].

  1. Afficher le(la) gagnant(e) (premier(ère) de la liste).

  2. 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.

  3. Bob a été disqualifié. Le retirer de la liste avec remove() et afficher le nouveau classement.

    Indice

    remove reç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].

  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 de L, et len(L) leur nombre.

  2. É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, ici x > seuil.

  3. Écrire une fonction indice_max(L) qui renvoie l’indice de la valeur maximale (sans utiliser max() ni index()).

    Indice

    Garder dans une variable i_max la position du plus grand élément rencontré jusque-là. Au départ, i_max vaut 0 ; on parcourt ensuite les positions suivantes et on met i_max à jour dès que L[i] dépasse L[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_max
    
  4. Utiliser 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_max renvoie 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

  1. 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}")
  1. 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.

  2. Écrire une fonction plafonner(L, m) qui remplace, dans la liste L elle-même, chaque valeur strictement supérieure à m par m, et ne renvoie rien. Écrire ensuite une fonction plafonnee(L, m) qui renvoie une nouvelle liste plafonnée et laisse L intacte.

    Indice

    plafonner modifie la liste reçue : parcourir ses positions avec for i in range(len(L)) et remplacer L[i] par m lorsqu’il le dépasse. plafonnee construit au contraire une nouvelle liste avec append, comme sans_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
  1. 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.

  1. retirer_premier a un effet de bord : elle appelle une méthode qui modifie la liste (pop) et ne renvoie rien. sans_premier ne modifie rien et renvoie un résultat.

  2. 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].

  1. Les entiers de 0 à 10.

  2. Les carrés des entiers de 0 à 10.

  3. Les entiers pairs de 0 à 20.

  4. À 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.

  5. À 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.