Aller au contenu

Ecrire des fonctions en Python

Mise à jour :

logo python

Les fonctions sont au cœur de la programmation en Python. Elles permettent de structurer le code, de le rendre plus lisible et de réutiliser des blocs sans avoir à les réécrire. En maîtrisant les fonctions, les développeurs peuvent écrire des programmes plus efficaces et maintenables.

Comprendre les fonctions

Une fonction est un bloc de code réutilisable qui exécute une tâche spécifique. Pour définir une fonction, j’utilise le mot-clé def suivi du nom de la fonction et des parenthèses contenant éventuellement des paramètres. Le code à exécuter se trouve dans le bloc indenté suivant.

Par exemple :

def saluer():
print("Bonjour !")

Pour appeler cette fonction, on écrit simplement :

saluer() # Affiche "Bonjour !"

Les paramètres et les arguments

Les fonctions peuvent accepter des paramètres pour traiter des données variables. Les paramètres sont les variables énumérées entre parenthèses dans la définition de la fonction. Lors de l’appel de la fonction, les valeurs fournies sont appelées arguments.

Exemple avec un paramètre :

def saluer(nom):
print(f"Bonjour, {nom} !")
saluer("Alice") # Affiche "Bonjour, Alice !"

Il est également possible de définir des paramètres par défaut. Si aucun argument n’est fourni lors de l’appel, ces paramètres prendront la valeur par défaut.

Exemple avec paramètre par défaut :

def saluer(nom="cher visiteur"):
print(f"Bonjour, {nom} !")
saluer() # Affiche "Bonjour, cher visiteur !"

Les valeurs de retour

Une fonction peut renvoyer une valeur en utilisant le mot-clé return. Cette valeur peut ensuite être utilisée ailleurs dans le programme.

Exemple de fonction avec valeur de retour :

def additionner(a, b):
return a + b
resultat = additionner(5, 3)
print(resultat) # Affiche 8

Si aucune valeur n’est spécifiée après return, la fonction renvoie None.

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.

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 anonymes (lambda)

Les fonctions anonymes ou lambda, sont des fonctions sans nom définies en une seule ligne. Elles sont utiles pour des opérations simples et rapides.

Exemple de fonction lambda :

multiplication = lambda x, y: x * y
print(multiplication(4, 5)) # Affiche 20

Les lambda sont souvent utilisées avec des fonctions intégrées comme map(), filter() ou sorted().

Exemple avec map() :

nombres = [1, 2, 3, 4]
carres = list(map(lambda x: x**2, nombres))
print(carres) # Affiche [1, 4, 9, 16]

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.

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.

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 01 : 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.