Fonctions#

Qu'est-ce qu'une fonction ?#

Dans un programme, certains blocs d'instructions doivent être réutilisés à plusieurs endroits. On peut par exemple imaginer une dizaine d'instructions permettant de vérifier qu'un mot de passe est suffisamment robuste (au moins 12 caractères, une majuscule, un caractère spécial, etc.). Ces instructions devront non seulement être utilisées lors de l'inscription d'un nouvel utilisateur, mais également lors du changement de mot de passe.

On pourrait simplement copier/coller ces dix lignes à ces deux endroits du programme. Dès lors, le programme pourrait être représenté avec le schéma ci-dessous, dans lequel les cases bleues représentent le même code dupliqué à deux endroits différents.

Schéma d'un programme dans lequel le même bloc de code est copié à deux endroits

Toutefois, recopier les mêmes instructions plusieurs fois vient avec des désavantages

  • Si le code doit être modifié, il faudra aller le changer partout où il a été copié/collé

  • Du point de vue d'un programmeur qui découvre le code, il n'est pas clair au 1er coup d'oeil que ces lignes copiées/collées sont les mêmes et qu'elles doivent le rester

  • Pour ce même programmeur, l'utilité de ces lignes n'est pas directement claire non plus : il devra les lire pour les analyser et les comprendre.

Pour pallier ces problèmes, le code utilisé 2x ne doit pas être copié/collé, mais déplacé "en marge" du programme principal dans une fonction. Lorsque, dans notre programme, on souhaite utiliser ces instructions mises en marge, on ne fait alors qu'un appel à cette fonction. Le programme ressemblera dès lors à cela :

Schéma d'un programme qui appelle deux fois une fonction F définie en marge

Avec cela, lorsqu'on modifie une fois le code à réutiliser, la modification impactera tous les appels de fonction. De plus, le nom de la fonction (ici F) devrait être significatif et nommer l'action effectuée par la fonction. Dans l'exemple de la vérification de sécurité du mot de passe, la fonction aurait pu avoir comme nom vérifie_sécurité_mdp. Ainsi, avec une fonction, le programme devient plus lisible et est plus facilement modifiable.

Définir et appeler une fonction#

Le mot-clef permettant de définir une fonction est def. Celui-ci est suivi du nom de la fonction puis d'une paire de parenthèses et de deux-points. Les instructions indentées sous la définition constituent le corps de la fonction, c'est-à-dire le bloc d'instructions à exécuter lorsque la fonction est appelée.

Définir une fonction ne l'exécute pas : il faut encore l'appeler, en écrivant son nom suivi d'une paire de parenthèses. Dans l'exemple ci-dessous, la fonction affiche_salutations est définie une seule fois, puis appelée 2x à différents endroits du programme.

1def affiche_salutations():
2    print("Bonjour")
3    print("Comment allez-vous ?")
4
5print("Début du programme")
6affiche_salutations()
7print("Pouvez-vous répéter svp, je n'ai pas compris")
8affiche_salutations()

Fonction avec paramètres#

Les fonctions peuvent être paramétrées. C'est-à-dire que leur exécution va dépendre de valeurs qui seront précisées au moment de l'appel. Ces paramètres se placent entre les parenthèses de la définition de la fonction et sont séparés par une virgule. Ils peuvent ensuite être réutilisés dans le corps de la fonction. Lors de l'appel, on précise obligatoirement les valeurs des paramètres entre les parenthèses.

1def calcul_et_affiche_aire_triangle(base, hauteur):
2    aire = base * hauteur / 2
3    print("L'aire d'un triangle de", base, "de base et", hauteur, "de hauteur est de", aire)
4
5calcul_et_affiche_aire_triangle(10, 20)
6calcul_et_affiche_aire_triangle(20, 10)
7calcul_et_affiche_aire_triangle(35, 54)

Afficher n'est pas retourner#

La fonction ci-dessus affiche son résultat avec un print. Le problème, c'est que les valeurs affichées sont ensuite perdues : impossible de les additionner pour obtenir l'aire totale, de les comparer, ou de les réutiliser plus loin. La fonction a montré le résultat à l'écran, mais elle ne l'a pas donné au programme.

