# Fonctions : organiser le code --- Dans ce cours, nous allons voir comment les **fonctions** permettent d'organiser efficacement le code. Nous allons partir d'un programme mal rédigé et nous allons l'améliorer. --- ```python[1-11] x = int(input()) y = int(input()) a = x b = y while a % b != 0: r = a % b a = b b = r z = b print(x//z) print(y//z) ``` Comprendre ce que fait ce programme sera pénible même pour celui qui l'a écrit. **→ Le programmeur doit faire un effort de lisibilité !** Même à l'utilisation, on ne comprend rien. --- ### Ajouter des commentaires ? Très mauvaise solution ! ```python[1-11] x = int(input()) # saisie du numérateur y = int(input()) # saisie du dénominateur a = x # calcul du pgcd b = y while a % b != 0: r = a % b a = b b = r z = b print(x//z) # affichage du numérateur réduit print(y//z) # affichage du dénominateur réduit ``` Les commentaires doublent le temps de lecture. *J'en mets parfois mais c'est pour le cours...* --- ### Bien nommer les variables ... et rendre les ''input'' et ''print'' plus explicites. ```python[1-10] num = int(input("Numérateur : ")) den = int(input("Dénominateur : ")) a = num b = den while a % b != 0: r = a % b a = b b = r d = b print(f"Fraction réduite : {num//d}/{y//d}"); ``` --- ### Extraire la fonction ```python[3-9] num = int(input("Numérateur : ")) den = int(input("Dénominateur : ")) a = num b = den while a % b != 0: r % b a = b= a b = r d = b print(f"Fraction réduite : {num//d}/{y//d}"); ``` Ce morceau fait un calcul. On va extraire ce calcul pour en faire une **fonctions** --- ```python[1-6,10] def ma_fonction(a,b): while a % b != 0: r % b a = b= a b = r return b num = int(input("Numérateur : ")) den = int(input("Dénominateur : ")) d = ma_fonction(num, den) print(f"Fraction réduite : {num//d}/{y//d}"); ``` ![ma_fonction](./medias/fonctions/fonction.svg) Pour l'instant, ça ne semble pas changer grand chose. --- ![signature](./medias/fonctions/defex.png) ![ma_fonction](./medias/fonctions/fonction.svg) Pour l'instant, ça ne semble pas changer grand chose. --- ### signature ![signature](./medias/fonctions/mafonction_signature.png) La **signature** indique le nom de la fonction et ses entrées. --- ### Bien nommer la fonction ```python[1-11] def pgcd(a,b): while a % b != 0: r % b a = b= a b = r return b num = int(input("Numérateur : ")) den = int(input("Dénominateur : ")) d = pgcd(num, den) print(f"Fraction réduite : {num//d}/{y//d}"); ``` ![pgcd](./medias/fonctions/pgcd.svg) --- ### bloc principal ![principal](./medias/fonctions/principal.png) Le bloc principal n'est pas indenté dans une fonction. C'est lui qui s'exécute. La **définition** de la fonction n'occasionne aucune exécution. --- ### bloc principal ![principal](./medias/fonctions/principal.png) La fonction a permis de simplifier le principal. --- ### documenter ![principal](./medias/fonctions/documentation.png) Documentez **toujours** vos fonctions. --- ### typer ```python[1] def pgcd(a:int,b:int) -> int: """ a, b: deux entiers positifs, b non nul renvoie le pgcd de a, b """ while a % b != 0: r % b a = b= a b = r return b ``` Typer est optionnel mais peut aider. --- ### Et encore beaucoup d'avantages * évite les répétitions * facilite les tests automatiques * les variables utilisées n'existent que le temps nécessaire. * facilite le travail à plusieurs * simplifie la structure * modularisation (exemple à suivre) --- # IL FAUT FAIRE DES FONCTIONS !!!!! --- ### La fonction renvoie * Une fonction ne contient **jamais** de `print`... * **SAUF** si la fonction est fait exprès pour l'affichage. * La sortie d'une fonction est faite par `return` --- ## `print` c'est mal... *d'en mettre n'importe où !* --- ### modulariser ```python # monmodule.py def pgcd(a:int,b:int) -> int: ... ``` ```python # main.py from monmodule import pgcd num = int(input("Numérateur : ")) den = int(input("Dénominateur : ")) d = pgcd(num, den) print(f"Fraction réduite : {num//d}/{y//d}"); ``` La foncton est déplacée dans un module à part ce qui allège encore le principal. --- ### assert : précondition `assert` permet d'indiquer une condition qui **doit** être vérifiée. ```python # monmodule.py def pgcd(a:int,b:int) -> int: """ renvoie le pgcd de a et b """ assert b != 0 ... ``` Indique clairement la condition à laquelle la fonction fait son travail correctement. --- ### assert : test simple On sait **d'avance** que `pgcd(15,35) == 7`. On peut s'en servir comme test simple vérifiant que la fonction fait bien son travail. ```python # monmodule.py def pgcd(a:int,b:int) -> int: """ renvoie le pgcd de a et b """ ... assert pgcd(15,35) == 5 ``` --- ### portée des variables *cf. exercices pour ce point*