def ma_fonction(p1, p2):
resultat = p1 * p2 + p1 + 5
return resultatLes fonctions
Avant de commencer
- Téléchargez ce notebook Jupyter
- Connectez-vous au Jupyter ENSAI avec id et mot de passe
- ou une autre plate-forme (SSPCloud, Jupyter Lab, Google Colab, Kaggle…)
- Importez le fichier .ipynb
1 Fonctions
L’idée d’une fonction est de regrouper ensemble des morceaux de codes qui pourraient être utilisés à plusieurs endroits de votre programme.
Utiliser des fonctions est une bonne pratique :
- cela réduit la duplication du code
- cela permet de mieux structurer le code et le rendre plus clair
Une fonction est composée de :
- un ensemble de paramètres
- des instructions qui utilisent les paramètres
- retourne ou affiche un résultat
Le mot clé def sert à définir une fonction.
Voici un exemple de fonction :
- Nom de la fonction : ma_fonction
- Paramètres : 2 paramètres p1 et p2
- Sortie : résultat de l’opération p1 x p2 + p1 + 5
Maintenant que notre fonction est définie, nous pouvons l’appeler autant de fois que nous le souhaitons
ma_fonction(2, 6)ma_fonction(5, 1) + ma_fonction(8, 2)1.1 Arguments
Les arguments sont les paramètres de la fonction.
Lorsqu’on appelle une fonction en lui spécifiant des arguments, on dit qu’on lui « passe » des arguments.
Ces arguments deviennent alors des variables qui peuvent être utilisées uniquement à l’intérieur de la fonction.
def maximum(a, b):
if a > b:
resultat = a
else:
resultat = b
return resultatmaximum(1, 5)À l’extérieur des fonctions, les arguments n’existent plus et ne sont plus connus.
aPassage par position et passage par mot-clé
En Python, les fonctions admettent deux modes de passage des arguments :
- le passage par position : les arguments sont passés dans l’ordre dans lequel ils ont été définis
- le passage par mot-clé : on précise le nom du paramètre lors du passage de l’argument
Illustrons cette différence à partir d’une fonction qui réalise simplement une division.
def division(x, y):
if y == 0:
print("ERREUR : Division par 0 impossible")
else:
return x / y# Passage par position
division(8, 2) # Passage par mot-clé
division(x=8, y=2) Dans le cas du passage par position, le respect de l’ordre est impératif.
print(division(0, 5))
print(division(5, 0))Nous remarquons que s’affiche None ci-dessus.
L’explication est que lorsque l’on passe dans la partie de code if y == 0, il n’y a pas de return.
Donc par défaut la méthode renvoie None, ce qui représente l’absence de valeur.
Dans le cas du passage par mot-clé, l’ordre n’a plus d’importance.
print(division(x=0, y=5))
print(division(y=5, x=0))Arguments obligatoires et arguments optionnels
Lorsqu’on définit une fonction, il est fréquent de vouloir faire cohabiter :
- des arguments que doit absolument spécifier l’utilisateur
- des arguments optionnels qui spécifient un comportement par défaut de la fonction, mais peuvent également être modifiés si nécessaire
Regardons par exemple comment on peut modifier le comportement de la fonction print à l’aide d’un argument optionnel.
print("salut")
print("salut")print("salut", end=' ')
print("salut")Nous avons modifié le comportement du premier appel à print via le paramètre optionnel end.
Par défaut, cette valeur est fixée à '\n', soit un retour à la ligne.
Nous l’avons modifié dans la deuxième cellule à un espace, d’où la différence de résultat.
Nous allons maintenant créer une fonction avec un argument optionnel.
Pour expliquer le comportement de cette méthode, une documentation a été ajoutée entre les caractères """.
def note_finale(note1, note2, bonus=0) -> float:
"""Fonction d'ajout de 2 notes
Parameters
----------
note1 : float
la première note
note2 : float
la deuxième note
bonus : float
un bonus (optionnel, par défaut égal à 0)
Returns
-------
float : sommes des 2 notes et du bonus
"""
return note1 + note2 + bonus# Comportement par défaut (bonus=0)
note_finale(8.5, 7) # Comportement modifié
note_finale(8.5, 7, bonus = 2) Vous remarquerez également que la signature de la fonction se termine par -> float.
C’est également un élément de documentation non contraignant. Cela siginfie le type de données attendu en sortie.
Bonus : nombre d’arguments variable
- La notation
*argspermet à une fonction de recevoir un nombre variable d’arguments positionnels - La notation
**kwargspermet à une fonction de recevoir un nombre variable d’arguments clé-valeur
# Exemple d'utilisation de args
def moyenne(*args):
somme = 0
nb = 0
for a in args:
somme += a
nb += 1
print(f"Moyenne de {args} : {somme / nb}")
moyenne(10, 15)
moyenne(8, 20, 16, 12)# Exemple d'utilisation de kwargs
def recette(**kwargs):
for a in kwargs:
# get argument name
arg_name = a
# get argument value
arg_value = kwargs[arg_name]
print(arg_name, " = ", arg_value)
recette(tomate=2, farine="100g", sel=True)1.2 Résultats
Principe
On a vu :
- que toute fonction renvoie un résultat en sortie
- que l’instruction
returnpermet de spécifier ce résultat
Lorsque la fonction est appelée, elle est évaluée à la valeur spécifiée par return, et cette valeur peut alors être récupérée dans une variable et utilisée dans des calculs ultérieurs, et ainsi de suite.
def division(x, y):
return x / ya = division(4, 2)
b = division(9, 3)
division(a, b) # 2 / 3Remarque importante : lorsqu’une instruction return est atteinte dans une fonction, le reste de la fonction n’est pas exécuté.
def test(x):
return x
print("vais-je être affiché ?")
test(3)Renvoyer plusieurs résultats
Une fonction renvoie par définition un résultat, qui peut être tout objet Python. Comment faire si l’on souhaite renvoyer plusieurs résultats ? On peut simplement enregistrer les différents résultats dans un conteneur (liste, tuple, dictionnaire, etc.), qui peut lui contenir un grand nombre d’objets.
def calculs_mathematiques(a, b):
somme = a + b
difference = a - b
produit = a * b
return somme, difference, produit
resultats = calculs_mathematiques(10, 5)
print(resultats)
type(resultats)Par défaut, les retours multiples sont des tuples.
Mais il est également possible de retourner une liste ou un dictionnaire.
def puissance_liste(a):
return [a**2, a**3]
puissance_liste(4)def puissance_dico(nombre):
carre = nombre ** 2
cube = nombre ** 3
return {"carre": a**2, "cube": a**3}
puissance_dico(4)1.3 Lambda fonctions
Il existe une autre manière concise de définir une fonction simple, la lambda fonction.
carre = lambda x: x**2
carre(6)2 Exercices
2.1 Exercice 1
Créer une fonction puissance qui prend en entrée deux nombres x et y et renvoie la fonction puissance \(x^y\).
# Testez votre réponse dans cette cellule2.2 Exercice 2
Écrire une fonction statistiques_descriptives qui :
- prend en entrée une liste de nombre
- renvoie la moyenne et la variance
# Testez votre réponse dans cette cellule2.3 Exercice 3
Écrire une fonction est_pair qui :
- prend en entrée un paramètre
- retourne un booléen pour dire si ce paramètre est pair
Ajouter un test pour vérifier que le paramètre est un entier.
# Testez votre réponse dans cette cellule2.4 Exercice 4
Écrire une fonction qui :
- prend en entrée une liste d’éléments quelconques
- renvoie une nouvelle liste constituée des éléments uniques de la liste initiale
- permet via un paramètre optionnel de trier ou non la liste finale par ordre alphanumérique (le comportement par défaut est de ne pas trier).
# Testez votre réponse dans cette cellule2.5 Exercice 5
Les fonctions récursives sont des fonctions qui s’appellent elles-mêmes dans le corps de la fonction, ce qui entraîne des appels infinis jusqu’à atteindre un critère d’arrêt (voir exemple du triangle de Pascal ci-dessous).
Coder de manière récursive la fonction factoriel.
def triangle_pascal(n):
if n == 0:
return [[1]] # Condition d'arrêt
else:
triangle = triangle_pascal(n - 1) # Appel récursif pour obtenir les lignes précédentes
prev_row = triangle[-1] # Récupérer la dernière ligne générée
new_row = [1] # Premier élément de la nouvelle ligne
# Calculer les éléments de la nouvelle ligne
for i in range(len(prev_row) - 1):
new_row.append(prev_row[i] + prev_row[i + 1])
new_row.append(1) # Dernier élément de la nouvelle ligne
triangle.append(new_row) # Ajouter la nouvelle ligne au triangle
return triangle
print('\n'.join(['\t'.join(map(str, row)) for row in triangle_pascal(10)]))# Testez votre réponse dans cette cellule2.6 Exercice 6
Écrire une fonction appliquer_fonction_liste qui :
- prend en paramètre :
- une liste d’entiers
- une fonction
- retourne la liste à laquelle on a appliqué la fonction
Exemple :
appliquer_fonction_liste([1, 2, 3, 4], lambda x: x**2) -> [1, 4, 9, 16]
# Testez votre réponse dans cette cellule