Avec le mot-clef return, la fonction rend sa valeur au programme au lieu de simplement l'afficher. On peut alors la récupérer dans une variable et l'utiliser à notre guise, par exemple pour additionner deux aires.

1def aire_triangle(base, hauteur):
2    aire = base * hauteur / 2
3    return aire
4
5aire1 = aire_triangle(5, 10)
6aire2 = aire_triangle(10, 13)
7
8aire_totale = aire1 + aire2
9print("Aire totale :", aire_totale)

Important

  • print affiche une valeur à l'écran. On la voit, mais le programme ne peut pas la réutiliser.

  • return rend une valeur au programme. Rien ne s'affiche, mais on peut la récupérer et la réutiliser.

Récupérer et utiliser une valeur de retour#

Une valeur retournée n'est utile que si on la récupère. Dans le programme ci-dessous, la fonction calcule bien le double de 5, mais comme le résultat n'est rangé nulle part, il est immédiatement perdu : le programme n'affiche donc rien du tout.

1def double(nombre):
2    return nombre * 2
3
4double(5)   # la valeur 10 est calculée... puis jetée

Pour utiliser la valeur retournée, il faut la capter en la plaçant après une variable et un =, exactement comme on le fait avec un input(). Plus généralement, l'appel d'une fonction qui retourne une valeur peut s'utiliser partout où l'on pourrait écrire cette valeur : dans une variable, directement dans un print, dans un calcul ou dans une condition.

 1def double(nombre):
 2    return nombre * 2
 3
 4resultat = double(5)            # ranger le résultat dans une variable
 5print(resultat)
 6print(double(5))                # afficher directement le résultat
 7total = double(5) + double(10)  # utiliser le résultat dans un calcul
 8print("Total :", total)
 9
10if double(5) > 8:               # utiliser le résultat dans une condition
11    print("Le double de 5 est plus grand que 8")

Avertissement

C'est l'erreur la plus fréquente avec les fonctions : écrire double(5) en pensant que "ça va afficher 10". Une fonction qui return n'affiche jamais rien toute seule. Si vous voulez voir la valeur, il faut soit la ranger dans une variable, soit l'afficher vous-même avec un print.

Le return met fin à la fonction#

Dès qu'un return est exécuté, la fonction s'arrête immédiatement : les instructions qui le suivent dans le corps de la fonction ne sont jamais exécutées. Dans l'exemple ci-dessous, si le nombre est positif, le premier return renvoie sa valeur et quitte la fonction ; le second return n'est atteint que pour les nombres négatifs. On n'a donc même pas besoin d'un else.

1def valeur_absolue(nombre):
2    if nombre >= 0:
3        return nombre
4    return -nombre
5
6print(valeur_absolue(7))
7print(valeur_absolue(-4))

Exercices#

Exercice 22#

Définir une fonction et l'appeler sont deux choses différentes, et les lignes d'un programme ne s'exécutent plus forcément de haut en bas. Lisez attentivement le programme ci-dessous et répondez sans l'exécuter.

1def bonjour():
2    print("B")
3    print("C")
4
5print("A")
6bonjour()
7print("D")
8bonjour()
9print("E")
  1. Dans quel ordre les lettres s'affichent-elles ? Écrivez-les à la suite, sans espaces.

  2. Quelle est la première ligne exécutée par le programme ?

  3. Combien de fois la ligne 3 est-elle exécutée ?

  4. Combien de fois la ligne 5 est-elle exécutée ?

Exercice 23#

Les cinq programmes ci-dessous se ressemblent, mais n'affichent pas la même chose. Pour chacun, prédisez ce qui s'affiche à l'écran, en réfléchissant à ce que fait vraiment chaque appel de fonction. Si le programme n'affiche rien, écrivez rien.

  1. def double(nombre):
        return nombre * 2
    
    double(5)
    print("Terminé")
    
  2. def double(nombre):
        return nombre * 2
    
    resultat = double(5)
    print(resultat)
    
  3. def double(nombre):
        print(nombre * 2)
    
    double(5)
    
  4. def double(nombre):
        return nombre * 2
    
    print(double(5) + double(10))
    
  5. def prix_total(quantite):
        return quantite * 3
    
    commande = prix_total(4)
    print(commande + 5)
    

