Les fonctions#
À faire
Synchroniser avec Semaine4/01-fonctions.md; notamment la MySTification des exercices
Documentation d’une fonction#
Lorsqu’on écrit une fonction, est important de la documenter, c’est-à-dire de fournir des informations claires et précises sur ce que fait la fonction, comment l’utiliser correctement, et ce à quoi s’attendre en termes de comportement et de résultats. Cette documentation est généralement écrite sous forme de commentaires dans le code source de la fonction.
Exemple :
def factorielle(n):
    """ Fonction qui calcule la factorielle
       Paramètre n : un nombre entier positif
       Renvoie n!
     """
Une bonne documentation :
- Est concise et précise 
- Donne les préconditions sur les paramètres 
- Décrit le résultat (ce que fait la fonction) 
Astuce pour être efficace :
- Toujours commencer par écrire la documentation 
 De toute façon il faut réfléchir à ce que la fonction va faire!
Tests d’une fonction#
En informatique, il est important d’apprendre à écrire des tests qui permettent de valider le bon fonctionnement des ses fonctions et programmes.
Il existe en Python un mot-clé, assert, qui permet de tester une expression booléenne.
Vous l’avez déjà rencontré dans les TPs précédents. Si cette expression s’évalue à True,
il ne se passe rien.
Astuces pour être efficace :
- Commencer par écrire les tests d’une fonction 
 De toute façon il faut réfléchir à ce qu’elle va faire!
- Tester les cas particuliers 
- Tant que l’on est pas sûr que la fonction est correcte : - Faire des essais supplémentaires 
- Capitaliser ces essais sous forme de tests 
 
- Si l’on trouve un bogue (ou bug en anglais, une erreur) : - Ajouter un test caractérisant le bogue 
 
Astuce
Les fonctions préexistantes en python
En python, on peut appeler de nombreuses fonctions préexistantes. Vous en avez déjà vu
quelques unes : type(), print(), range()… Nous en découvrirons d’autres au fur et
à mesure des TPs.
Exercice 1 : renvoyer versus afficher#
- Les deux cellules suivantes définissent respectivement les fonctions - abset- afficheAbs; notez les différences entre ces deux fonctions, puis exécutez les cellules.
def abs(a):
    """ Une fonction qui calcule la valeur absolue
      Paramètres : a, un entier
      Renvoie : la valeur absolue de a
    """
    if (a > 0):
        return a
    else:
        return -a
def afficheAbs(a):
    """ Une fonction qui affiche la valeur absolue
      Paramètres : a, un entier
    """
    if (a > 0):
        print(a)
    else :
        print(-a)
- Observez les appels suivants; y a-t-il une différence entre - abset- afficheAbs?
abs(-3)
3
abs(-3)
3
afficheAbs(-3)
3
afficheAbs(-3)
3
Indication
Explication
abs renvoie une valeur alors que afficheAbs l”affiche. On notera ci-dessus
que, avec abs(3);, Jupyter ne montre pas du tout la valeur alors que, avec abs(3),
Jupyter montre la valeur avec son type (int). Inversement afficheAbs affiche la
valeur mais ne la renvoie pas.
Exercice 1 (suite)
- Essayez de deviner le résultat des appels suivants puis exécutez pour vérifier : 
abs(-5) + abs(3)
8
afficheAbs(-5) + afficheAbs(3)
5
3
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[8], line 1
----> 1 afficheAbs(-5) + afficheAbs(3)
TypeError: unsupported operand type(s) for +: 'NoneType' and 'NoneType'
La seconde cellule vous donne une erreur, comprenez-vous pourquoi?
Explication
afficheAbs ne fait qu’afficher une valeur sans la renvoyer (type de retour void); il
n’est donc pas possible de réutiliser cette valeur par la suite, par exemple pour faire
un calcul ou un test.
Exercice 2 : une fonction utilisant une fonction#
Complétez la fonction ci-dessous dont on donne la documentation.
⚠️ Vous devez utiliser un appel à l’une des deux fonctions précédentes, afficheAbs ou
abs; laquelle faut-il choisir ? Pourquoi ? ⚠️
def distance(a, b):
    """ Distance de deux points sur une droite
      Paramètre : a un entier: la coordonnée du premier point
      Paramètre : b un entier: la coordonnée du deuxième point
      Renvoie : la valeur absolue de la différence entre a et b
    """
    ### BEGIN SOLUTION
    return abs(b-a)
    ### END SOLUTION
