# 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}");
```

Pour l'instant, ça ne semble pas changer grand chose.
---


Pour l'instant, ça ne semble pas changer grand chose.
---
### signature

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}");
```

---
### bloc principal

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

La fonction a permis de simplifier le principal.
---
### documenter

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*