Exercice 24#

Chacun des programmes suivants comporte au moins une erreur. Parfois, cette erreur fait directement buguer le programme avec un message d'erreur rouge. D'autres fois, le programme s'exécute correctement, mais son résultat n'est pas logique.

Corrigez chacun de ces codes de manière à ce qu'ils s'exécutent correctement et affichent un résultat logique.

  1. 1def périmètre_carré(côté):
    2    périmètre = côté * 4
    3    print(périmètre)
    4
    5p1 = périmètre_carré(5)
    6p2 = périmètre_carré(7)
    7total = p1 + p2
    8print(total)
    
  2.  1def maximum(liste):
     2    maximum = -99999
     3    for n in liste:
     4        if n > maximum:
     5            maximum = n
     6    return maximum
     7
     8#Doit afficher le maximum de la liste ci-dessous
     9ma_liste = [4, 6, 2, 8, -4, 3, 10, 9, 4, 7, -3]
    10maximum(ma_liste)
    
  3.  1def applique_réduction(prix, code):
     2    if code == "STX":
     3        return prix * 0.8
     4    elif code == "JANM":
     5        return prix * 0.65
     6    elif code == "FRI":
     7        return prix * 0.9
     8    else:
     9        return prix
    10
    11prix_de_base_1 = 67
    12prix_de_base_2 = 45
    13applique_réduction(prix_de_base_1, "JANM")
    14applique_réduction(prix_de_base_2, "STX")
    15prix_réduit_total = prix_de_base_1 + prix_de_base_2
    16print(prix_réduit_total)
    
  4.  1def ajoute_s(mot, nombre):
     2    if nombre > 1:
     3        mot + "s"
     4    else:
     5        mot
     6
     7n_chat = int(input("Combien de chats as-tu ?"))
     8n_chien = int(input("Combien de chiens as-tu ?"))
     9txt_chat = ajoute_s("chat", n_chat)
    10txt_chien = ajoute_s("chien", n_chien)
    11print("Tu as", n_chat, txt_chat, "et", n_chien, txt_chien)
    

Exercice 25#

Définissez une fonction nommée sanctions_STX permettant de déterminer les sanctions à STX en fonction du nombre de retards et du nombre d'absences injustifiées. Pour rappel, les sanctions sont les suivantes :

  • Au moins 3 retards ou 2 absences injustifiées : retenue

  • Au moins 6 retards ou 4 absences injustifiées : retenue samedi matin

  • Au moins 9 retards ou 6 absences injustifiées : avertissement écrit

  • Au moins 12 retards ou 8 absences injustifiées : menace d'exclusion

  • Au moins 15 retards ou 10 absences injustifiées : exclusion

  • En dessous de tout cela : rien

La fonction retourne la sanction. Utilisez-la ensuite pour déterminer les sanctions de 2 élèves : l'un ayant 4 retards et 0 absence injustifiée, l'autre 2 retards et 2 absences injustifiées.

Si les deux sanctions sont pareilles, votre programme affichera en plus : Deux mêmes sanctions...

1def sanctions_STX(n_retards, n_absences_inj):

Exercice 26#

Une fonction devient vraiment utile lorsqu'on la réutilise sur des données différentes. Écrivez une fonction moyenne qui reçoit une liste de nombres en paramètre et qui retourne leur moyenne. Utilisez-la ensuite, sans la réécrire, pour afficher successivement le prix moyen des pizzas d'une carte et la température moyenne de la semaine.

1def moyenne(liste):
2    # Complétez le corps de la fonction
3
4prix_pizzas = [12.5, 18, 22.5, 15, 19]
5températures = [14, 17, 21, 19, 12, 9, 13]
6
7# Appelez la fonction deux fois et affichez les deux résultats