Fonctions avec valeur de retour#
import pathlib
import sqlite3
path = pathlib.Path('database.sqlite')
exists = path.exists()
db = sqlite3.connect(path)
if not exists:
db.executescript(pathlib.Path('pizzeria.sql').read_text())
def execute_sql(request):
results = db.execute(request).fetchall()
if results == None or results == [] :
return []
if len(results[0]) == 1:
return [x[0] for x in results]
return results
Afficher n'est pas retourner#
Jusqu'à présent, nos fonctions affichaient leur résultat avec un print. Reprenons par exemple une fonction qui calcule l'aire d'un triangle.
def aire_triangle(base, hauteur):
aire = base * hauteur / 2
print(aire)
aire_triangle(5, 10)
aire_triangle(10, 13)
Ce programme affiche bien les deux aires (25.0 et 65.0), mais il y a un problème : ces deux valeurs sont perdues une fois affichées. 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.
Note
Il est crucial de se rappeler qu'avec un print(), la valeur calculée par la fonction est ensuite perdue. Pour la réutiliser dans le programme principal, il faudra impérativement utiliser un return.
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.
def aire_triangle(base, hauteur):
aire = base * hauteur / 2
return aire
aire1 = aire_triangle(5, 10)
aire2 = aire_triangle(10, 13)
aire_totale = aire1 + aire2
print("Aire totale :", aire_totale)
Important
printaffiche une valeur à l'écran. On la voit, mais le programme ne peut pas la réutiliser.returnrend une valeur au programme. Rien ne s'affiche, mais on peut la récupérer et la réutiliser.
Récupérer la 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.
def double(nombre):
return nombre * 2
double(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 faisait avec un input().
def double(nombre):
return nombre * 2
resultat = double(5)
print(resultat)
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.
Utiliser une valeur de retour#
Une fois qu'une fonction retourne une valeur, son appel peut s'utiliser partout où vous pourriez écrire cette valeur : directement dans un print, dans un calcul, dans une condition, ou même comme paramètre d'une autre fonction.
def double(nombre):
return nombre * 2
print(double(5)) # afficher directement le résultat
total = double(5) + double(10) # utiliser le résultat dans un calcul
print("Total :", total)
if double(5) > 8: # utiliser le résultat dans une condition
print("Le double de 5 est plus grand que 8")
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.
def valeur_absolue(nombre):
if nombre >= 0:
return nombre
return -nombre
print(valeur_absolue(7))
print(valeur_absolue(-4))
Exercices#
Exercice 34#
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, puis vérifiez en réfléchissant à ce que fait vraiment
chaque appel de fonction. Si le programme n'affiche rien, écrivez rien.
def double(nombre): return nombre * 2 double(5) print("Terminé")
def double(nombre): return nombre * 2 resultat = double(5) print(resultat)
def double(nombre): print(nombre * 2) double(5)
def double(nombre): return nombre * 2 print(double(5) + double(10))
def prix_total(quantite): return quantite * 3 commande = prix_total(4) print(commande + 5)
Solution
Terminéseulement. La fonction calcule bien10, mais comme cet appeldouble(5)n'est rangé dans aucune variable, la valeur est aussitôt perdue. La seule chose affichée est leprint("Terminé")de la dernière ligne. C'est le piège n° 1 des fonctions : unreturnn'affiche rien tout seul.10. Cette fois l'appel est capté dans la variableresultat, que leprintaffiche ensuite.10également — mais pour une raison opposée au programme 2 ! Ici la fonction ne retourne rien : c'est elle-même qui contient leprint. Le résultat s'affiche donc pendant l'appel. Les programmes 2 et 3 affichent la même chose, mais dans le programme 3 on ne pourrait pas réutiliser la valeur10ailleurs, alors que dans le programme 2, oui.30. Un appel qui retourne une valeur peut s'utiliser directement dans un calcul :double(5)vaut 10,double(10)vaut 20, et c'est leur somme qui est affichée.17. L'appelprix_total(4)retourne12, qui est rangé danscommande. La dernière ligne affiche donccommande + 5, soit17.
Exercice 35#
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.
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)
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)
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)
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 )
Solution
1def périmètre_carré(côté): 2 périmètre = côté * 4 3 return périmètre 4 5p1 = périmètre_carré(5) 6p2 = périmètre_carré(7) 7total = p1 + p2 8print(total)
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] 10m = maximum(ma_liste) 11print(m)
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 13réduit_1 = applique_réduction(prix_de_base_1, "JANM") 14réduit_2 = applique_réduction(prix_de_base_2, "STX") 15prix_réduit_total = réduit_1 + réduit_2 16print(prix_réduit_total)
1def ajoute_s(mot, nombre): 2 if nombre > 1: 3 return mot + "s" 4 else: 5 return 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 36#
La fonction ci-dessous permet de calculer et de retourner le périmètre d'un cercle. Appelez cette fonction 2x en récupérant la valeur de retour pour déterminer le périmètre total d'un cercle de rayon 3 et de rayon 5
1def périmètre_cercle(rayon):
2 périmètre = 2 * 3.14159 * rayon
3 return périmètre
4
5#Complétez le code ici
Solution
def périmètre_cercle(rayon):
périmètre = 2 * 3.14159 * rayon
return périmètre
p1 = périmètre_cercle(3)
p2 = périmètre_cercle(5)
total = p1 + p2
print("Le périmètre total est de", total)
Exercice 37#
Le code ci-dessous fait appel à une fonction calculant et retournant un prix réduit de 20%. Définissez cette fonction et écrivez son corps.
1prix = 56
2prix_réduit = réduction_20(prix)
3print("Prix réduit :", prix_réduit, "CHF")
Solution
def réduction_20(p):
return p * 0.8
prix = 56
prix_réduit = réduction_20(prix)
print("Prix réduit :", prix_réduit, "CHF")
Exercice 38#
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 :
retenueAu moins 6 retards ou 4 absences injustifiées :
retenue samedi matinAu moins 9 retards ou 6 absences injustifiées :
avertissement écritAu moins 12 retards ou 8 absences injustifiées :
menace d'exclusionAu moins 15 retards ou 10 absences injustifiées :
exclusionEn dessous de tout cela :
rien
Utilisez ensuite la fonction 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):
Solution
def sanctions_STX(n_retards, n_absences_inj):
if n_retards >= 15 or n_absences_inj >= 10:
return "exclusion"
elif n_retards >= 12 or n_absences_inj >= 8:
return "menace d'exclusion"
elif n_retards >= 9 or n_absences_inj >= 6:
return "avertissement écrit"
elif n_retards >= 6 or n_absences_inj >= 4:
return "retenue samedi matin"
elif n_retards >= 3 or n_absences_inj >= 2:
return "retenue"
else:
return "rien"
sanction1 = sanctions_STX(4, 0)
sanction2 = sanctions_STX(2, 2)
print("Sanction du 1er élève :", sanction1)
print("Sanction du 2ème élève :", sanction2)
if sanction1 == sanction2:
print("Deux mêmes sanctions...")
Exercice 39#
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 et la quantité moyenne commandée dans la base de données de la pizzeria.
1def moyenne(liste):
2 # Complétez le corps de la fonction
3
4prix = execute_sql("SELECT prix FROM Pizza")
5quantités = execute_sql("SELECT quantite FROM Commande")
6
7# Appelez la fonction deux fois et affichez les deux résultats
Solution
1def moyenne(liste):
2 total = 0
3 for valeur in liste:
4 total = total + valeur
5 return total / len(liste)
6
7prix = execute_sql("SELECT prix FROM Pizza")
8quantités = execute_sql("SELECT quantite FROM Commande")
9
10print("Prix moyen d'une pizza :", moyenne(prix), "CHF")
11print("Quantité moyenne par commande :", moyenne(quantités))
Le prix moyen est d'environ 18.33 CHF et la quantité moyenne d'environ 1.67 pizza par commande.
Remarquez que la fonction ne sait rien des pizzas : elle reçoit une liste de nombres et rend leur moyenne, un point c'est tout. C'est ce qui permet de l'appeler deux fois sur des données qui n'ont aucun rapport entre elles. Sans valeur de retour, il aurait fallu écrire deux fois le même calcul.