Dรฉfinir une fonction personnelleโ๏ธ
Nous pouvons dรฉfinir des fonctions pour notre propre usage ou pour la communautรฉ de programmeurs.
Fonctions sans paramรจtre ni valeur de retourโ๏ธ
Supposons que je veuille รฉcrire la mรชme phrase ร diffรฉrents endroits d'un programme :
...
print("Vous trouverez plus d'informations en vous rendant sur notre site internet")
...
...
print("Vous trouverez plus d'informations en vous rendant sur notre site internet")
...
alors je peux remarquer deux problรจmes :
- c'est clairement une perte de temps de devoir retaper le mรชme texte (oui, il y a le copier-coller) ;
- si je veux amรฉliorer mon texte, il faudra le faire partout oรน il apparaรฎt (oui, il y a la fonction Remplacer...).
Bref, il serait prรฉfรฉrable de se conformer ร la philosophie DRY : "Don't Repeat Yourself".
Pour cela, nous allons dรฉfinir une fonction avec le mot clรฉ def
:
def afficher_texte_site():
print("Vous trouverez plus d'informations en vous rendant sur notre site internet")
Il ne nous reste plus qu'ร appeler cette fonction lร oรน c'est utile :
...
afficher_texte_site()
...
...
afficher_texte_site()
...
ร vous : dรฉfinissez puis appelez la fonction afficher_texte_site()
:
ร retenir
Dรฉfinition : une fonction est un bloc d'instructions qui sont exรฉcutรฉes quand cette fonction est appelรฉe.
Pour dรฉfinir une fonction sans paramรจtre ni valeur de retour :
def ma_fonction():
instruction_1
instruction_2
instruction_3
...
derniรจre instruction
Remarquez :
- le
:
indispensable ร la fin de la ligne dudef
; - que les instructions sont regroupรฉes dans un bloc qui est dรฉlimitรฉ grรขce ร des tabulations (touche Tab โน) ou par 4 espaces parfois, ce dรฉcalage vers la droite est appelรฉ indentation ;
- que ce bloc dโinstructions n'est exรฉcutรฉ que si j'appelle ma fonction (en รฉcrivant
ma_fonction()
plus loin dans le programme) ; - que notre fonction
afficher_texte_site
n'a pas de valeur de retour (essayez de tapertype(afficher_texte_site())
), elle ne renvoie rien : elle procรจde juste ร un affichage ; une telle fonction est parfois appelรฉe procรฉdure. L'affichage du texte est un effet de bord.
Exercice
-
Sans utiliser de copier-coller, dรฉfinissez une fonction nommรฉe
propagande
et qui affiche le texte "Longue vie ร notre cher prรฉsident Tapioca".
Utilisez ensuite cette fonction pour afficher 4 fois ce texte. -
Modifiez la fonction afin de pouvoir afficher "Gloire ร notre nouveau prรฉsident Alcazar !"
Appel d'une fonctionโ๏ธ
Exercice
- Observez et exรฉcutez le script ci-dessous, que remarquez-vous ?
- Ajoutez l'appel aux deux fonctions ร la fin du script.
- Placez ces appels au bon endroit.
Explication
Normalement, les instructions sont exรฉcutรฉes du haut vers le bas. Ici, l'introduction de fonctions semblent casser cet ordre mais retenez bien que tant qu'une fonction n'est pas appelรฉe, ses instructions ne sont pas exรฉcutรฉes.
Exercice
- Tapez le script suivant :
๐ Script Python
aff_texte() def aff_texte(): print("La NSI c'est cool !")
- Exรฉcutez-le puis corrigez l'erreur.
Explication
Vous l'aurez compris, l'erreur ne vient pas du texte mais du fait qu'une fonction ne peut pas รชtre appelรฉe avant d'รชtre dรฉfinie ! C'est un peu comme si vous parliez chinois ร quelqu'un qui ne le parle pas !
Enfin, il est possible d'appeler une fonction dans une autre fonction, testez ceci par exemple :
def aff_texte():
print("La NSI c'est cool !")
def trois_fois_texte():
aff_texte()
aff_texte()
aff_texte()
trois_fois_texte()# appel de la fonction
Fonctions avec paramรจtre(s) mais sans valeur de retour (procรฉdures)โ๏ธ
Supposons maintenant que notre texte change un peu :
...
print("Plus d'informations ร l'adresse http://site_bidon.com, onglet Actualitรฉs")
...
...
print("Plus d'informations ร l'adresse http://www.autre_site_bidon.fr, onglet Conseils")
...
Lร encore, รฉvitons de nous rรฉpรฉter en dรฉfinissant une fonction avec ici 2 paramรจtres :
def afficher_texte_site(adresse, onglet):
print("Plus d'informations ร l'adresse", adresse, ", onglet", onglet)
(observez bien la diffรฉrence entre le mot "onglet" qui n'est que du texte et la variable onglet qui est un des paramรจtres).
Il ne nous reste plus qu'ร appeler cette fonction ainsi :
...
afficher_texte_site("http://site_bidon.com", "Actualitรฉs")
...
...
afficher_texte_site("http://www.autre_site_bidon.fr", "Conseils")
...
ร vous : redรฉfinissez puis appelez la fonction afficher_texte_site()
:
ร retenir
Pour dรฉfinir une fonction avec paramรจtres mais sans valeur de retour :
def ma_fonction(param1, param2, ...):
bloc dโinstructions ร exรฉcuter dans la fonction
Plus d'explications
def ma_fonction(param1, param2, ..., paramN):
instructions
se lit "je dรฉfinis une fonction nommรฉe ma_fonction
ayant les paramรจtres param1
, param2
, ..., paramN
qui va exรฉcuter certaines instructions".
Les valeurs des paramรจtres ne seront connues quโร lโappel de la fonction. Il s'agit d'รฉcrire quelque chose qui s'adapte aux valeurs des paramรจtres.
Exercice
Considรฉrons les fonctions suivantes :
def afficher_trois_dieses():
print("###")
def afficher_trois_etoiles():
print("***")
def afficher_trois_plus():
print("+++")
Nous voyons qu'il y a ici une rรฉpรฉtition, non pas de texte, mais de principe.
- รcrivez une fonction
afficher_trois
qui aura un paramรจtre nommรฉsymbole
et qui permettra de remplacer les trois fonctions (et mรชme plus). - รcrivez une fonction
afficher_plusieurs
qui aura deux paramรจtres nommรฉssymbole
etnb_fois
et qui permettra d'afficher un nombre quelconque de fois un symbole. - Appelez cette fonction avec
afficher_plusieurs("$", 10)
,afficher_plusieurs("$")
etafficher_plusieurs(10, "$")
.
Commentaire
Attention de bien respecter le nombre (et les types) des paramรจtres d'une fonction lors de l'appel de celle-ci !
Fonctions sans paramรจtre mais avec valeur(s) de retourโ๏ธ
Bien souvent, une fonction renvoie des valeurs. Pour cela, il faut utiliser le mot-clรฉ return
.
Par exemple, si je veux stocker la date de l'armistice de 1945 :
def armistice_2eme_gm():
return "8 mai 1945"
il ne me reste plus ensuite qu'ร appeler cette fonction pour rรฉcupรฉrer cette date importante :
armistice_2eme_gm()
Remarque
Bien sรปr il serait ici plus pertinent de dรฉfinir une constante plutรดt qu'une fonction : ARMISTICE_2EME_GM = "8 mai 1945"
).
Copiez et exรฉcutez les trois lignes de code prรฉcรฉdent dans une console (n'oubliez pas l'indentation de 4 espaces pour la deuxiรจme ligne) :
Faรฎtes maintenant la mรชme chose dans un รฉditeur :
Explications
Nous avons appelรฉ notre fonction mais rien ne s'affiche !?
En fait cette fonction renvoie bien la valeur "8 mai 1945"... mais ร qui ?
- si nous faisons un simple appel comme ci-dessus, la fonction est exรฉcutรฉe, une valeur est renvoyรฉe mais perdue (sauf si nous travaillons dans la console, oรน elle est affichรฉe);
- nous pouvons utiliser une variable pour rรฉcupรฉrer cette valeur :
arm = armistice_2eme_gm()
; - nous pouvons aussi vouloir que la valeur renvoyรฉe soit affichรฉe ร l'รฉcran :
print(armistice_2eme_gm())
; - nous pourrions enfin envoyer cette valeur ร une autre fonction...
Attention
Ne confondez pas print
et return
. La premiรจre fonction ne fait qu'envoyer des valeurs vers l'affichage ร l'รฉcran, la seconde renvoie une ou des valeurs, qui pourront รชtre stockรฉes (dans une variable) et utilisรฉes plus tard.
Je ne vois toujours pas la diffรฉrence !
Par analogie, imaginez que vous jouiez ร un jeu sur console et que vous dirigez le joystick vers le haut :
- la manette dรฉtecte un mouvement mรฉcanique et renvoie (
return
) ร la console un code du genre "dir_haut" ; - une premiรจre fonction du programme de la console reรงoit le code "dir_haut" et l'envoie (
return
) ร d'autres fonctions :- une qui calcule si le personnage peut se dรฉplacer dans cette direction, si oui celle-ci renvoie (
return
) alors les nouvelles coordonnรฉes du personnage ; - une qui rรฉcupรจre ces coordonnรฉes et s'occupe de dรฉplacer/re-dessiner le personnage ;
- une qui s'occupe de gรฉrer les effets du mouvement : changement de score, mort du personnage, etc. et renvoie (
return
) ces informations.
- une qui calcule si le personnage peut se dรฉplacer dans cette direction, si oui celle-ci renvoie (
Remarquez qu'il n'y a pas forcรฉment d'affichage ร l'รฉcran de texte donc de print
(heureusement, la console ne va pas vous dire toutes les opรฉrations qu'elle effectue !!).
Au final, la commande return
est bien plus utilisรฉe et importante que print
!
ร retenir
Pour dรฉfinir une fonction sans paramรจtre mais avec valeur(s) de retour :
def ma_fonction():
instruction_1
instruction_1
...
derniรจre instruction
return resultat1, resultat2, ...
Nous verrons plus tard que la commande return
interrompt le dรฉroulement d'une fonction et n'est pas forcรฉment ร la fin de celle-ci.
Une fonction ne renvoie qu'une valeur. Toujours !
En fait techniquement une fonction ne renvoie qu'une valeur. Par exemple :
def fonction_idiote():
return 5, 2
nous voyons que deux valeurs sont renvoyรฉes : 5 et 2. En vรฉritรฉ, la fonction renvoie le couple (5, 2) donc une valeur.
Essayez, pour le vรฉrifier, d'entrer cela dans l'รฉditeur :
def fonction_idiote():
return 5, 2
resultat = fonction_idiote()
print(resultat)
Exercice
Essayez d'รฉcrire une fonction moyenne_alea
qui :
- choisit trois nombres entiers compris entre 1 et 100 au hasard ;
- calcule et renvoie leur moyenne.
Appelez ensuite cette fonction en affectant le rรฉsultat ร une variable appelรฉe moy
.
Enfin affichez la valeur de moy
.
Une rรฉponse possible
import random
def moyenne_alea():
somme = random.randint(1, 100) + random.randint(1, 100) + random.randint(1, 100)
return somme / 3
moy = moyenne_alea()
print(moy)
Fonctions avec paramรจtre(s) et valeur(s) de retourโ๏ธ
La plupart du temps, une fonction reรงoit des donnรฉes (les paramรจtres) et en renvoie d'autres.
En voici un exemple :
def euro_vers_dollar(montant):
return montant*0.9953 # en supposant qu'un euro vaut 0,9953 dollar
print(euro_vers_dollar(5)) # pour convertir 5 โฌ
ร retenir
Pour dรฉfinir une fonction dans le cas gรฉnรฉral :
def
ma_fonction
(
param1, param2, ...
):
instruction_1
instruction_2
...
instruction_n
return
resultat1, resultat2, ...
Ne rien renvoyer ou renvoyer rien
- Nous l'avons vu, certaines fonctions, dites procรฉdures, ne renvoient rien (elles n'ont pas de
return
). Il est donc inutile de taper dans ce cas quelque chose du genrea = ma_fonction(...)
. - Dans ce cas, la fonction renvoie la valeur rien (
None
en Python). Par exemple, une fonction qui prend trois nombres entiers et renvoie ceux qui sont pairs devra parfois renvoyer... rien (return None
). Ce rien constitue alors une information (ici : il y a pas de nombres pairs parmi les trois nombres).
Un bouton en plus
Les รฉditeurs des exercices suivants comportent le bouton en plus. Quand vous aurez modifiรฉ le code, cliquez sur ce bouton pour le faire vรฉrifier.
Exercice
รcrivez puis testez (avec un print
) une fonction qui convertit des degrรฉs Celsius en degrรฉs Fahrenheit (je vous laisse chercher la formule sur le net).
Exercice
รcrivez et testez une fonction qui prend en paramรจtres deux nombres et renvoie leur produit et leur somme.
Exemple d'appel :
>>> produit_et_somme(5,3)
(15, 8)
Exercice
รcrivez et testez une fonction qui prend deux chaรฎnes de caractรจres, par exemple "Marc" et "Julie" et renvoie dans ce cas la chaรฎne suivante : Marc + Julie = ๐
.
Exercice
Fonctions utilisรฉes dans des fonctionsโ๏ธ
Dans certains cas, les valeurs renvoyรฉes par une fonction peuvent รชtre utilisรฉes par (deviennent les paramรจtres d') une autre fonction.
En voici un exemple :
def europy-undverspy-unddollar(montant):bksl-nl return montant py-str 0.99 # en supposant qu'un euro vaut 0,99 dollarbksl-nlbksl-nldef dollarpy-undverspy-undyuan(montant):bksl-nl return montant py-str 6.81 # en supposant qu'un dollar vaut 6,81 yuansbksl-nlbksl-nldef europy-undverspy-undyuan(montant):bksl-nl montantpy-unddollar = europy-undverspy-unddollar(montant)bksl-nl montantpy-undyuan = dollarpy-undverspy-undyuan(montantpy-unddollar)bksl-nl return montantpy-undyuanbksl-nlbksl-nl# remarque : rien ne va s'afficher lors de l'exรฉcution de ce scriptbksl-nl# vous pouvez appeler la fonction europy-undverspy-undyuan dans la consolebksl-nl
La fonction euro_vers_yuan
appelle les deux fonctions euro_vers_dollar
et dollar_vers_yuan
.
Nous pourrions รฉcrire cette fonction de faรงon plus concise (mais moins claire ?) :
def euro_vers_yuan(montant):
return dollar_vers_yuan(euro_vers_dollar(montant))
Exercice
- รcrivez une fonction
demande_prenom
qui affiche "Quel est votre prรฉnom ?", demande une rรฉponse et renvoie cette rรฉponse. - รcrivez une fonction
demande_naissance
qui affiche "En quelle annรฉe รชtes-vous nรฉ ?", demande une rรฉponse et renvoie cette rรฉponse. - รcrivez une fonction
demande_infos
qui utilise les deux prรฉcรฉdentes et affiche "Bonjour le prรฉnom entrรฉ, vous avez environ l'รขge approximatif de la personne".
Exercice
- รcrivez une fonction
de_4
qui simule un dรฉ tรฉtraรฉdrique en renvoyant un nombre entier entre 1 et 4. - รcrivez une fonction
lancer_3_des
qui utilise la prรฉcรฉdente et renvoie la somme et la moyenne de trois lancers d'un dรฉ tรฉtraรฉdrique.
Petit bรชtisier des erreurs courantes sur les fonctions
- N'utilisez pas des paramรจtres constants.
Les paramรจtres d'une fonction sont toujours des variables.
Par exemple, la fonction suivante :๐ Script Pythonn'a aucune capacitรฉ d'adaptation (ses paramรจtres sont toujoursdef mafonction(4, "Toto"): print(4 * "Toto")
4
et"Toto"
, on pourrait tout aussi bien les retirer) et de toute faรงon Python n'acceptera pas cette syntaxe. - N'รฉcrasez pas les paramรจtres.
Par exemple, dans la fonction suivante :๐ Script Pythonil n'y a pas d'erreur de syntaxe mais ร quoi sert le paramรจtredef mafonction(a, b): a = 3 print(a * b)
a
si on รฉcrase immรฉdiatement sa valeur ? - La valeur renvoyรฉe par la fonction doit รชtre rรฉcupรฉrรฉe ou affichรฉe :
๐ Script Pythonfait bien ce que l'on attend (calculer le produit de 4 et de 5) mais la valeur renvoyรฉe (le produit) est perdu ! Il faut donc suivant les besoins soit affecter le rรฉsultat ร une variable :def mafonction(a, b): produit = a * b return produit mafonction(4, 5)
๐ Script Pythonsoit l'afficher :def mafonction(a, b): produit = a * b return produit resultat = mafonction(4, 5)# stockage pour utilisation ultรฉrieure
๐ Script Pythonsoit l'utiliser dans une autre fonction :def mafonction(a, b): produit = a * b return produit print(mafonction(4, 5))# affichage immรฉdiat
๐ Script Pythondef mafonction_idiote(a): print(a) def mafonction(a, b): produit = a * b return produit mafonction_idiote(mafonction(4, 5))# la fonction idiote va ici afficher 20
- N'utilisez pas le nom de la fonction en tant que variable :
๐ Script Pythonfonctionne mais la lisibilitรฉ de l'ensemble est lamentable (et รงa bugguerait peut-รชtre dans d'autres langages moins permissifs).def mafonction(a, b): mafonction = a * b return mafonction
- De prรฉfรฉrence, utilisez des noms de fonctions et de variables "parlants" :
๐ Script Pythonest mieux que :
def multiplier_texte(nb, texte): return nb * texte
๐ Script PythonPensez ร la personne (vous par exemple) qui va relire votre code dans 6 mois...def f(a, b): return a * b