Aller au contenu

Ecrire des fonctions en Python

Mise à jour :

logo python

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} !")
# Utilisation
dire_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
# Utilisation
ma_somme = additionner(5, 3)
print(ma_somme) # Affiche 8
# Ou directement
print(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
# Utilisation
print(calculer_aire_rectangle(5, 3)) # Affiche 15
print(est_nombre_pair(4)) # Affiche True
print(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
# Mieux
def 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.