Accueil/Informatique & Développement /Chapitre 07 /Exercices corrigés

Python — exercices

Des TP1 à TP6 et du support d'exercices — avec les résultats vérifiés.

🎯

Deux réflexes avant de coder

Écrivez l'algorithme en français d'abord : entrées, traitements, sorties. Et pensez à convertir tout ce qui sort d'un input(). Ces deux gestes éliminent la moitié des erreurs.

01Le signe d'un produit (TP1 · ex. 1)

1Sans calculer le produit Moyen

Demander deux nombres entiers et indiquer si leur produit est négatif ou positif. Contrainte : on ne doit pas calculer le produit. (Le cas du produit nul est laissé de côté.)

✅ Correction
python
a = int(input("Premier nombre : "))
b = int(input("Deuxième nombre : "))

if (a > 0 and b > 0) or (a < 0 and b < 0):
    print("Le produit est positif")
else:
    print("Le produit est négatif")
🧰 La règle des signes, traduite en code

Le produit est positif quand les deux nombres ont le même signe — tous deux positifs, ou tous deux négatifs. Sinon il est négatif. Aucune multiplication n'est nécessaire : c'est tout l'intérêt de l'exercice.

Version encore plus courte, qui exprime directement « même signe » :

python
if (a > 0) == (b > 0):
    print("Le produit est positif")
else:
    print("Le produit est négatif")

(a > 0) vaut True ou False : on compare directement les deux booléens.

⚠️ Le piège est dans l'énoncé

« On ne doit pas calculer le produit » — beaucoup écrivent quand même if a * b > 0:. C'est juste mathématiquement, mais cela ne répond pas à la question posée, et l'exercice est raté.

Lisez les contraintes : elles sont là parce qu'elles imposent une autre façon de penser.

02Catégories de niveau (TP1 · ex. 2)

2Quatre tranches Facile

Demander combien de langages de programmation l'utilisateur connaît, puis afficher sa catégorie : Débutant (0 à 1), Intermédiaire (2 à 3), Avancé (4 à 5), Expert (plus de 5).

✅ Correction
python
n = int(input("Combien de langages connaissez-vous ? "))

if n <= 1:
    print("Débutant")
elif n <= 3:
    print("Intermédiaire")
elif n <= 5:
    print("Avancé")
else:
    print("Expert")
🧰 Une seule borne par test suffit

On pourrait écrire elif n >= 2 and n <= 3:. C'est inutile : si l'on atteint ce test, c'est que n <= 1 était faux, donc que n vaut au moins 2. Chaque branche hérite du contraire des précédentes.

Testez avec 1, 2, 3, 4, 5 et 6 : ce sont les valeurs aux frontières qui révèlent les erreurs.

03Crédit logement (TP1 · ex. 3)

3Trois cas d'attribution Moyen

Un agent peut bénéficier du crédit logement dans l'un des trois cas suivants :

  1. 4 ans d'ancienneté et note ≥ 16 ;
  2. 3 ans d'ancienneté et note ≥ 18 ;
  3. 5 ans ou plus et note ≥ 13.
✅ Correction
python
anciennete = int(input("Années d'ancienneté : "))
note       = float(input("Note d'appréciation : "))

if (anciennete == 4 and note >= 16) \
   or (anciennete == 3 and note >= 18) \
   or (anciennete >= 5 and note >= 13):
    print("L'agent peut bénéficier du crédit logement.")
else:
    print("L'agent ne peut pas en bénéficier.")
🧰 La structure de la condition reflète l'énoncé

Trois cas séparés par « ou » (or), et dans chaque cas deux critères liés par « et » (and). Les parenthèses ne sont pas décoratives : sans elles, la priorité de and sur or produirait un regroupement différent de ce que vous voulez.

Le \ en fin de ligne permet de poursuivre l'instruction à la ligne suivante — utile pour rester lisible. On peut aussi entourer toute la condition d'une paire de parenthèses.

⚠️ == 4 et non >= 4

Le cas 1 dit « 4 ans d'ancienneté », pas « au moins 4 ans ». Écrire anciennete >= 4 ferait passer un agent de 6 ans avec 16 par ce cas — ce qui est vrai par le cas 3 (≥ 5 et ≥ 13), mais fausserait un agent de 4 ans avec 14, qui doit être refusé.

Vérifiez chaque cas limite : 4 ans / 15 → refusé · 3 ans / 18 → accepté · 5 ans / 13 → accepté.

04Sommes et nombres premiers

4Trois classiques des boucles Moyen

  1. Calculer et afficher la somme de tous les entiers de 1 à 50.
  2. Afficher tous les nombres premiers entre 2 et 50.
  3. Demander un mot et compter ses voyelles (a, e, i, o, u, y).
✅ Correction
python — 1. la somme
somme = 0
for i in range(1, 51):        # 51 exclu → on va bien jusqu'à 50
    somme += i

print("Somme :", somme)       # Somme : 1275

Vérification : la formule de Gauss donne 50 × 51 / 2 = 1275. ✔