Vérifiez le comportement de votre fonction distance sur l’exemple ci-dessous; essayez
sur quelques autres exemples; corrigez la fonction si nécessaire :
distance(5,3)
2
Les tests ci-dessous automatisent partiellement la vérification du comportement de votre
fonction; comme la valeur attendue est spécifiée, il ne reste qu’à vérifier que l’on
obtient bien true à chaque fois :
distance(5,3) == 2
True
distance(-4,2) == 6
True
distance(2,-5) == 7
True
Exercice 3 : tests automatiques#
Dans l’exercice précédent, on a testé la fonction distance. Cependant, il a fallu
exécuter les trois cellules de test séparément et s’assurer pour chacune d’entre elles
que true était affiché et pas false. Pour n’être averti que s’il y a un problème et
savoir d’où il provient, nous allons rassembler les tests en une seule cellule à l’aide
de l’infrastructure d’automatisation des tests aperçue dans les TPs précédents.
Essayez les exemples suivants. .
Astuce
À chaque fois que vous redémarrez le noyau, allez ensuite dans Cellule ->
Exécuter toutes les précédentes. Cela exécute toutes les cellules qui sont avant celle
où vous vous trouvez. Vous éviterez ainsi de perdre du temps à chercher où sont les
cellules qu’il faut ré-exécuter.
assert ( 1 < 2 )
assert ( 1 > 2 )
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[14], line 2
      1 assert ( 1 < 2 )
----> 2 assert ( 1 > 2 )
AssertionError: 
On remarque que, si la condition en paramètre de assert est vraie, il n’y a aucun
affichage. Par contre si la condition est fausse, un message d’erreur indiquant la
condition fausse est affiché.
Avec assert, les tests de la fonction distance se mettent sous la forme :
assert ( distance(5,3)  == 2 )
assert ( distance(-4,2) == 6 )
assert ( distance(2,-5) == 7 )
### BEGIN HIDDEN TESTS
assert ( distance(-5,-2) == 3)
### END HIDDEN TESTS
Exécutez ces tests. Leur exécution ne devrait rien afficher.
Exécutez les deux cellules suivantes pour définir et tester la fonction maxAbs.
Corrigez la fonction pour qu’elle passe les tests.
def maxAbs(a, b):
    """ Une fonction qui renvoie la valeur absolue du plus grand des deux entiers 
       en valeur absolue
      Paramètre : a, un entier
      Paramètre : b un entier
      Renvoie : la valeur absolue du plus grand des deux entiers en valeur absolue
     """
    print(abs(a))
    print(abs(b))
    if abs(a) >= abs(b):
        return a
    else :
        return b
assert( maxAbs(  6,  2) ==  6 )
assert( maxAbs(-15,  5) == 15 )
assert( maxAbs( -2, -3) ==  3 )
6
2
15
5
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[17], line 2
      1 assert( maxAbs(  6,  2) ==  6 )
----> 2 assert( maxAbs(-15,  5) == 15 )
      3 assert( maxAbs( -2, -3) ==  3 )
AssertionError: 
Exercice 4#
Mêmes consignes que pour l’exercice 1 :
def sommeAbs(a, b):
    """ somme des valeurs absolues (aussi appelée norme L1)
      Paramètre : a un entier
      Paramètre :  b un entier
      Renvoie : la somme des valeurs absolues de a et b
     """
    ### BEGIN SOLUTION
    return abs(a) + abs(b)
    ### END SOLUTION
sommeAbs(5,-3)
8
sommeAbs(5,-3)  == 8
True
sommeAbs(-4,-2) == 6
True
sommeAbs(2,5) == 7
True
Exercice 5 : suivre la documentation et les tests#
Implantez la fonction nombreSecondes dont la documentation est donnée ci-dessous :
### BEGIN SOLUTION
def nombreSecondes(j, h, m, s):
    """ Renvoie en secondes la durée décrite en jours, heures, minutes, secondes
      Paramètre : j un entier représentant le nombre de jours
      Paramètre : h un entier représentant le nombre d heures
      Paramètre : m un entier représentant le nombre de minutes
      Paramètre : s un entier représentant le nombre de secondes
      Renvoie : la durée totale en secondes
    """
    return s + (60 * (m + 60 * (h + 24*j)))
### END SOLUTION
Vérifiez son fonctionnement sur les exemples et tests ci-dessous :
nombreSecondes(1,1,1,1)
90061
assert( nombreSecondes(0,0,0,1)  == 1      )
assert( nombreSecondes(0,0,1,0)  == 60     )
assert( nombreSecondes(0,1,0,0)  == 3600   )
assert( nombreSecondes(1,0,0,0)  == 86400  )
assert( nombreSecondes(3,2,5,25) == 266725 )
