07 - 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 produit le code [x * 2 for x in range(4)] ?

  • 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. On multiplie chaque valeur par 2 : 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 [x for x in range(4)] (sans la multiplication).
  • D est faux : range(4) produit quatre valeurs, pas cinq. Erreur du « off-by-one ».

Exercice 2 : exemple travaillé – construire et parcourir une liste

Problème : on souhaite créer la liste des carrés des entiers de 1 à 5, puis afficher chaque élément avec son indice.

Étape 1. Créer la liste par compréhension :

carres = [n ** 2 for n in range(1, 6)]
print(carres)  # [1, 4, 9, 16, 25]

Étape 2. Parcourir la liste avec les indices grâce à enumerate() :

for i, valeur in enumerate(carres):
    print(f"carres[{i}] = {valeur}")

Résultat :

carres[0] = 1
carres[1] = 4
carres[2] = 9
carres[3] = 16
carres[4] = 25

Point clé : enumerate() renvoie à chaque tour un couple (indice, valeur), ce qui évite de gérer l’indice manuellement.


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).
  3. Remplacer "dimanche" par "DIMANCHE".
  4. Afficher la longueur de la liste.
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)
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]

Alternative par compréhension : pairs = [i * 2 for i in range(12)]


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).
  3. Bob a été disqualifié. Le retirer de la liste avec remove() et afficher le nouveau classement.
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.

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, 1):
    print(f"  {i}. {art}")

4.3 Séparation pair/impair (mathématiques)

Écrire une fonction separer(L) qui prend une liste de nombres et renvoie deux listes : les nombres pairs et les nombres impairs.

print(separer([3, 8, 12, 5, 7, 20]))
# ([8, 12, 20], [3, 5, 7])
Correction
def separer(L):
    pairs = []
    impairs = []
    for x in L:
        if x % 2 == 0:
            pairs.append(x)
        else:
            impairs.append(x)
    return (pairs, impairs)

print(separer([3, 8, 12, 5, 7, 20]))
# ([8, 12, 20], [3, 5, 7])

Variante par compréhension :

def separer(L):
    return ([x for x in L if x % 2 == 0],
            [x for x in L if x % 2 != 0])

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

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 : l’opérateur not in parcourt toute la liste resultat à chaque test, ce qui rend la complexité quadratique ($O(n^2)$) dans le pire cas. Pour de grandes listes, on utiliserait un ensemble (set).


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.
  2. Écrire une fonction au_dessus(L, seuil) qui renvoie la liste des températures strictement supérieures au seuil donné.
  3. Écrire une fonction indice_max(L) qui renvoie l’indice de la valeur maximale (sans utiliser max() ni index()).
  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.
Correction
def moyenne(L):
    return sum(L) / len(L)

def au_dessus(L, seuil):
    return [x for x in L if x > seuil]

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 : [14.0, 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):
    return L[1:]

a = [3, 6, 9]
b = sans_premier(a)
print(a, b)
retirer_premier(a)
print(a, b)
  1. Laquelle des deux fonctions a un effet de bord ? À quoi le voit-on dans son code ?
  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.
Correction
  1. Affichage :
[3, 6, 9] [6, 9]
[6, 9] [6, 9]

sans_premier construit une nouvelle liste par slicing : 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(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

Écrire chacune des listes suivantes en une seule instruction, par compréhension.

  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.
  5. À partir de nombres = [4, -2, 7, 0, -9, 3], les nombres strictement positifs.
  6. À partir de matrice = [[1, 2, 3], [4, 5, 6]], la liste « aplatie » [1, 2, 3, 4, 5, 6].
Correction
mots = ["chat", "girafe", "python", "oie", "hérisson"]
nombres = [4, -2, 7, 0, -9, 3]
matrice = [[1, 2, 3], [4, 5, 6]]

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]
print([x for ligne in matrice for x in ligne])         # [1, 2, 3, 4, 5, 6]

Pour la dernière, les deux for se lisent dans l’ordre des boucles imbriquées : pour chaque ligne de la matrice, pour chaque x de la ligne.