Anticiper les erreurs classiques
- Fiche de cours
- Quiz
- Profs en ligne
- Videos
- Application mobile
- Mettre en place des automatismes pour anticiper les erreurs de programmation.
- S’assurer, étape par étape, qu’un programme s’exécute correctement.
- Il est important de bien définir les éléments de la résolution du problème étudié.
- Mettre en place de bonnes pratiques de rédaction des codes permet d’éviter des erreurs.
- Bien nommer les variables permet de décrire ce que fait le code.
- L’utilisation du mot-clé assert ou de la fonction print() peut permettre de vérifier l’exécution d’un code.
- Écrire une fonction en Python. (1re)
- Tester un programme. (1re)
- Étudier la terminaison et la correction d’un programme. (1re)
Lorsque l’on veut écrire un programme informatique, on souhaite en réalité résoudre un problème, répondre à un exercice ou réaliser un projet.
Il faut au préalable circonscrire précisément ce que l’on veut faire et ce que l’on attend du programme.
Il faut pour cela :
- définir précisément la ou les données en entrée, notamment leur nature ;
- définir précisément la ou les données en sortie, notamment leur nature ;
- définir les différentes étapes qui permettent de résoudre le problème et notamment les données intermédiaires utilisées ;
- déterminer un ou des jeux de tests, c’est-à-dire des données en entrée pour lesquelles on connait les résultats en sortie afin de tester le code.
On peut ainsi anticiper les éventuelles erreurs de raisonnement et de structure.
D’un point de vue pratique, lorsqu’un programme est à réaliser, il est courant de vouloir coder directement sur ordinateur. C’est possible pour des problèmes relativement simples.
Si un problème est plus complexe, il est cependant parfois indispensable d’organiser sa résolution avant de passer sur machine car cela permet de gagner en efficacité. Cela passe souvent par un travail écrit qui permet de tout planifier.
Si on souhaite écrire une fonction maximum(a, b, c) qui prend pour arguments trois nombres a, b et c, et qui renvoie le plus grand des trois nombres, on constate vite qu’il y a plusieurs cas possibles. Les déterminer à l’avance permet de comprendre comment le coder.
On peut ainsi écrire le code suivant.
Python | Explication |
def maximum(a, b, c): | |
if a < b and b < c: return c |
Si a est plus petit que b et si b est plus petit que c, le plus grand élément est c. |
elif a < c and c < b: return b |
Si a est plus petit que c et si c est plus petit que b, le plus grand élément est b. |
elif b < c and c < a: return a |
Si b est plus petit que c et si c est plus petit que a, le plus grand élément est a. |
elif b < a and a < c: return c |
Si b est plus petit que a et si a est plus petit que c, le plus grand élément est c. |
elif c < b and b < a: return a |
Si c est plus petit que b et si b est plus petit que a, le plus grand élément est a. |
elif c < a and a < b: return b |
Si c est plus petit que a et si a est plus petit que b, le plus grand élément est b. |
De manière plus formelle, le moyen le plus sûr pour anticiper les erreurs est d’écrire un algorithme de résolution du problème, d’en étudier la terminaison, puis la correction.
On se prémunit ainsi de toute erreur, bien que cela puisse s’avérer parfois complexe et chronophage. Toutefois, avoir en tête ces trois étapes fondamentales de l’algorithmique est important même si on ne le formalise pas strictement.
- Écriture de l’algorithme
- Terminaison de l’algorithme
- Correction de l’algorithme
En programmation, il est essentiel de bien nommer les variables car c’est une bonne manière de décrire ce que fait le code : cela en facilite la rédaction et la lecture. On peut ainsi anticiper des erreurs de programmation grâce à la description du code apportée par un nommage pertinent des variables.
La fonction func1(a) prend pour argument un tableau de nombres a et retourne l’indice de son plus grand élément.
b = 0
for i in range(len(a)):
if a[i] > a[b]:
b = i
return b
maxi = 0
for i in range(len(tab)):
if tab[i] > tab[maxi]:
maxi = i
return maxi
Le code de la fonction func1(a) est peu lisible. Sans indications, il faut une analyse précise de son code pour comprendre la nature des variables a et b.
En revanche, le code de la fonction func2(a) donne des informations sur la variable tab qui semble être un tableau et la variable maxi qui semble référencer un maximum ; tab[maxi] précise que ce maximum est un indice.
Le meilleur nommage des variables du code de la fonction func2(tab) donne davantage de sens.
Une bonne pratique en programmation est de s’habituer à normaliser les noms de variable.
Il existe deux manières principales pour éviter les erreurs de nommage : le camelCase et le snake_case.
L’indice de masse corporel (IMC) d’une personne est donné par la formule IMC = masse/taille² où la masse est exprimée en kg et la taille en mètre.
Voici deux fonctions imc qui permettent de calculer l’IMC d’une personne, l’une en camelCase, l’autre en snake_case.
camelCase |
def imc(maMasse,
maTaille):
return maMasse/maTaille**2 |
snake_case |
def imc(ma_masse,
ma_taille):
return ma_masse/ma_taille**2 |
Un code inapproprié consisterait à
mélanger les deux écritures et
même à en utiliser d’autres, plus
baroques.
Par exemple, on pourrait avoir un code fonctionnel
mais moins lisible comme ceci :
def imc(Ma_masse,
Mataille):
return Ma_masse/Mataille**2
Une autre bonne pratique en programmation est de normaliser l’utilisation des espaces, ce qui rend le code plus lisible et permet d’éviter certaines erreurs.
+, -, =, ==, <, <=, >, >= | espace avant et après |
:, , (virgule) | espace après mais pas avant |
[, {, ( | pas d'espace après |
], }, ) | pas d’espace avant |
La fonction minimum(tab) prend en argument tab un tableau de nombres et renvoie son minimum.
def minimum(tab ):
n = len( tab)
mini= tab[ 0 ]
for i in range(1 ,n ):
if mini> tab[ i] :
mini =tab[i ]
return mini
Ce code fonctionne mais est difficilement lisible.
Par exemple, tab[ i] et tab[i ]
référencent le même
élément. La différence
d’écriture rend moins
compréhensible ce code.
Un usage correct des espaces donne le code suivant.
def minimum(tab):
n = len(tab)
mini = tab[0]
for i in
range(1, n):
if mini > tab[i]:
mini = tab[i]
return mini
Il est ainsi possible de vérifier des propriétés importantes d’un programme écrit ou en cours d’écriture.
On souhaite écrire un code reste(a, b) qui permette d’obtenir le reste de la division euclidienne de a par b (a > b).
On sait que deux assertions sont fondamentales :
- a doit être plus grand que b ;
- le reste doit être strictement plus petit que b.
Le code suivant permet d’obtenir le reste tout en vérifiant les assertions précédentes.
def reste(a, b):
assert a > b , "a doit
être plus grand que b"
r = a
while r > b:
r = r - b
assert r < b, "r doit être
plus petit que b"
return
r
En Python, lorsqu’un code ne fonctionne pas comme on le souhaite ou lorsque l’on a un doute sur sa conception, la fonction print() peut permettre d’afficher des étapes intermédiaires de l'exécution du code et ainsi de vérifier s’il y a un problème ; s’il y a un problème, la fonction print() indique à quel moment il se situe.
Si l’on veut coder l’algorithme de tri par sélection du minimum, il peut être utile d’afficher au fur et à mesure de son exécution l’état du tableau à trier.
Voici le code du tri par sélection du minimum.
def tri_selection(tab):
n = len(tab)
for i in
range(0, n-1):
mini = i
for j in range(i+1, n):
if tab[j] < tab[mini]:
mini = j
if mini != i:
tab[i], tab[mini] = tab[mini], tab[i]
Afin de vérifier si cette fonction fait ce que l’on veut, on peut utiliser la fonction print().
def tri_selection(tab):
print("tab = ",
tab)
n = len(tab)
for i in range(0, n-1):
print("Pour i = ",
i)
mini = i
for j in range(i+1, n):
if tab[j] < tab[mini]:
mini = j
if mini != i:
tab[i], tab[mini] = tab[mini], tab[i]
print("tab = ", tab)
Avec Python Tutor, cela donne le résultat suivant.
Il est ainsi possible de vérifier la bonne exécution de chaque étape de l’algorithme.
Vous avez obtenu75%de bonnes réponses !