python — 2. les nombres premiers
for n in range(2, 51):
    est_premier = True

    for diviseur in range(2, int(n ** 0.5) + 1):
        if n % diviseur == 0:
            est_premier = False
            break

    if est_premier:
        print(n, end=" ")

# 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47      → 15 nombres
python — 3. les voyelles
mot = input("Entrez un mot : ").lower()
compteur = 0

for lettre in mot:
    if lettre in "aeiouy":
        compteur += 1

print(f"{compteur} voyelle(s)")

# "informatique" → 6 voyelles
🧰 Trois idiomes Python à retenir
for lettre in mot: on parcourt une chaîne directement, sans indice
if lettre in "aeiouy": in teste l'appartenance — bien plus court que six or
.lower() met en minuscules, sinon « A » ne serait pas comptée

Et int(n ** 0.5) donne la racine carrée : au-delà, tout diviseur aurait déjà été trouvé (voir le même raisonnement au chapitre JavaScript).

05Listes de postes (TP3 · ex. 1)

5Afficher, ajouter, supprimer Facile

python — données
postes = ["PC01", "PC02", "PC03", "PC04", "PC05"]
  1. Afficher tous les postes.
  2. Ajouter "PC06".
  3. Supprimer "PC03".
✅ Correction
python
postes = ["PC01", "PC02", "PC03", "PC04", "PC05"]

# 1. Afficher
for poste in postes:
    print(poste)

# 2. Ajouter
postes.append("PC06")
# → PC01 PC02 PC03 PC04 PC05 PC06

# 3. Supprimer
postes.remove("PC03")
# → PC01 PC02 PC04 PC05 PC06
⚠️ remove() supprime par VALEUR, pas par indice
postes.remove("PC03")supprime l'élément qui vaut "PC03"
del postes[2]supprime l'élément à l'indice 2
postes.pop()retire le dernier et le renvoie

Deux détails qui piquent : remove() ne supprime que la première occurrence, et lève une ValueError si la valeur est absente. Pour être sûr :

python
if "PC03" in postes:
    postes.remove("PC03")
⚠️ Ne modifiez jamais une liste que vous parcourez
python — comportement imprévisible
for poste in postes:
    if poste.startswith("PC0"):
        postes.remove(poste)      # ✘ la liste se décale sous les pieds de la boucle

Des éléments sont sautés. La parade : parcourir une copie (for poste in postes[:]:) ou construire une nouvelle liste.

06Dédupliquer des IP (TP3 · ex. 2)

6Supprimer les doublons Moyen

python — données
connexions = ["192.168.0.10", "192.168.0.12", "10.0.0.5", "192.168.0.10"]
  1. Afficher toutes les connexions.
  2. Créer une nouvelle liste sans doublons.
✅ Correction
python
connexions = ["192.168.0.10", "192.168.0.12", "10.0.0.5", "192.168.0.10"]

# 1. Toutes les connexions
for ip in connexions:
    print("IP :", ip)

# 2. Sans doublons
uniques = set(connexions)
for ip in uniques:
    print("IP :", ip)

# IP : 10.0.0.5
# IP : 192.168.0.12
# IP : 192.168.0.10
⚠️ L'ordre a changé — et ce n'est pas un bug

Comparez la liste de départ et la sortie : 10.0.0.5 arrive en premier alors qu'elle était troisième. Un set n'est pas ordonné : il garantit l'unicité, pas l'ordre.

Si l'ordre compte, deux solutions :

python
uniques = sorted(set(connexions))       # dédoublonné puis TRIÉ

uniques = list(dict.fromkeys(connexions))   # garde l'ordre d'APPARITION

La seconde écriture exploite le fait qu'un dictionnaire conserve l'ordre d'insertion et ne peut pas avoir deux fois la même clé.

🌍 Ce que raconte un doublon d'IP

Dans un journal de connexions, une IP qui revient n'est pas anormale : c'est une machine qui s'est connectée plusieurs fois. Dédupliquer répond à la question « combien de machines distinctes ? », pas « combien de connexions ? ». Deux questions, deux traitements — ne les confondez pas dans un rapport.

07Dictionnaire de matériel (TP3 · ex. 3)

7Parcourir un stock Moyen

python — données
materiel = {
    "switch": 5,
    "routeur": 2,
    "point_acces": 7
}

Afficher le stock complet, puis ajouter un matériel et calculer le total.

✅ Correction
python — avec .items()
for nom, quantite in materiel.items():
    print(f"Matériel : {nom} | Quantité : {quantite}")

# Matériel : switch | Quantité : 5
# Matériel : routeur | Quantité : 2
# Matériel : point_acces | Quantité : 7
python — sur les clés seules
for nom in materiel:
    print(nom, materiel[nom])
python — ajouter et totaliser
materiel["firewall"] = 3           # ajout

total = 0
for quantite in materiel.values():
    total += quantite
print("Total :", total)            # 17

# ou, en une ligne :
print("Total :", sum(materiel.values()))
🧰 .items() est la forme à privilégier

Les deux parcours donnent le même résultat, mais .items() récupère la clé et la valeur en un seul geste. La seconde forme doit aller rechercher materiel[nom] à chaque tour — plus verbeux et un peu plus lent.

