Les fonctions#

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#

Exécutez les cellules suivantes qui définissent deux fonctions.

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)

Observez les appels suivants; y a-t-il une différence entre abs et afficheAbs?

BEGIN SOLUTION

abs renvoie une valeur alors que afficheAbs ne fait qu”afficher une valeur. Comme on le voit dans les cellules suivante, le résultat dans Jupyter a l’air d’être le même. C’est à l’utilisation des fonctions que l’on fera une différence.

END SOLUTION

abs(-3)
3
abs(-3)
3
afficheAbs(-3)
3
afficheAbs(-3)
3

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?

BEGIN SOLUTION

afficheAbs ne fait qu’afficher une valeur sans la renvoyer (elle ne renvoie donc rien); il n’est donc pas possible de réutiliser cette valeur par la suite, par exemple pour faire un calcul.

END SOLUTION

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