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
       Retourne 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#

  1. Les deux cellules suivantes définissent respectivement les fonctions abs et 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
      Retour : 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)
  1. Observez les appels suivants; y a-t-il une différence entre abs et 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)

  1. 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?

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
      Retour : 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
      Retour : 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
      Retour : 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
      Retour : 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 )

Retourner à l’index