correction examen
Exercice 1 : Questions de cours – Généralités (4pts)
1. Différence entre mutabilité et immutabilité en Python
Correction :
En Python, un objet mutable peut être modifié après sa création, tandis qu'un objet immutable ne le peut pas.
Exemple :
# Liste (mutable)
ma_liste = [1, 2, 3]
ma_liste[0] = 10 # Modification possible
print(ma_liste) # [10, 2, 3]
# Tuple (immutable)
mon_tuple = (1, 2, 3)
# mon_tuple[0] = 10 # Erreur ! TypeError
print(mon_tuple) # (1, 2, 3) - inchangé
Explication : Les listes sont mutables car on peut modifier leur contenu sans changer leur identité. Les tuples sont immutables car toute tentative de modification crée un nouvel objet.
2. Le paramètre key dans les fonctions sorted(), max(), min()
Correction :
Le paramètre key permet de spécifier une fonction qui sera appliquée à chaque élément pour déterminer la valeur de comparaison.
Exemple :
etudiants = [("Alice", 15), ("Bob", 12), ("Charlie", 18)]
# Trier par note (deuxième élément)
tries = sorted(etudiants, key=lambda x: x[1])
print(tries) # [('Bob', 12), ('Alice', 15), ('Charlie', 18)]
# Trouver l'étudiant avec la note max
meilleur = max(etudiants, key=lambda x: x[1])
print(meilleur) # ('Charlie', 18)
Explication : La fonction lambda lambda x: x[1] extrait la note de chaque tuple, et c'est sur cette valeur que se fait la comparaison.
3. Différence entre return et print dans une fonction
Correction :
- return renvoie une valeur qui peut être utilisée dans le programme
- print affiche une valeur mais ne la renvoie pas
Exemple :
def fonction_avec_return(x):
return x * 2
def fonction_avec_print(x):
print(x * 2)
resultat1 = fonction_avec_return(5) # resultat1 = 10
resultat2 = fonction_avec_print(5) # Affiche 10, mais resultat2 = None
print(f"Résultat avec return: {resultat1}") # Résultat avec return: 10
print(f"Résultat avec print: {resultat2}") # Résultat avec print: None
Explication : return permet de récupérer une valeur pour une utilisation ultérieure, print sert uniquement à l'affichage.
4. Les compréhensions de listes
Correction :
Une compréhension de liste est une syntaxe concise pour créer des listes à partir d'autres séquences.
Exemple :
# Créer une liste des carrés de 0 à 9
carres = [x**2 for x in range(10)]
print(carres) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# Avec condition (nombres pairs)
pairs = [x for x in range(10) if x % 2 == 0]
print(pairs) # [0, 2, 4, 6, 8]
# Sans compréhension (équivalent)
carres_sans_comp = []
for x in range(10):
carres_sans_comp.append(x**2)
Explication : La syntaxe [expression for élément in séquence if condition] est plus concise et souvent plus lisible que les boucles traditionnelles.
5. Les arguments par défaut dans les fonctions
Correction :
Les arguments par défaut permettent de donner une valeur par défaut à un paramètre si l'appelant ne fournit pas d'argument.
Exemple :
def saluer(nom, message="Bonjour"):
return f"{message}, {nom}!"
print(saluer("Alice")) # Bonjour, Alice!
print(saluer("Bob", "Salut")) # Salut, Bob!
print(saluer(nom="Charlie", message="Bienvenue")) # Bienvenue, Charlie!
Explication : Les paramètres avec valeurs par défaut doivent être placés après les paramètres sans valeur par défaut.
Exercice 2 : Analyse des stocks (3pts)
Énoncé :
Une boutique dispose d'un inventaire représenté par une liste de tuples (produit, quantité, prix_unitaire). Écrire une fonction qui retourne :
- La valeur totale du stock
- Les produits dont la quantité est inférieure à un seuil donné (paramètre optionnel avec valeur par défaut de 5)
- Le produit ayant la plus grande valeur en stock (quantité × prix)
Correction :
def analyse_stock(inventaire, seuil=5):
if not inventaire:
return 0, [], None
# 1. Valeur totale du stock
valeur_totale = sum(quantite * prix for _, quantite, prix in inventaire)
# 2. Produits avec stock faible
stock_faible = [(produit, quantite) for produit, quantite, prix in inventaire
if quantite < seuil]
# 3. Produit avec plus grande valeur
produit_max = max(inventaire, key=lambda x: x[1] * x[2])
nom_max, quantite_max, prix_max = produit_max
valeur_max = quantite_max * prix_max
return valeur_totale, stock_faible, (nom_max, valeur_max)
# Test
stock = [
("Stylo", 10, 1.5),
("Cahier", 3, 2.0),
("Gomme", 8, 0.8),
("Règle", 2, 1.2)
]
total, faible, meilleur = analyse_stock(stock)
print(f"Valeur totale du stock: {total:.2f} €")
print(f"Produits en stock faible: {faible}")
print(f"Produit de plus grande valeur: {meilleur[0]} ({meilleur[1]:.2f} €)")
# Avec seuil personnalisé
total, faible, meilleur = analyse_stock(stock, seuil=4)
print(f"\nAvec seuil=4 - Produits faibles: {faible}")
Exercice 3 : Compression de données clients (3pts)
Énoncé :
Une entreprise possède une liste de commandes clients sous forme [client, produit, prix]. Écrire deux fonctions :
compresser_commandes(liste) qui regroupe par client et retourne un dictionnaire {client: [liste des prix]}
statistiques_client(dictionnaire_compressé, client) qui retourne pour un client donné : nombre de commandes, prix total, prix moyen
Correction :
def compresser_commandes(commandes):
"""Compresse la liste de commandes en dictionnaire par client"""
resultat = {}
for client, produit, prix in commandes:
if client not in resultat:
resultat[client] = []
resultat[client].append(prix)
return resultat
def statistiques_client(dictionnaire, client):
"""Retourne les statistiques pour un client donné"""
if client not in dictionnaire:
return 0, 0, 0
prix = dictionnaire[client]
nb_commandes = len(prix)
prix_total = sum(prix)
prix_moyen = prix_total / nb_commandes if nb_commandes > 0 else 0
return nb_commandes, prix_total, prix_moyen
# Test
commandes = [
("Alice", "Stylo", 2.5),
("Bob", "Cahier", 3.0),
("Alice", "Gomme", 1.2),
("Charlie", "Règle", 1.8),
("Alice", "Cahier", 3.0),
("Bob", "Stylo", 2.5)
]
# Compression
compresse = compresser_commandes(commandes)
print("Commandes compressées par client:")
for client, prix in compresse.items():
print(f" {client}: {prix}")
# Statistiques pour Alice
nb, total, moyen = statistiques_client(compresse, "Alice")
print(f"\nStatistiques pour Alice:")
print(f" Nombre de commandes: {nb}")
print(f" Total des achats: {total:.2f} €")
print(f" Prix moyen: {moyen:.2f} €")
# Statistiques pour un client inexistant
nb, total, moyen = statistiques_client(compresse, "David")
print(f"\nStatistiques pour David: {nb} commandes, {total} €")
Exercice 4 : Filtrage et transformation avec lambda (2pts)
Énoncé :
À partir d'une liste de dictionnaires représentant des produits [{"nom": "A", "prix": 10, "stock": 5}, ...], utiliser des fonctions lambda avec filter() et map() pour :
- Filtrer les produits en rupture de stock (stock = 0)
- Créer une liste des noms des produits dont le prix est supérieur à un seuil
- Appliquer une réduction de 10% sur tous les produits dont le stock est > 10
Correction :
def gerer_produits(produits, seuil_prix=15):
# 1. Produits en rupture de stock
rupture = list(filter(lambda p: p["stock"] == 0, produits))
# 2. Noms des produits avec prix > seuil
noms_chers = list(map(lambda p: p["nom"],
filter(lambda p: p["prix"] > seuil_prix, produits)))
# 3. Appliquer réduction de 10% sur stock > 10
produits_avec_reduction = list(map(
lambda p: {**p, "prix": round(p["prix"] * 0.9, 2)} if p["stock"] > 10 else p,
produits
))
return rupture, noms_chers, produits_avec_reduction
# Test
catalogue = [
{"nom": "Stylo", "prix": 2.5, "stock": 15},
{"nom": "Cahier", "prix": 4.0, "stock": 0},
{"nom": "Sac", "prix": 25.0, "stock": 3},
{"nom": "Trousse", "prix": 8.5, "stock": 12},
{"nom": "Agenda", "prix": 12.0, "stock": 0}
]
rupture, chers, nouveau_catalogue = gerer_produits(catalogue, seuil_prix=10)
print("1. Produits en rupture:")
for p in rupture:
print(f" {p['nom']}")
print(f"\n2. Produits avec prix > 10€: {chers}")
print("\n3. Catalogue après réduction:")
for p in nouveau_catalogue:
print(f" {p['nom']}: {p['prix']}€ (stock: {p['stock']})")
Problème : Gestion d'une bibliothèque (8pts)
Partie A : Gestion des livres (4pts)
Données :
bibliotheque = [
("1984", "George Orwell", 1949, 8.99, 3),
("Le Petit Prince", "Antoine de Saint-Exupéry", 1943, 7.50, 5),
("Dune", "Frank Herbert", 1965, 12.99, 2),
("Fondation", "Isaac Asimov", 1951, 11.50, 4),
("Harry Potter", "J.K. Rowling", 1997, 15.99, 1)
]
# Format: (titre, auteur, année, prix, exemplaires)
1. Afficher les informations de chaque livre
print("=== INVENTAIRE DE LA BIBLIOTHÈQUE ===\n")
for livre in bibliotheque:
titre, auteur, annee, prix, exemplaires = livre
print(f"? {titre}")
print(f" Auteur: {auteur}")
print(f" Année: {annee}")
print(f" Prix: {prix:.2f} €")
print(f" Exemplaires: {exemplaires}")
print()
2. Créer une liste des livres récents (après 1950)
print("=== LIVRES PUBLIÉS APRÈS 1950 ===\n")
livres_recents = [livre for livre in bibliotheque if livre[2] > 1950]
for livre in livres_recents:
titre, auteur, annee, prix, exemplaires = livre
print(f"• {titre} ({annee}) - {auteur}")
3. Trouver le livre le plus cher et le moins cher
print("\n=== PRIX DES LIVRES ===\n")
# Livre le plus cher
livre_cher = max(bibliotheque, key=lambda x: x[3])
titre_cher, auteur_cher, annee_cher, prix_cher, ex_cher = livre_cher
print(f" Livre le plus cher: {titre_cher} - {prix_cher:.2f} €")
# Livre le moins cher
livre_pas_cher = min(bibliotheque, key=lambda x: x[3])
titre_pc, auteur_pc, annee_pc, prix_pc, ex_pc = livre_pas_cher
print(f"? Livre le moins cher: {titre_pc} - {prix_pc:.2f} €")
# Prix moyen
prix_moyen = sum(livre[3] * livre[4] for livre in bibliotheque) / sum(livre[4] for livre in bibliotheque)
print(f"? Prix moyen pondéré par stock: {prix_moyen:.2f} €")
4. Trier les livres par année de publication (du plus ancien au plus récent)
print("\n=== LIVRES TRIÉS PAR ANNÉE (ANCIEN → RÉCENT) ===\n")
livres_tries = sorted(bibliotheque, key=lambda x: x[2])
for livre in livres_tries:
titre, auteur, annee, prix, exemplaires = livre
print(f"{annee} - {titre} ({auteur})")
Partie B : Gestion des emprunts (4pts)
Données :
emprunts = {
"Alice": [("1984", "2024-01-15"), ("Dune", "2024-01-20")],
"Bob": [("Fondation", "2024-01-10")],
"Charlie": [("Harry Potter", "2024-01-05"), ("1984", "2024-01-12"), ("Le Petit Prince", "2024-01-18")],
"Diane": []
}
1. Fonction pour compter le nombre total d'emprunts
def total_emprunts(dictionnaire_emprunts):
total = 0
for emprunts_utilisateur in dictionnaire_emprunts.values():
total += len(emprunts_utilisateur)
return total
print("=== STATISTIQUES DES EMPRUNTS ===\n")
print(f"Nombre total d'emprunts: {total_emprunts(emprunts)}")
2. Fonction pour trouver le livre le plus emprunté
def livre_plus_emprunte(dictionnaire_emprunts):
compteur = {}
for emprunts_utilisateur in dictionnaire_emprunts.values():
for livre, date in emprunts_utilisateur:
if livre in compteur:
compteur[livre] += 1
else:
compteur[livre] = 1
if not compteur:
return None, 0
livre_max = max(compteur.items(), key=lambda x: x[1])
return livre_max
livre_pop, nb_emprunts = livre_plus_emprunte(emprunts)
print(f"Livre le plus emprunté: '{livre_pop}' ({nb_emprunts} fois)")
3. Fonction pour trouver l'utilisateur le plus actif
def utilisateur_plus_actif(dictionnaire_emprunts):
if not dictionnaire_emprunts:
return None, 0
utilisateur_max = max(dictionnaire_emprunts.items(),
key=lambda x: len(x[1]))
return utilisateur_max[0], len(utilisateur_max[1])
user_actif, nb_emprunts_user = utilisateur_plus_actif(emprunts)
print(f"Utilisateur le plus actif: {user_actif} ({nb_emprunts_user} emprunts)")
4. Fonction pour suggérer des livres à un utilisateur
def suggerer_livres(utilisateur, dictionnaire_emprunts, catalogue):
"""
Suggère des livres du même auteur que ceux déjà empruntés
"""
if utilisateur not in dictionnaire_emprunts:
return []
# Livres déjà empruntés par l'utilisateur
livres_empruntes = [livre for livre, date in dictionnaire_emprunts[utilisateur]]
if not livres_empruntes:
return []
# Trouver les auteurs des livres empruntés
auteurs_interets = set()
for livre in livres_empruntes:
for livre_catalogue in catalogue:
if livre_catalogue[0] == livre: # Si titre correspond
auteurs_interets.add(livre_catalogue[1]) # Ajouter l'auteur
break
# Suggérer d'autres livres de ces auteurs
suggestions = []
for livre in catalogue:
titre, auteur, annee, prix, exemplaires = livre
if auteur in auteurs_interets and titre not in livres_empruntes:
suggestions.append((titre, auteur, annee))
return suggestions
print("\n=== SUGGESTIONS DE LIVRES ===\n")
suggestions = suggerer_livres("Charlie", emprunts, bibliotheque)
print("Suggestions pour Charlie (aime Orwell et Herbet):")
for titre, auteur, annee in suggestions:
print(f" • {titre} ({auteur}, {annee})")
5. Fonction pour calculer la valeur totale des livres empruntés
def valeur_emprunts_utilisateur(utilisateur, dictionnaire_emprunts, catalogue):
"""
Calcule la valeur totale des livres empruntés par un utilisateur
"""
if utilisateur not in dictionnaire_emprunts:
return 0
# Créer un dictionnaire des prix des livres
prix_livres = {livre[0]: livre[3] for livre in catalogue}
valeur_totale = 0
for livre, date in dictionnaire_emprunts[utilisateur]:
if livre in prix_livres:
valeur_totale += prix_livres[livre]
return valeur_totale
print("\n=== VALEUR DES EMPRUNTS ===\n")
for utilisateur in emprunts.keys():
valeur = valeur_emprunts_utilisateur(utilisateur, emprunts, bibliotheque)
print(f"{utilisateur}: {valeur:.2f} € de livres empruntés")
Fin de l'examen