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

Exercices

Objectif :

Cet exercice est conçu pour vous familiariser avec les fonctions en Python, et plus précisément l’utilisation de différents types d’arguments : arguments obligatoires, arguments par défaut, arguments nommés, et arguments avec liste (variadics).

Vous devez une fonction qui calcule le prix total d’un repas dans un restaurant. Le prix total dépend des éléments suivants :

  • Le prix des plats (entrée, plat principal, dessert).
  • Un pourcentage de taxe appliqué au total (par défaut 10%).
  • Un pourcentage de pourboire que le client peut choisir de donner (par défaut 15%).

Détails des arguments de la fonction :

  • Arguments obligatoires :

    • prix_entree : Le prix de l’entrée.
    • prix_plat : Le prix du plat principal.
    • prix_dessert : Le prix du dessert.
  • Arguments optionnels avec des valeurs par défaut :

    • taxe : Le pourcentage de taxe à ajouter au total (par défaut 10%).
    • pourboire : Le pourcentage de pourboire à ajouter au total (par défaut 15%).
  • Arguments variadics :

    • *extras : Une liste de prix d’extras (par exemple boissons ou autres plats ajoutés). Ces éléments sont optionnels.

La fonction doit renvoyer le prix total du repas en incluant la taxe et le pourboire, ainsi que les extras, s’il y en a.

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

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.