S'entraîner...
Erreurs de syntaxe
Copiez les 2 codes suivants, collez-le dans un éditeur Python puis exécutez-les.
Répondez ensuite aux questions.
Question
def val_abs(a, b):
if a-b > 0:
return a-b
else
return b-a
Question 1 : Que signifie l'erreur signalée par la console ?
Question 2 : Corrigez ensuite cette erreur.
Solution
File "val_abs.py", line 10
else
^
SyntaxError: invalid syntax
Une erreur de syntaxe est signalée au niveau du else : il manque les deux-points « : ».
Question
def multi(a, b):
while b > 0:
resultat = resultat + a
b = b-1
return resultat
Question 1 : Effectuez un appel à la fonction multi(). Que signifie l'erreur signalée par la console ?
Question 2 : Corrigez ensuite cette erreur.
Indice
Effectuer un appel de la fonction signifie que, dans le programme principal (en dehors de la fonction donc, on appelle multi() avec 2 arguments à l'intérieur correspondant aux 2 paramètres de la fonction définie multi(a, b).
Solution
Explication de l'erreur
Traceback (most recent call last):
File "multi.py", line 14, in <module>
multi(3, 7)
File "multi.py", line 9, in multi
resultat = resultat + a
UnboundLocalError: local variable 'resultat' referenced before assignment
Une erreur de syntaxe est signalée en ligne 3 : la variable d'accumulation resultat est utilisée sans avoir été initialisée.
Solution
Correction du programme
def multi(a, b):
resultat = 0
while b > 0:
resultat = resultat + a
b = b-1
return resultat
Plan de tests
Sur votre cahier, réaliser les 2 tableaux 'plan de tests' des 2 fonctions suivantes et renseignez-le. Vérifier ensuite avec la correction.
Question
La fonction meme_signe(a, b) doit renvoyer True lorsque a et b sont des entiers de même signe et False dans le cas contraire. On considère que 0 est positif et négatif.
Établir un plan de tests pour cette fonction.
cas | a | b | valeur renvoyée attendue |
---|---|---|---|
_ | _ | _ | _ |
_ | _ | _ | _ |
_ | _ | _ | _ |
_ | _ | _ | _ |
_ | _ | _ | _ |
Indice
a et b peuvent avoir 2 types de signes... 0 est aussi un cas particulier à prendre en compte lors du test.
Solution
cas | a | b | valeur renvoyée attendue |
---|---|---|---|
a > 0 et b > 0 | 2 | 4 | True |
a < 0 et b > 0 | -2 | 4 | False |
a > 0 et b < 0 | 6 | -5 | False |
a < 0 et b < 0 | -4 | -2 | True |
L'un des deux vaut 0 | 0 | -3 | True |
Question
La fonction somme_impair(n) doit renvoyer la somme des n premiers entiers impairs consécutifs.
Établir un plan de tests pour cette fonction.
cas | n | valeur renvoyée attendue |
---|---|---|
_ | _ | _ |
_ | _ | _ |
_ | _ | _ |
Solution
Un plan de test possible :
cas | n | valeur renvoyée attendue |
---|---|---|
aucun | 0 | 0 |
un | 1 | 1 |
plusieurs | 4 | 1+3+5+7 = 16 |
Utilisation du module doctest de Python
Le but de cette partie est de mettre en œuvre le module doctest sur 2 fonctions différentes : somme_impair() et contient_e().
Question
Pour mettre en œuvre ce plan de tests de la question précédente, on rédige le code de la fonction, suivi du programme principal qui contient l'appel au module doctest :
def somme_impair(n):
"""
n - int, entier strictement positif
Sortie: int - somme des n premiers entiers impairs
>>> somme_impair(0)
0
>>> somme_impair(1)
1
>>> somme_impair(4)
16
"""
s = 0
for i in range(1, n):
s = s + 2*i+1
return s
##----- Mise en oeuvre des tests -----##
if __name__ == "__main__":
import doctest
doctest.testmod()
Question 1 : Copiez-collez et exécutez ce code. Tous les tests sont-ils passés ?
Question 2 : Dans le cas où des tests ne sont pas passés, corrigez le code pour qu'il ne contienne plus d'erreur de logique.
Solution
Solution question 1
Il y a bien une erreur de logique dans notre code puisque notre console affiche cette dernière ligne :
***Test Failed*** 2 failures.
Solution
Solution question 2
La boucle n'est pas parcourue n fois mais seulement n-1 fois. Il faut donc modifier le paramètre de la fonction range() à la ligne 13. Avec cette correction, plus rien ne doit être signalé dans la console.
Question
On considère la fonction contient_e() qui prend en paramètre une chaîne de caractères et qui renvoie un booléen de valeur True si la chaîne contient le caractère 'e' et False sinon.
def contient_e(mot):
"""
mot – str
Sortie: bool – True si mot contient 'e', False sinon
>>> .............................................................
.............................................
>>> .............................................................
.............................................
"""
..................................................................
..................................................................
..................................................................
..................................................................
..................................................................
##----- Mise en oeuvre des tests -----##
if __name__ == '__main__' :
import doctest
doctest.testmod()
Question 1 : Complétez les lignes 5 à 8 du code ci-dessus qui contient deux tests à réaliser dans la console par le module doctest.
Question 2 : Complétez la définition de la fonction contient_e() afin qu'elle respecte ses spécifications puis testez votre code.
Indice
Question 1 : on pourra utiliser 2 chaînes de caractères différentes...
Question 2 : parcourons notre chaîne avec une boucle...
Solution
Question 1 : Docstrings
Il faut un test pour lequel la valeur renvoyée est True, un autre pour False :
def contient_e(mot):
"""
mot – str
Sortie: bool – True si mot contient 'e', False sinon
>>> contient_e('abcd')
False
>>> contient_e('Exemple')
True
"""
Solution
Question 2 : code de la fonction
On parcourt chaque caractère. Dès qu'on en trouve un qui est un 'e', on renvoie True.
Si on les a tous parcourus et qu'on n'a trouvé aucun 'e', alors on renvoie False.
def contient_e(mot):
"""
mot – str
Sortie: bool – True si mot contient 'e', False sinon
>>> contient_e('abcd')
False
>>> contient_e('Exemple')
True
"""
for carac in mot:
if carac == 'e':
return True
return False
##----- Mise en oeuvre des tests -----##
if __name__ == '__main__' :
import doctest
doctest.testmod()
Un seconde code plus simple : L'opérateur in est bien plus efficace car il répond directement à cette question :
def contient_e(mot):
"""
mot – str
Sortie: bool – True si mot contient 'e', False sinon
>>> contient_e('abcd')
False
>>> contient_e('Exemple')
True
"""
return 'e' in mot
##----- Mise en oeuvre des tests -----##
if __name__ == '__main__' :
import doctest
doctest.testmod()
Assert : protéger son programme
On considère à nouveau la fonction contient_e() étudiée précédemment.
Question
Question 1 : Utilisez une assertion pour tester que le paramètre saisi est bien une chaîne de caractères.
def contient_e(mot):
"""
mot – str
Sortie: bool – True si mot contient 'e', False sinon
"""
assert ..............................................
if 'e' in mot:
return True
else:
return False
Question 2 : Testez ensuite ce code dans la console :
>>> contient_e('abcd')
>>> contient_e(17)
Solution
Question 1 :
def contient_e(mot):
"""
mot – str
Sortie: bool – True si mot contient 'e', False sinon
"""
assert type(mot) == str, "Le paramètre mot doit être une chaîne de caractères."
if 'e' in mot:
return True
else:
return False
Avec les f-strings (Python 3.6), on peut aller un peu plus loin en faisant :
assert isinstance(mot, str), f"Le paramètre {mot} doit être une chaîne de caractères."
Solution
Question 2 :
>>> contient_e('abcd')
False
>>> contient_e(17)
File "contient_e.py", line 13, in contient_e
assert type(mot) == str, "Beta, c'est du string"
AssertionError: Beta, c'est du string
ou avec les fstrings :
assert isinstance(mot, str), f"Le paramètre {mot} doit être une chaîne de caractères."
AssertionError: Le paramètre 17 doit être une chaîne de caractères.
Erreurs à connaître
Dans ces exercices, votre travail consiste à :
reconnaître les erreurs les plus classiques ;
comprendre ce qu'elles signifient ;
les corriger.
Question
Copiez, collez le code ci-dessous dans un éditeur :
def erreur1(a, b):
"""
a, b – int ou float
Sortie: int ou float – a-b si a-b est positif, b-a sinon
"""
if a > b:
return a-b
else:
return b-a
Exécutez ce code. Que signifie l'erreur signalée ?
Corrigez ce code puis testez-le.
Question
Copiez, collez le code ci-dessous dans un éditeur :
def erreur2(texte):
"""
texte – str
Sortie: str – Le texte dans lequel les caractères sont écrits dans l'autre sens
"""
for carac in texte:
reponse = carac + reponse
return reponse
Exécutez ce code. Une erreur est-elle signalée ?
Effectuez l'appel :
erreur2('exemple')
Que signifie l'erreur signalée ?
Corrigez ce code puis testez-le à nouveau.
Question
Copiez, collez le code ci-dessous dans un éditeur :
def erreur3(texte):
"""
texte – str
Sortie: str – Le texte dans lequel on ne conserve qu'une lettre sur deux
"""
reponse = ""
for i in range(0, len(texte), 2):
reponse = reponse + texte(i)
return reponse
Exécutez ce code. Une erreur est-elle signalée ?
Effectuez un appel à la fonction erreur3().
Que signifie l'erreur signalée ?
Corrigez ce code puis testez-le à nouveau.
Question
Copiez, collez le code ci-dessous dans un éditeur :
def erreur4(texte):
"""
texte – str
Sortie: str – Le texte dans lequel le premier et le dernier caractère sont échangés
"""
reponse = texte[len(texte-1)]
for i in range(1, len(texte-1)):
reponse = reponse + texte[i]
reponse = reponse + texte[0]
return reponse
Exécutez ce code. Une erreur est-elle signalée ?
Effectuez un appel à la fonction erreur4().
Que signifie l'erreur signalée ?
Corrigez ce code puis testez-le à nouveau.
Question
Copiez, collez le code ci-dessous dans un éditeur :
def erreur5(texte):
"""
texte – str
Sortie: str – Les caractères de texte ayant pour indice 1, 2, 4, 8, 16, etc...
"""
reponse = ''
indice = 1
while indice <= len(texte):
reponse = reponse + texte[indice]
indice = indice*2
return reponse
Exécutez ce code. Une erreur est-elle signalée ?
Effectuez plusieurs appels différents à la fonction erreur5() jusqu'à l'apparition d'une erreur.
Que signifie l'erreur signalée ?
Attention, respectez bien les spécifications : le paramètre d'appel DOIT être une chaîne de caractères.
Corrigez ce code puis testez-le à nouveau.
Question
Copiez, collez le code ci-dessous dans un éditeur :
def erreur6(a, b):
"""
a, b – int, entiers strictement positifs
Sortie: int – pgcd des entiers a et b
"""
while b >= 0:
reste = a%b
a = b
b = reste
return b
Exécutez ce code puis effectuez des appels à la fonction erreur6() jusqu'à l'apparition d'une erreur.
Corrigez ce code puis testez-le à nouveau.
Un programme testé et vérifié !
On considère la fonction factorielle() définie par :
def factorielle(n):
"""
n – int, entier strictement positif
Sortie: int – le produit 1×2×3×...×n.
"""
f = 0
for i in range(n):
f = f*i
return f
Question
Question 1 : Insérez un plan de test dans le docstring de cette fonction. On s'intéressera aux cas particuliers de la fonction factorielle.
Question 2 : Ajoutez une assertion afin que le paramètre n respecte les spécifications.
Question 3 : Exécutez ce code afin qu'il soit testé automatiquement par le module doctest.
Vérifiez que les tests ne « passent » pas.
Question 4 : Insérez des print() dans ce code pour suivre l'évolution des variables puis corrigez ce code.