Modularité - Correction
Modulariser un code
Problèmes identifiés et solutions
| Problème | Solution |
|---|---|
| Aucune fonction ! | Diviser le code en fonctions : 1 fonction = 1 seule tache "élémentaire" |
| Redondance du code : le même code se retrouve à l'identique à plusieurs endroits du programme ( affichage du menu, calcul de la moyenne). | Factoriser le code, de façon à ce qu'il soit plus lisible, et surtout plus facilement maintenable |
| Utilisation de variables globales ( les tableaux eleves et notes, modifiées en n'importe quel point du programme. | Préférer le passage d'argument(s) en paramètre(s) des fonctions, et le renvoi de résultat(s) lors de l'appel de celles-ci. |
Liste des fonctions/programme principal
| Fonctions | Programme principal |
|---|---|
|
|
Pas de print ( sauf exception, comme ici dans l'affichage du menu ) ni de input dans les fonctions,
ce n'est pas leur rôle d'afficher ou de demander des données à l'utilisateur ( cela se fait dans le programme principal ).
Penser à la documentation du code (docstring, annotations de type, etc...), mais c'est un autre problème.
Proposition de code corrigé
def afficher_menu():
"""Affiche le menu principal.
Entrées : aucune
Sorties : aucune
"""
print("\n=== Gestion des élèves et des notes ===")
print("1. Ajouter un élève")
print("2. Ajouter une note à un élève")
print("3. Calculer la moyenne d'un élève")
print("4. Afficher la moyenne de la classe")
print("5. Afficher l'élève avec la meilleure moyenne")
print("6. Quitter")
def ajouter_eleve(nom, eleves, notes):
"""Ajoute un élève au tableau des élèves, et crée un tableau vide pour ses notes.
Entrées : nom (str) = le nom de l'élève à ajouter
eleves (list) = le tableau des élèves
notes (list) = le tableau des notes
Sorties : les tableaux 'eleves' et 'notes' modifiés
"""
eleves.append(nom)
notes.append([])
return eleves, notes
def ajouter_note(nom, eleves, notes, nouvelle_note):
"""Ajoute une note à un élève.
Entrées : nom (str) = le nom de l'élève
eleves (list) = le tableau des élèves
notes (list) = le tableau des notes
nouvelle_note (float) = la nouvelle note à ajouter
Sorties : le tableau 'notes' modifié (list)
"""
indice = eleves.index(nom)
notes[indice].append(note)
return notes
def calculer_moyenne(notes):
"""Calcule la moyenne d'une liste de notes.
Entrées : notes (list) = un tableau de notes
Sortie : la moyenne des notes (float)
"""
if len(notes) == 0: # si aucune note dans la liste
return None
return sum(notes) / len(notes)
def moyenne_eleve(nom, eleves, notes):
"""Calcule et affiche la moyenne des notes d'un élève.
Entrées : nom (str) = le nom de l'élève
eleves (list) = le tableau des élèves
notes (list) = le tableau des notes
Sortie : la moyenne des notes (float)
"""
indice = eleves.index(nom)
moyenne = calculer_moyenne(notes[indice])
return moyenne
def moyenne_classe(notes):
"""Calcule et affiche la moyenne de la classe.
Entrées : notes (list) = le tableau de notes
Sortie : la moyenne des notes (float)
"""
toutes_les_notes = [note for liste_notes in notes for note in liste_notes]
moyenne = calculer_moyenne(toutes_les_notes)
return moyenne
def meilleur_eleve(eleves, notes):
"""Trouve et affiche l'élève avec la meilleure moyenne.
Entrées : eleves (list) = le tableau des élèves
notes (list) = le tableau des notes
Sortie : le nom du meilleur élève (str) et sa moyenne (float)
"""
meilleur_eleve = ""
meilleure_moyenne = -1
for i in range(len(eleves)):
moyenne = calculer_moyenne(notes[i])
if moyenne is not None:
if moyenne > meilleure_moyenne:
meilleure_moyenne = moyenne
meilleur_eleve = eleves[i]
return meilleur_eleve, meilleure_moyenne
# Programme principal
eleves = ["Alice", "Bob", "Charlie"]
notes = [[12, 15, 10], [14, 13, 16], [11, 12, 9]]
while True:
afficher_menu()
choix = input("Entrez votre choix (1-6) : ")
if choix == "1":
nom = input("Nom du nouvel élève ?")
eleves, notes = ajouter_eleve(nom, eleves, notes)
print("Nouveau tableau des élèves : ", eleves)
elif choix == "2":
nom = input("Nom de l'élève ?")
note = float(input("Note à ajouter ?"))
notes = ajouter_note(nom, eleves, notes, note)
print("Nouveau tableau des notes : ", notes)
elif choix == "3":
nom = input("Nom de l'élève ?")
moyenne = moyenne_eleve(nom, eleves, notes)
print("La moyenne de l'élève", nom, "est", moyenne)
elif choix == "4":
moyenne = moyenne_classe(notes)
print("La moyenne de la classe est", moyenne)
elif choix == "5":
eleve = meilleur_eleve(eleves, notes)
print("Le meilleur élève est :", eleve[0], "avec une moyenne de", eleve[1])
elif choix == "6":
print("Au revoir !")
break
else:
print("Choix invalide. Veuillez entrer un nombre entre 1 et 6.")
Code du module modultab
def maximum(t):
"""Renvoie la valeur maximale dans le tableau.
@param : t = tableau de valeurs (list)
@return : la valeur maximale dans t
"""
assert isinstance(t, list), "L'argument 't' doit être un tableau."
assert len(t) != 0, "Le tableau ne peut pas être vide."
maxi = t[0]
for elt in t:
if elt > maxi:
maxi = elt
return maxi
def minimum(t):
"""Renvoie la valeur minimale dans le tableau.
@param : t = tableau de valeurs (list)
@return : la valeur minimale dans t
"""
assert isinstance(t, list), "L'argument 't' doit être un tableau."
assert len(t) != 0, "Le tableau ne peut pas être vide."
mini = t[0]
for elt in t:
if elt < mini:
mini = elt
return mini
def somme(t):
"""Renvoie la somme des élément d'un tableau.
@param : t = tableau de valeurs (list)
@return : la somme des éléments de t
"""
assert isinstance(t, list), "L'argument 't' doit être un tableau."
assert len(t) != 0, "Le tableau ne peut pas être vide."
s = 0
for elt in t:
s += elt
return s
def produit(t):
"""Renvoie le produit des élément d'un tableau.
@param : t = tableau de valeurs (list)
@return : le produit des éléments de t
"""
assert isinstance(t, list), "L'argument 't' doit être un tableau."
assert len(t) != 0, "Le tableau ne peut pas être vide."
p = 1
for elt in t:
p *= elt
return p
def longueur(t):
"""Renvoie le nombre d'éléments dans un tableau.
@param : t = tableau de valeurs (list)
@return : le nombre d'élément(s) dans t (int)
"""
assert isinstance(t, list), "L'argument 't' doit être un tableau."
n = 0
for elt in t:
n += 1
return n
def moyenne(t):
"""Renvoie la moyenne des élément d'un tableau.
@param : t = tableau de valeurs (list)
@return : la moyenne des éléments de t (float)
"""
assert isinstance(t, list), "L'argument 't' doit être un tableau."
assert len(t) != 0, "Le tableau ne peut pas être vide."
s = 0
for elt in t:
s += elt
return s / longueur(t)
def inverse(t):
"""Renvoie un nouveau tableau, avec les éléments dans l'ordre inverse de celui passé en paramètre.
@param : t = tableau de valeurs (list)
@return : un nouveau tableau, avec les éléments en ordre inverse (list)
"""
assert isinstance(t, list), "L'argument 't' doit être un tableau."
nouveau = []
for elt in t:
nouveau = [elt] + nouveau
return nouveau
def tri(t, reverse = False):
"""Tri en place un tableau avec l'algorithme de tri par sélection.
@param : t = tableau de valeurs (list)
@param: ordre = booléen indiquant l'ordre de tri : False = ordre croissant (par défaut), True = ordre décroissant
@return : le tableau trié (list)
"""
assert isinstance(t, list), "L'argument 't' doit être un tableau."
for i in range(len(t)-1):
ech = i
for j in range(i+1, len(t)):
if reverse:
if t[j] > t[ech]:
ech = j
else:
if t[j] < t[ech]:
ech = j
if ech != i:
t[i], t[ech] = t[ech], t[i]
return t
if __name__ == '__main__':
# tests du module
t = [12, 1, 5, 63, 78, 4, 51, 32, 23, 7, 19, 45]
print(maximum(t))
print(minimum(t))
print(somme(t))
print(produit(t))
print(longueur(t))
print(moyenne(t))
print(inverse(t))
tri(t)
print(t)
tri(t, reverse=True)
print(t)
Quelques remarques
- noter la façon utilisée ici pour indiquer dans la docstring des fonctions la nature des paramètres et des valeurs de retour :
@param : indique le rôle, le type,... d'un paramètre @return : indique la nature, le type,... d'une valeur de retour - bien retenir que, dans une assertion, on teste la condition qui doit être vraie.
- la fonction
isinstance(variable, type)renvoie un booléen indiquant si une variable est d'un type donné ou non. - on peut indiquer des valeurs par défaut pour certains paramètres dans la définition d'une fonction, comme par exemple ici dans la fonction
tri(ligne 93), dans laquelle on donne au paramètre reverse la valeur par défautFalse( = tri par ordre croissant).
On appelle paramètre nommé un paramètre avec une valeur par défaut : l'utilisateur du module n'est alors pas obligé de lui passer une valeur en argument lors de l'appel de la fonction, le code utilisera la valeur par défaut; par contre, il doit indiquer le nom de ce paramètre au cas où il l'utilise lors de cet appel : la valeur passée remplace alors celle par défaut .
A noter que, dans la liste des paramètres d'une fonction, les paramètres nommés doivent être toujours placés après les paramètres non nommés.