Ecrire des fonctions en Python
Mise à jour :
Imaginez que vous devez expliquer à quelqu’un comment préparer un café. Au lieu de répéter chaque fois toute la procédure, vous pourriez simplement dire “prépare un café”. C’est exactement ce que font les fonctions en Python : elles vous permettent de donner un nom à une série d’actions et de les réutiliser facilement.
Dans ce guide, vous apprendrez à créer vos propres “recettes” de code que vous pourrez utiliser encore et encore, rendant vos programmes plus organisés et plus faciles à comprendre.
Qu’est-ce qu’une fonction ?
Pensez à une fonction comme à une machine : vous lui donnez quelque chose en entrée, elle fait son travail, et vous récupérez un résultat en sortie. Parfois, elle peut juste faire une action sans rien vous rendre.
En Python, une fonction ressemble à ceci :
def nom_de_la_fonction(): # Ce que fait la fonction print("Hello !")
Le mot def
dit à Python : “Je vais créer une nouvelle fonction”. Après, vous
choisissez un nom (ici nom_de_la_fonction
), puis vous mettez des parenthèses
()
.
Exemple concret - Une fonction qui dit bonjour :
def dire_bonjour(): print("Bonjour ! Comment allez-vous ?")
Pour utiliser cette fonction (on dit “l’appeler”), écrivez simplement :
dire_bonjour() # Affiche "Bonjour ! Comment allez-vous ?"
C’est aussi simple que ça ! Vous venez de créer votre première fonction.
Donner des informations à vos fonctions
Souvent, vos fonctions ont besoin d’informations pour travailler. C’est comme quand vous demandez à quelqu’un de vous préparer un sandwich : vous devez préciser quel type de pain et quelle garniture vous voulez.
En programmation, ces informations s’appellent des paramètres (quand vous définissez la fonction) et des arguments (quand vous l’utilisez).
Fonction avec un paramètre
def dire_bonjour_a(nom): print(f"Bonjour, {nom} !")
# Utilisationdire_bonjour_a("Alice") # Affiche "Bonjour, Alice !"dire_bonjour_a("Bob") # Affiche "Bonjour, Bob !"
Ici, nom
est le paramètre (la “case vide” dans votre fonction), et “Alice” ou
“Bob” sont les arguments (les valeurs que vous donnez).
Paramètres avec valeurs par défaut
Parfois, vous voulez que votre fonction fonctionne même si on ne lui donne pas toutes les informations. C’est comme avoir une recette avec des ingrédients optionnels :
def dire_bonjour_a(nom="cher ami"): print(f"Bonjour, {nom} !")
dire_bonjour_a("Marie") # Affiche "Bonjour, Marie !"dire_bonjour_a() # Affiche "Bonjour, cher ami !"
Si vous ne précisez pas de nom, la fonction utilise “cher ami” par défaut.
Récupérer un résultat de vos fonctions
Jusqu’à présent, nos fonctions ne font qu’afficher du texte. Mais souvent, vous voulez qu’elles vous rendent un résultat que vous pouvez utiliser ailleurs. C’est comme utiliser une calculatrice : vous appuyez sur des boutons et elle vous donne un résultat.
Le mot magique pour cela est return
:
def additionner(a, b): resultat = a + b return resultat
# Utilisationma_somme = additionner(5, 3)print(ma_somme) # Affiche 8
# Ou directementprint(additionner(10, 7)) # Affiche 17
Analogie simple : Imaginez une fonction comme une usine :
- Vous donnez des matières premières (les paramètres)
- L’usine fait son travail
- Elle vous rend un produit fini (la valeur de retour)
Important : Si votre fonction n’a pas de return
, elle renvoie
automatiquement None
(c’est comme si elle ne rendait rien).
Exemple pratique : créer une calculatrice simple
Maintenant que vous connaissez les bases, créons quelques fonctions utiles :
def calculer_aire_rectangle(longueur, largeur): """Calcule l'aire d'un rectangle""" aire = longueur * largeur return aire
def est_nombre_pair(nombre): """Vérifie si un nombre est pair""" if nombre % 2 == 0: return True else: return False
# Utilisationprint(calculer_aire_rectangle(5, 3)) # Affiche 15print(est_nombre_pair(4)) # Affiche Trueprint(est_nombre_pair(7)) # Affiche False
Ces fonctions sont utiles car vous pouvez les réutiliser partout dans votre programme sans réécrire le code.
🚀 Concepts avancés (optionnels pour débuter)
Les sections suivantes couvrent des concepts plus avancés. Vous pouvez les explorer une fois que vous maîtrisez les bases ci-dessus.
Les fonctions imbriquées
En Python, il est possible de définir une fonction à l’intérieur d’une autre. Cela peut être utile pour encapsuler une logique spécifique ou créer des closures.
Les fonctions imbriquées sont particulièrement utiles quand vous avez besoin de créer des fonctions spécialisées qui n’existent que dans un contexte précis. Elles permettent d’organiser le code en gardant des fonctions auxiliaires proches de la fonction principale qui les utilise.
Un cas typique est la création de fonctions personnalisées selon des paramètres, comme construire différents types de calculatrices ou de validateurs. Elles sont également essentielles pour implémenter des décorateurs personnalisés et créer des closures qui mémorisent des valeurs de leur environnement parent.
Exemple de fonction imbriquée :
def operation(arithmetique): def addition(a, b): return a + b def soustraction(a, b): return a - b if arithmetique == "addition": return addition else: return soustraction
fonction_calc = operation("addition")print(fonction_calc(10, 5)) # Affiche 15
Les fonctions courtes (lambda) - Version simplifiée
Parfois, vous avez besoin d’une fonction très simple pour une tâche rapide. Au lieu d’écrire une fonction complète, vous pouvez utiliser ce qu’on appelle une “lambda” :
# Au lieu d'écrire :def multiplier(x, y): return x * y
# Vous pouvez écrire :multiplier = lambda x, y: x * y
print(multiplier(4, 5)) # Affiche 20
Quand utiliser lambda ? Pour des fonctions très simples d’une seule ligne. C’est comme utiliser une calculatrice de poche au lieu d’installer un logiciel complet.
Les fonctions lambda sont idéales pour les opérations de transformation
rapides sur des collections de données, notamment avec les fonctions map()
,
filter()
et sorted()
. Elles permettent d’éviter de créer des fonctions
nommées pour des calculs ponctuels et simples.
Elles sont particulièrement appréciées dans le traitement de données (tri personnalisé, filtrage, transformations mathématiques) et dans la programmation fonctionnelle. Les lambdas excellent aussi comme fonctions de rappel (callbacks) dans les interfaces graphiques ou les API qui attendent une fonction simple en paramètre.
Conseil pour débuter : Ne vous préoccupez pas trop des lambdas au début. Les
fonctions normales avec def
sont plus claires et suffisantes.
Les arguments variables (*args et **kwargs)
Pour créer des fonctions acceptant un nombre variable d’arguments, on
utilise *args
pour les arguments positionnels et **kwargs
pour les arguments
nommés.
Les arguments variables sont essentiels pour créer des fonctions flexibles
qui peuvent traiter un nombre indéterminé de paramètres. *args
est parfait
pour des fonctions comme somme()
, maximum()
, ou concatener()
où vous ne
savez pas à l’avance combien de valeurs vous allez recevoir.
**kwargs
est indispensable pour créer des fonctions de configuration où
vous voulez accepter des options nommées variées, ou pour transmettre des
paramètres à d’autres fonctions. Ces mécanismes sont couramment utilisés dans
les frameworks web, les APIs, et pour créer des wrappers autour de
fonctions existantes.
Exemple avec *args
:
def somme(*nombres): total = 0 for nombre in nombres: total += nombre return total
print(somme(1, 2, 3, 4)) # Affiche 10
Exemple avec **kwargs
:
def afficher_infos(**infos): for cle, valeur in infos.items(): print(f"{cle} : {valeur}")
afficher_infos(nom="Alice", age=30, ville="Paris")# Affiche :# nom : Alice# age : 30# ville : Paris
Les annotations de type
Depuis Python 3.5, il est possible d’ajouter des annotations de type aux paramètres et au type de retour des fonctions. Cela améliore la lisibilité du code et facilite la maintenance.
Exemple d’annotations de type :
def saluer(nom: str) -> None: print(f"Bonjour, {nom} !")
Ces annotations sont informatives et n’affectent pas l’exécution du programme.
Les fonctions récursives
Une fonction récursive est une fonction qui s’appelle elle-même. C’est utile pour résoudre des problèmes pouvant être décomposés en sous-problèmes similaires.
La récursivité est naturelle pour traiter des structures hiérarchiques comme les arbres de fichiers, les menus imbriqués, ou les structures de données arborescentes. Elle excelle dans la résolution de problèmes mathématiques (factorielles, suites de Fibonacci, calculs combinatoires) et les algorithmes de tri (tri rapide, tri fusion).
Les fonctions récursives sont également utiles pour parcourir des structures complexes dont la profondeur n’est pas connue à l’avance, comme analyser du JSON imbriqué ou naviguer dans des répertoires avec des sous-dossiers. Cependant, attention aux performances et aux limites de récursion pour de grandes données.
Exemple de fonction récursive pour calculer la factorielle :
def factorielle(n): if n == 0: return 1 else: return n * factorielle(n - 1)
print(factorielle(5)) # Affiche 120
Bonnes pratiques pour écrire des fonctions en Python
Pour écrire des fonctions efficaces et maintenables en Python, il est important de suivre certaines bonnes pratiques. Ces principes améliorent la lisibilité du code, facilitent la collaboration entre développeurs et réduisent les risques d’erreurs.
Nommer les fonctions de manière claire et descriptive
Les noms de fonctions doivent refléter précisément leur rôle. Un nom clair permet de comprendre rapidement ce que fait la fonction sans avoir à lire son code interne.
Exemple :
def calculer_moyenne(notes): return sum(notes) / len(notes)
Garder les fonctions courtes et spécifiques
Une fonction doit accomplir une seule tâche ou fonctionnalité spécifique. Cela facilite la compréhension, le test et la maintenance du code.
Exemple :
Au lieu de créer une fonction qui effectue plusieurs opérations, il est préférable de la diviser en fonctions plus petites.
def lire_donnees(fichier): # Code pour lire les données pass
def analyser_donnees(donnees): # Code pour analyser les données pass
def afficher_resultats(resultats): # Code pour afficher les résultats pass
Utiliser les docstrings pour documenter les fonctions
Les docstrings sont des chaînes de caractères placées immédiatement après la
définition d’une fonction pour la documenter. Elles permettent d’expliquer le
rôle de la fonction, ses paramètres, ses valeurs de retour et d’autres
informations utiles. En Python, les docstrings sont accessibles via
l’attribut __doc__
de la fonction ou avec la fonction help()
.
Exemple de docstring :
def additionner(a, b): """ Additionne deux nombres et renvoie le résultat.
:param a: Le premier nombre à additionner. :param b: Le second nombre à additionner. :return: La somme de a et b. """ return a + b
Dans cet exemple, la docstring explique ce que fait la fonction additionner
,
décrit les paramètres a
et b
et indique ce que la fonction retourne.
Cette documentation est précieuse pour les autres développeurs ou pour soi-même
lors de la maintenance du code.
Pour consulter la docstring, il est possible d’utiliser help()
:
help(additionner)
Ce qui affichera :
Help on function additionner in module __main__:
additionner(a, b) Additionne deux nombres et renvoie le résultat.
:param a: Le premier nombre à additionner. :param b: Le second nombre à additionner. :return: La somme de a et b.
Bonnes pratiques pour les docstrings :
- Commencer par une phrase courte résumant le rôle de la fonction.
- Décrire les paramètres et les valeurs de retour de manière claire.
- Utiliser un style cohérent, comme le format reStructuredText ou Google Docstrings.
- Éviter les informations redondantes ou évidentes.
- Mettre à jour la docstring si la fonction est modifiée.
Les docstrings peuvent également être utilisées par des outils de génération de documentation automatique, ce qui facilite la création de documents complets sur le code.
Éviter les effets de bord
Une fonction doit idéalement être pure, c’est-à-dire qu’elle ne modifie pas l’état du programme en dehors de son scope et ne dépend pas de variables externes. Cela rend la fonction plus prévisible et facilite le débogage.
Exemple :
Éviter de modifier des variables globales à l’intérieur d’une fonction.
# Moins recommandécompteur = 0
def incrementer_compteur(): global compteur compteur += 1
# Mieuxdef incrementer(compteur): return compteur + 1
Utiliser les annotations de type
Les annotations de type améliorent la lisibilité du code et aident à détecter les erreurs potentielles. Elles indiquent les types attendus pour les paramètres et la valeur de retour.
Exemple :
def saluer(nom: str) -> None: print(f"Bonjour, {nom} !")
Gérer les exceptions de manière appropriée
Il est important de prévoir et de gérer les erreurs potentielles au sein des fonctions pour éviter les plantages inattendus.
Exemple :
def diviser(a, b): """ Divise a par b et gère la division par zéro. """ try: return a / b except ZeroDivisionError: print("Erreur : division par zéro.") return None
Éviter les arguments par défaut mutables
Utiliser des objets mutables comme valeurs par défaut peut entraîner des comportements inattendus.
Exemple problématique :
def ajouter_element(element, liste=[]): liste.append(element) return liste
À chaque appel sans spécifier la liste, l’élément sera ajouté à la même liste, ce qui peut causer des bugs.
Solution :
def ajouter_element(element, liste=None): if liste is None: liste = [] liste.append(element) return liste
Respecter les conventions de style
Suivre les conventions de style, comme celles définies dans PEP 8 ↗, rend le code plus cohérent et facile à lire.
Exemples de conventions :
- Utiliser des noms de fonctions en minuscules avec des underscores :
calculer_moyenne
- Indenter le code avec quatre espaces
- Limiter la longueur des lignes à 79 caractères
Exercices pratiques
Vous avez maintenant les bases pour écrire des scripts Python simples et utiliser des structures de données comme les listes, les tuples et les dictionnaires. Pour consolider vos connaissances, il est temps de mettre en pratique ce que vous avez appris.
👉 Travaux pratiques : TP 02 : Les fonctions ↗
Ces exercices couvrent notamment
- Définir et appeler une fonction
- Manipuler les paramètres (positionnels, nommés, valeurs par défaut)
- Retourner des valeurs et documenter son code
- Utiliser
*args
et**kwargs
- Créer des lambdas et des fonctions imbriquées (closures)
- Ajouter des annotations de type et des docstrings claires
- Comprendre la récursivité
- Valider ses compétences grâce à un challenge automatisé
Pourquoi pratiquer ?
La pratique est essentielle pour maîtriser un langage de programmation. En résolvant des exercices, vous renforcerez votre compréhension des concepts fondamentaux et développerez votre capacité à écrire du code efficace et lisible. Vous apprendrez également à identifier et à corriger les erreurs dans votre code, ce qui est une compétence cruciale pour tout développeur.
Comment procéder ?
Clonez le dépôt et suivez les consignes pour réaliser les étapes.
Contrôle de connaissances
Pourquoi ce contrôle ?
Cet contrôle va vous permettre de valider vos connaissances sur le sujet abordé dans le guide. Il comporte des QCM, des questions vrai/faux et des réponses ouvertes à un mot.
🕒 Le chronomètre commence dès que vous cliquez sur Démarrer le test. Vous devrez terminer l’examen avant la fin du temps imparti.
🎯 Pour réussir, vous devez obtenir au moins 80% de bonnes réponses.
💡 Je ne fournis pas directement les réponses aux questions. Cependant, si certaines sont complexes, des pistes d’explication pourront être proposées dans le guide ou après l’examen.
Bonne chance ! 🚀
Conclusion
En maîtrisant les différents aspects des fonctions, tels que les paramètres, les arguments, les fonctions anonymes (lambda), les décorateurs, les générateurs et les bonnes pratiques de documentation, vous pouvez créer des programmes plus efficaces et élégants.
En appliquant les principes abordés dans ce guide, il est possible d’écrire des fonctions robustes et performantes, tout en respectant les standards de qualité du code en Python. La pratique régulière et l’expérimentation avec différents types de fonctions contribueront à renforcer les compétences en programmation et à tirer pleinement parti de la puissance du langage Python.