Repère : .keys() les clés · .values() les valeurs · .items() les deux.

⚠️ Affecter une clé inexistante la CRÉE
python
materiel["firewal"] = 3     # faute de frappe → crée une NOUVELLE entrée
print(materiel)
# {'switch': 5, …, 'firewall': 3, 'firewal': 3}   ← deux entrées !

Contrairement à la lecture d'une clé absente, qui lève une KeyError bien visible, l'écriture ne proteste jamais. C'est pourquoi un stock peut silencieusement se dédoubler.

08Fonctions et rôles (TP6)

8Filtrer des utilisateurs Exigeant

Une entreprise gère ses comptes utilisateurs. Chaque utilisateur est un tuple (nom, prénom, âge, rôle).

python — données
utilisateurs = [
    ("Dupont", "Alice",   25, "admin"),
    ("Martin", "Bob",     30, "utilisateur"),
    ("Durand", "Charlie", 22, "technicien"),
    ("Petit",  "Diane",   28, "admin"),
    ("Leroy",  "Eve",     35, "utilisateur"),
]
  1. Une fonction afficher_utilisateurs_role(role) qui affiche les utilisateurs d'un rôle donné.
  2. Une fonction qui retourne la liste des rôles existants, sans doublon.
  3. Une fonction qui regroupe les utilisateurs par rôle.
✅ Correction
python
utilisateurs = [
    ("Dupont", "Alice",   25, "admin"),
    ("Martin", "Bob",     30, "utilisateur"),
    ("Durand", "Charlie", 22, "technicien"),
    ("Petit",  "Diane",   28, "admin"),
    ("Leroy",  "Eve",     35, "utilisateur"),
]


# 1. Afficher les utilisateurs d'un rôle
def afficher_utilisateurs_role(role):
    for nom, prenom, age, r in utilisateurs:
        if r == role:
            print(f"{prenom} {nom} ({age} ans)")


# 2. La liste des rôles, sans doublon
def liste_des_roles():
    roles = set()
    for utilisateur in utilisateurs:
        roles.add(utilisateur[3])      # le rôle est le 4e élément
    return sorted(roles)


# 3. Regrouper par rôle
def grouper_par_role():
    groupes = {}
    for nom, prenom, age, role in utilisateurs:
        if role not in groupes:
            groupes[role] = []         # on crée la liste au premier venu
        groupes[role].append(f"{prenom} {nom}")
    return groupes
résultat
>>> afficher_utilisateurs_role("admin")
Alice Dupont (25 ans)
Diane Petit (28 ans)

>>> liste_des_roles()
['admin', 'technicien', 'utilisateur']

>>> grouper_par_role()
{'admin':       ['Alice Dupont', 'Diane Petit'],
 'utilisateur': ['Bob Martin', 'Eve Leroy'],
 'technicien':  ['Charlie Durand']}
🧰 Le déballage de tuple
python
for nom, prenom, age, r in utilisateurs:     # déballage : 4 variables d'un coup

for utilisateur in utilisateurs:             # ou par indice
    nom = utilisateur[0]
    role = utilisateur[3]

La première forme est bien plus lisible : les noms des variables documentent la structure. Avec la seconde, il faut se souvenir que « 3 » veut dire « le rôle » — et c'est ainsi qu'on se trompe de colonne.

⚠️ Créer la liste avant d'y ajouter
python
groupes[role].append(nom)        # ✘ KeyError au tout premier utilisateur

if role not in groupes:
    groupes[role] = []           # ✔ on crée d'abord la liste vide
groupes[role].append(nom)

Un dictionnaire ne devine pas qu'une clé doit contenir une liste. Python offre un raccourci pour ce motif très courant :

python
groupes.setdefault(role, []).append(nom)

« Donne-moi la liste de ce rôle, et si elle n'existe pas, crée-la vide. »

🌍 Pourquoi un tuple plutôt qu'une liste ici

Un utilisateur a une structure fixe : toujours nom, prénom, âge, rôle, dans cet ordre. Le tuple l'exprime — on ne peut pas le modifier par accident. Une liste d'utilisateurs, en revanche, doit pouvoir grandir : d'où une liste de tuples.

Dans un vrai programme, on irait plus loin avec un dictionnaire par utilisateur ({"nom": "Dupont", "role": "admin"}) : plus verbeux, mais on ne compte plus les positions.

⚡ Les erreurs qui coûtent le plus de points

  • Oublier int() / float() autour d'un input().
  • Oublier que range(1, 11) s'arrête à 10.
  • Indentation incohérente — ou tabulations mêlées aux espaces.
  • Oublier les deux-points après if, for, def.
  • remove() pris pour une suppression par indice.
  • Croire qu'un set garde l'ordre.
  • Ajouter dans un dictionnaire sans créer la liste → KeyError.
  • Ne pas lire les contraintes de l'énoncé (« sans calculer le produit »).

Sources exploitées

  • TP1 — Initiation à Python · TP3 — Listes et dictionnaires · TP6 — Fonctions (le professeur)
  • Support d'exercices Python (boucles, nombres premiers, voyelles, serveurs)
  • comptes rendus d'élève