Specifications
Abstraction
Pour utiliser (appeler) une fonction, on n'a pas besoin de comprendre comment la fonction calcule son résultat, seulement de savoir quel résultat elle retourne et quels sont ses paramètres.
Celà permet d'effectuer simplement des calculs très compliqués par le biais de fonctions ecrites par d'autres programmeurs.
Python fournis un certain nombre de fonction sous forme de modules. Pour utiliser de telles fonctions, on doit dire à Python de les importer, avec la syntaxe suivante :
Où nom_module est le nom d'un module, et nom_fonction le nom d'une fonction de ce module
Le module random
fournit des fonctions qui permettent de générer des valeurs pseudo aléatoires1. Entre autres, la fonction randint
qui permet de générer un entier aléatoire entre une petite valeur (incluse) et une grande valeur (exclue).
Ecrivez l'exemple ci-dessus dans la partie éditeur, executez le script, et calculez la valeur de l'expression suivante plusieurs fois à l'aide de la console Python :
Cet appel retourne un entier aléatoire entre 1 et 6!
Vous devriez voir le résultat changer à chaque appel ou presque, par exemple :
Vous avez utilisé la fonction randint
, et pourtant, vous n'avez aucune idée de comment elle produit son résultat. Son fonctionnement dépasse même largement le cadre d'un cours de math de seconde ! Ce mécanisme est ce qu'on appelle une abstraction, c'est à dire que l'on ne garde que ce qui nous intéresse (le résultat), et qu'on n'a pas besoin de s'intéresser au reste (la méthode pour obtenir le résultat).
l'abstraction est une notion centrale en programmation. Toutefois, dans ce cours, nous ne travailleront quasiment qu'avec des abstractions à l'aide de fonctions.
docstrings
Parfois, le nom d'une fonction et le nom de ses paramètres est insuffisant pour exprimer précisément ce que la fonction calcule, ou comment bien l'utiliser. Dans ce cas là, Python nous propose d'ajouter une docstring. C'est une chaîne de caractères un peu spéciale qu'on met juste sous la ligne def
d'une fonction quand on la définit, et qui permet d'expliquer en français (ou en anglais) ce que la fonction fait.
Exercice
Proposez une docstring pour la fonction irradiance
que nous avons défini au chapitre précédent.
Quelques précisions à donner :
- r
est en millions de kms
- C'est l'irradiance solaire
Cette extension est facultative, a faire uniquement si vous cherchez un peu de défi ou aimez les maths et la physique.
Si on passe certaines valeurs comme paramètre r
, la fonction risque de renvoyer une valeur erronnée. Précisez ces restrictions dans la docstring.
r
est utilisée comme diviseur, il ne peut donc mathématiquement pas être zéro, sans quoi le calcul n'a aucun sens (on ne divise pas par zéro).r
est une distance. Or, une distance négative fait rarement sens, on veut donc préciser que cette distance est toujours positive.
La docstring, le nom d'une fonction et le nom de ses paramètres constituent la spécification d'une fonction. La spécification est simplement l'explication de ce que la fonction fait, sans expliquer comment elle le fait. Le code de la fonction, qui est en quelques sortes l'opposé de la spécification, s'appelle alors l'implémentation. La spécification est plus simple à lire que le code, et permet l'usage d'une fonction même si on n'en comprends pas le code.
Remarque
Dans ce cours, la spécification d'une fonction se limitera aux trois éléments mentionnés plus haut. Dans la pratique elle peut prendre de nombreuses formes : ce peut être un texte en français à part du code, des schémas, des images, un texte dans un langage spécial, ...
Tests
Souvent, quand on écrit la spécification d'une fonction, on veut vérifier que son implémentation corresponds. Pour ça, on va souvent écrire des tests automatiques. Le principe est d'écrire des sortes de petits programmes qui vont tester si une fonction marche, et on va donc laisser l'ordinateur faire le test.
Il existe de nombreux outils pour tester des fonctions en Python. Nous allons utiliser la plus directe, les doctests. C'est un module qui permet d'écrire dans la docstring du code comme si on l'écrivait en console, et aussi l'affichage correspondant, et le module executera les exemples automatiquement et vérifiera leur sortie.
Se met dans la docstring, séparé du dessus et dessous par des lignes vides.
Chaque bloc expression - attendu est un test.
Pour activer les tests automatiques, copiez-collez l'exemple précédent dans la partie éditeur et ajoutez les lignes suivantes en bas :
Nous verrons plus loin dans le cours ce qu'elles veulent dire. Executez. Et ... rien ne se passe...
C'est normal : la fonction carre
est correcte, et donc elle passe tous les tests.
Un test pour une fonction est généralement très simple. On donne des valeurs à la fonction, et on vérifie que le résultat est le bon.
Modifions-la pour la "casser":
Changez la ligne
en
Re-executez. Vous devriez voir apparaître le rapport de tests:
Les lignes 18, 19 et 20 sont un résumé :
Qui nous apprends que 2 tests sur 3 ont échoués.
Les blocs au dessus, séparés par des lignes de *
, sont chacun un rapport d'échec d'un test. Par exemple :
Etudions ce rapport :
Indique que le test qui a échoué est ligne 5 du fichier.
Rappelle l'expression qui a été testée. Ici, carre(4)
.
Rappelle la valeur que l'on attendait de l'appel de la fonction. Ici, 16
.
Rappelle la valeur réellement obtenu. Ici, 4
.
Ecrire un test pour une fonction est simple. On l'appelle avec des valeurs choisies, et on vérifie que la valeur retournée est la bonne.
Exercice
Ecrivez quelques doctests pour la fonction suivante, puis executez-les. Modifiez la fonction de manière à faire rater les tests :
Si vous n'avez pas tous les cas de tests ci dessous, pas de panique, l'important est d'avoir écrit quelques tests.
On peut écrire les tests à deux moments :
- Après avoir implémenté la fonction et vérifié manuellement qu'elle est correcte. On peut alors copier-coller directement des lignes de la console Python. Les tests serviront alors à vérifier que la fonction ne sera pas "cassée" par des modifications future.
- Avant d'implémentater la fonction. Les tests sont alors plus compliqués à écrire, puisqu'il faut faire les calculs à la main, mais ils serviront aussi à vérifier que la fonction a été bien implémentée.
Exercice
Ecrivez quelques tests pour la fonction irradiance
.
def irradiance(r):
"""Calcule la valeur de l'irradiance solaire en watts par mètres carrés,
r est la distance au soleil, en millions de kilomètres
>>> irradiance(20)
76612.70410000002
>>> irradiance(150)
1362.0036284444443
>>> irradiance(120)
2128.1306694444447
>>> irradiance(0.5)
122580326.56
"""
return (5535.8/r)**2
-
On parle de pseudo aleatoire, parce que les valeurs générées ressemblent à des valeurs aléatoires, mais ne le sont pas à proprement parler. ↩