fiche mémo : 2.2. Fonctions et obtention de l'aide.¶
Appel de fonctions, définition de nos propres fonctions, et utilisation de la documentation intégrée de Python¶
Vincent GODARD - V1 - 25/02/2025¶
Cours Introduction à la programmation¶
Département de géographie - L3 - Université de Paris 8¶
Traduction librement (largement) inspiré de : https://www.kaggle.com/code/colinmorris/functions-and-getting-help
Sources :
Kaggle : https://www.kaggle.com/learn
Python Tutorial : https://www.w3schools.com/python/default.asp
Cours de Python : https://python.sdv.u-paris.fr/00_avant_propos/
Téléchargement des documents nécessaires :
Dossier compressé à télécharger => (pas utile ici).
Vous avez déjà vu et utilisé des fonctions telles que print et abs. Mais Python possède bien d'autres fonctions, et définir vos propres fonctions est une partie importante de la programmation Python.
Dans cette leçon, vous en apprendrez davantage sur l'utilisation et la définition des fonctions.
1. Obtenir de l'aide¶¶
Vous avez vu la fonction abs dans le tutoriel précédent, mais que faire si vous avez oublié à quoi elle sert ?
La fonction help() est probablement la fonction Python la plus importante que vous puissiez apprendre. Si vous vous souvenez de l'utilisation de help(), vous détenez la clé pour comprendre la plupart des autres fonctions.
Voici un exemple :
help(round)
Ce qui peut se traduire par :
Aide sur la fonction intégrée round dans les modules intégrés :
round(number, ndigits=None)
Arrondir un nombre à une précision donnée en chiffres décimaux.
La valeur de retour est un entier si ndigits est omis ou None.
Sinon, la valeur de retour a le même type que le nombre. ndigits peut être négatif.
## Que se passe-t-il si ndigits = -1 pour number = 13.135 ?
round(13.135,-1)
help() affiche deux choses :
l'en-tête de cette fonction round(number, ndigits=None). Dans ce cas, cela nous indique que round() prend un argument que nous pouvons décrire comme number. De plus, nous pouvons éventuellement donner un argument séparé qui pourrait être décrit comme ndigits.
Une brève description en anglais de ce que fait la fonction.
Piège courant : lorsque vous recherchez une fonction, n'oubliez pas de transmettre le nom de la fonction elle-même, et non le résultat de l'appel de cette fonction.
Que se passe-t-il si nous appelons help lors d'un appel à la fonction round() ? Affichez la sortie de la cellule ci-dessous pour voir.
help(round(-2.01))
Python évalue une expression comme celle-ci de l'intérieur vers l'extérieur. Il calcule d'abord la valeur de round(-2.01), puis il fournit de l'aide sur la sortie de cette expression.
(Et il s'avère qu'il a beaucoup à dire sur les entiers ! Après avoir parlé plus tard des objets, des méthodes et des attributs en Python, la sortie d'aide ci-dessus aura plus de sens.)
round() est une fonction très simple avec une courte "chaîne de documentation" (docstring. help). celle-ci s'illustre encore plus lorsqu'il s'agit de fonctions plus complexes et configurables comme print. Ne vous inquiétez pas si la sortie suivante semble impénétrable... pour l'instant, voyez simplement si vous pouvez tirer quelque chose de nouveau de cette aide.
help(print)
Aide sur la fonction intégrée print dans les modules intégrés :
print(...) print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
Imprime les valeurs dans un flux, ou dans sys.stdout par défaut.
Arguments de mot-clé facultatifs :
file : un objet de type fichier (flux) ; par défaut, le sys.stdout actuel.
sep : chaîne insérée entre les valeurs (séparateur), par défaut un espace.
end : chaîne ajoutée après la dernière valeur, par défaut une nouvelle ligne.
flush : s'il faut forcer le vidage du flux.
Si vous le cherchiez, vous pourriez apprendre que print peut prendre un argument appelé sep, et que cela décrit ce que nous mettons entre tous les autres arguments lorsque nous les imprimons.
2. Définition des fonctions¶¶
Les fonctions intégrées sont très utiles, mais nous ne pouvons pas aller plus loin avec elles avant de devoir commencer à définir nos propres fonctions. Vous trouverez ci-dessous un exemple simple.
def least_difference(a, b, c):
diff1 = abs(a - b)
diff2 = abs(b - c)
diff3 = abs(a - c)
return min(diff1, diff2, diff3)
Cela crée une fonction appelée least_difference, qui prend trois arguments, a, b et c.
Les fonctions commencent par un en-tête introduit par le mot-clé def. Le bloc de code indenté qui suit le ":" est exécuté lorsque la fonction est appelée.
return est un autre mot-clé associé de manière unique aux fonctions. Lorsque Python rencontre une instruction return, il quitte immédiatement la fonction et transmet la valeur à sa droite au contexte d'appel.
La fonction least_difference calcule la plus petite différence absolue entre trois nombres donnés.
Fonctionnement :
La fonction calcule trois différences absolues :
diff1 : Différence absolue entre a et b
diff2 : Différence absolue entre b et c
diff3 : Différence absolue entre a et c
La fonction abs() est utilisée pour obtenir la valeur absolue de chaque différence.
La fonction min() est ensuite utilisée pour trouver la plus petite valeur parmi les trois différences calculées.
Valeur de retour : La fonction retourne un nombre (généralement un entier ou un flottant) qui représente la plus petite différence absolue entre les trois paires de nombres possibles.
Est-ce que le code source indique clairement ce que fait least_difference() ? Si nous n'en sommes pas sûrs, nous pouvons toujours l'essayer sur quelques exemples :
## Un essai à la fois
print(least_difference(1, 10, 100))
Qui se décompose en :
least_difference(1, 10, 100):
Différences : |1-10| = 9, |10-100| = 90, |1-100| = 99
La plus petite différence est 9
## Trois essais d'un coup !
print(
least_difference(1, 10, 100),
least_difference(1, 10, 10),
least_difference(5, 6, 7), # Python autorise les virgules de fin dans les listes d'arguments. N'est-ce pas sympa (How nice is that?) ?
)
Ou peut-être que la fonction help() peut nous dire quelque chose à ce sujet.
Aide sur la fonction least_difference dans le module __main__ :
least_difference(a, b, c)
Python n'est pas assez intelligent pour lire mon code et le transformer en une belle description en anglais. Cependant, lorsque j'écris une fonction, je peux fournir une description dans ce qu'on appelle la docstring.
3. Docstrings¶
Docstrings : raccourci pour DOCumentation STRINGs, permet d'afficher un commentaire sur le fonctionnement de la fonction, par exemple.
def least_difference(a, b, c):
"""Renvoie la plus petite différence entre deux nombres
parmi a, b et c.
>>> least_difference(1, 5, -5)
4
"""
diff1 = abs(a - b)
diff2 = abs(b - c)
diff3 = abs(a - c)
return min(diff1, diff2, diff3)
La docstring est une chaîne entre guillemets triples (qui peut s'étendre sur plusieurs lignes) qui vient immédiatement après l'en-tête d'une fonction. Lorsque nous appelons help() sur une fonction, elle affiche la docstring.
help(least_difference)
En dehors de cela : les deux dernières lignes de la docstring sont un exemple d'appel de fonction et son résultat. (Le >>> est une référence à l'invite de commande utilisée dans les shells interactifs Python.) Python n'exécute pas l'exemple d'appel - il est juste là pour le bénéfice du lecteur. La convention d'inclure 1 ou plusieurs exemples d'appels dans la docstring d'une fonction est loin d'être universellement observée, mais elle peut être très efficace pour aider quelqu'un à comprendre votre fonction. Pour un exemple concret, consultez cette docstring pour la fonction numpy np.eye (https://github.com/numpy/numpy/blob/v1.14.2/numpy/lib/twodim_base.py#L140-L194).
Les bons programmeurs utilisent des docstrings à moins qu'ils ne prévoient de jeter le code peu de temps après son utilisation (ce qui est rare). Vous devriez donc commencer à écrire des docstrings, vous aussi !
3. Les fonctions qui ne renvoient pas de données¶
Que se passerait-il si nous n'incluions pas le mot-clé return dans notre fonction ?
def least_difference(a, b, c):
"""Return the smallest difference between any two numbers
among a, b and c.
"""
diff1 = abs(a - b)
diff2 = abs(b - c)
diff3 = abs(a - c)
min(diff1, diff2, diff3)
print(
least_difference(1, 10, 100),
least_difference(1, 10, 10),
least_difference(5, 6, 7),
)
Python nous permet de définir de telles fonctions. Le résultat de leur appel est la valeur spéciale None. (Cela ressemble au concept de « null » dans d'autres langages.)
Sans instruction return, least_difference est complètement inutile, mais une fonction avec des effets de bord peut faire quelque chose d'utile sans rien renvoyer. Nous en avons déjà vu deux exemples : print() et help() ne renvoient rien. Nous les appelons uniquement pour leurs effets de bord (mettre du texte à l'écran). D'autres exemples d'effets de bord utiles incluent l'écriture dans un fichier ou la modification d'une entrée.
mystery = print()
print(mystery)
4. Arguments par défaut¶¶
Lorsque nous avons appelé help(print), nous avons vu que la fonction print possède plusieurs arguments optionnels. Par exemple, nous pouvons spécifier une valeur pour sep afin de placer une chaîne spéciale entre nos arguments imprimés :
print(1, 2, 3, sep=' < ')
Mais si nous ne spécifions pas de valeur, sep est traité comme ayant une valeur par défaut de ' ' (un seul espace).
print(1, 2, 3)
L'ajout d'arguments facultatifs avec des valeurs par défaut aux fonctions que nous définissons s'avère assez simple :
def greet(who="Colin"):
print("Hello,", who)
greet()
greet(who="Kaggle")
# (Dans ce cas, nous n’avons pas besoin de spécifier le nom de l’argument, car il est sans ambiguïté.)
greet("world")
## Pourquoi cette fonction :
def greet(who="Colin"):
print("Hello,", who)
greet()
## n'a pas besoin de return ?
Fonction procédurale vs fonction de retour
La fonction greet est ce qu'on appelle une fonction procédurale ou une procédure. Son but principal est d'effectuer une action (dans ce cas, afficher un message) plutôt que de calculer et renvoyer une valeur.
Explication détaillée
1) Objectif de la fonction :
Le but de cette fonction est simplement d'afficher un message de salutation. Elle accomplit cette tâche en utilisant print(), qui affiche directement sur la console.
2) Absence de calcul :
La fonction ne fait aucun calcul dont le résultat devrait être renvoyé et utilisé ailleurs dans le programme.
3) Effet de bord :
L'affichage sur la console est ce qu'on appelle un "effet de bord" en programmation. C'est une action qui modifie l'état du programme ou de son environnement, mais qui ne nécessite pas de valeur de retour.
4) Valeur de retour implicite :
En Python, si une fonction n'a pas d'instruction return explicite, elle renvoie automatiquement None. Cela est suffisant pour ce type de fonction.
5. Fonctions appliquées aux fonctions¶¶
Voici quelque chose d'efficace et puissant, même si cela peut sembler très abstrait au premier abord. Vous pouvez fournir des fonctions comme arguments à d'autres fonctions. Quelques exemples peuvent rendre cela plus clair :
5.1. 1er exemple de fonctions appliquées aux fonctions¶
## La fonction d'origine
def mult_by_five(x):
return 5 * x
def call(fn, arg):
"""Appeler fn sur arg"""
return fn(arg)
def squared_call(fn, arg):
"""Appeler fn sur le résultat de l'appel de fn sur arg"""
return fn(fn(arg))
print(
call(mult_by_five, 1),
squared_call(mult_by_five, 1),
sep='\n', # '\n' est le caractère de nouvelle ligne - il démarre une nouvelle ligne
)
## La fonction documentée
def mult_by_five(x):
"""
Multiplie le nombre donné par 5.
Args:
x (int ou float): Le nombre à multiplier.
Returns:
int ou float: Le résultat de la multiplication de x par 5.
"""
return 5 * x
def call(fn, arg):
"""
Appelle la fonction donnée avec l'argument spécifié.
Args:
fn (fonction): La fonction à appeler.
arg: L'argument à passer à la fonction.
Returns:
Le résultat de l'appel de fn avec arg.
"""
return fn(arg)
def squared_call(fn, arg):
"""
Appelle la fonction donnée deux fois, en utilisant le résultat du premier appel comme argument pour le second.
Args:
fn (fonction): La fonction à appeler.
arg: L'argument initial à passer à la fonction.
Returns:
Le résultat de l'appel de fn(fn(arg)).
"""
return fn(fn(arg))
# Appel des fonctions et affichage des résultats
print(
call(mult_by_five, 1), # Appelle mult_by_five(1), ce qui donne 5
squared_call(mult_by_five, 1), # Appelle mult_by_five(mult_by_five(1)), ce qui donne 25
sep='\n', # Utilise un saut de ligne comme séparateur entre les résultats
)
Explication du code final :
1) call(mult_by_five, 1) appelle mult_by_five avec l'argument 1, ce qui renvoie 5.
2) squared_call(mult_by_five, 1) fait deux choses :
• D'abord, il appelle mult_by_five(1), ce qui donne 5.
• Ensuite, il appelle à nouveau mult_by_five avec ce résultat : mult_by_five(5), ce qui donne 25.
3) La fonction print affiche ces deux résultats (5 et 25) sur des lignes séparées grâce à l'argument sep='\n'.
Ce code démontre l'utilisation de fonctions d'ordre supérieur en Python, où les fonctions peuvent être passées comme arguments à d'autres fonctions.
5.2. 2ème exemple de fonctions appliquées aux fonctions¶
Les fonctions qui opèrent sur d'autres fonctions sont appelées « fonctions d'ordre supérieur ». Vous n'écrirez probablement pas les vôtres avant un certain temps. Mais il existe des fonctions d'ordre supérieur intégrées à Python que vous pourriez trouver utiles à appeler.
Voici un exemple intéressant utilisant la fonction max.
Par défaut, max renvoie le plus grand de ses arguments. Mais si nous passons une fonction en utilisant l'argument key facultatif, elle renvoie l'argument x qui maximise key(x) (alias le « argmax »).
## La fonction d'origine
def mod_5(x): # mod est un reccourci pour modulo
"""Renvoie le reste de x après avoir divisé par 5"""
return x % 5
print(
'Quel nombre est le plus grand ?',
max(100, 51, 14),
'Quel nombre est le plus grand modulo 5 ?',
max(100, 51, 14, key=mod_5),
sep='\n',
)
## La fonction documentée
def mod_5(x):
"""
Renvoie le reste de x après avoir divisé par 5.
Args:
x (int): Le nombre à diviser par 5.
Returns:
int: Le reste de la division de x par 5 (0, 1, 2, 3, ou 4).
"""
return x % 5
print(
'Quel nombre est le plus grand ?',
max(100, 51, 14),
'Quel nombre est le plus grand modulo 5 ?',
max(100, 51, 14, key=mod_5),
sep='\n',
)
Explication détaillée du code :
1) La fonction mod_5(x) :
• Cette fonction utilise l'opérateur modulo % pour calculer le reste de la division de x par 5.
• Par exemple, mod_5(7) renverrait 2, car 7 divisé par 5 donne 1 avec un reste de 2.
2) Premier appel à max() :
• max(100, 51, 14) compare ces trois nombres et renvoie le plus grand, qui est 100.
3) Deuxième appel à max() avec key=mod_5 :
• max(100, 51, 14, key=mod_5) utilise la fonction mod_5 comme critère de comparaison.
• Pour chaque nombre, Python calcule d'abord son modulo 5 :
○ 100 % 5 = 0
○ 51 % 5 = 1
○ 14 % 5 = 4
• Ensuite, il choisit le nombre qui a donné le plus grand résultat avec mod_5, qui est 14 dans ce cas.
4) La fonction print() :
• Affiche quatre éléments sur des lignes séparées grâce à sep='\n' :
○ La chaîne "Quel nombre est le plus grand ?"
○ Le résultat de max(100, 51, 14)
○ La chaîne "Quel nombre est le plus grand modulo 5 ?"
○ Le résultat de max(100, 51, 14, key=mod_5)
Ce code démontre comment l'utilisation de la fonction key dans max() peut modifier le critère de comparaison, permettant des comparaisons basées sur des transformations des valeurs originales plutôt que sur les valeurs elles-mêmes.
5.3. 3ème exemple de fonctions appliquées aux fonctions¶
## Comment afficher tous les chiffres pairs entre 0 et 10
def print_modulo():
""" Affiche tous les chiffres pairs compris entre 0 et 10 """
for i in range(10):
if i % 2 == 0:
print(i)
print_modulo()
## Impression de la documentation (docstring)
print(print_modulo.__doc__)
## Comment afficher tous les chiffres impairs entre 0 et 10
def print_modulo():
""" Affiche tous les chiffres impairs compris entre 0 et 10 """
for i in range(10):
if i % 2 != 0:
print(i)
print_modulo()