Maîtrise de Python Intermédiaire
Maîtrise des fonctions
Au-delà des bases des fonctions
Vous savez déjà comment définir et appeler une fonction en Python. Maintenant, explorons comment rendre ces fonctions plus dynamiques et puissantes. Les fonctions en Python ne sont pas de simples blocs de code ; ce sont des objets à part entière, ce qui ouvre un monde de possibilités.
Commençons par une question courante : comment créer une fonction qui accepte un nombre variable d'arguments ? C'est là qu'interviennent *args et **kwargs.
Arguments flexibles avec *args et **kwargs
Imaginez que vous écrivez une fonction qui additionne des nombres. Vous pourriez la définir pour deux ou trois arguments, mais que faire si vous voulez en additionner dix ? Ou seulement un ? C'est là que *args est utile. Il permet à une fonction de recevoir un nombre quelconque d'arguments positionnels, qu'elle regroupe dans un tuple.
def additionner_tout(*nombres):
total = 0
for nombre in nombres: # nombres est un tuple
total += nombre
return total
print(additionner_tout(1, 5, 3))
# Sortie: 9
print(additionner_tout(10, 20, 30, 40))
# Sortie: 100
De même, vous permet de gérer un nombre arbitraire d'arguments nommés (keyword arguments). Python les rassemble dans un dictionnaire, où les noms des arguments deviennent les clés.
def afficher_profil_utilisateur(**infos):
print("Profil utilisateur :")
for cle, valeur in infos.items(): # infos est un dictionnaire
print(f"- {cle.capitalize()}: {valeur}")
afficher_profil_utilisateur(nom="Alice", age=30, ville="Paris")
# Sortie:
# Profil utilisateur :
# - Nom: Alice
# - Age: 30
# - Ville: Paris
Règle de base :
*argspour une liste d'arguments sans nom,**kwargspour une liste d'arguments nommés. Vous pouvez les utiliser ensemble, mais*argsdoit toujours précéder**kwargsdans la définition de la fonction.
Portée et Closures
Comprendre où Python cherche une variable est crucial pour éviter les bugs. L'ordre est défini par la règle : Local, Enclosing (englobant), Global, et Built-in (intégré).
- Local : L'intérieur de la fonction actuelle.
- Enclosing : L'intérieur de toute fonction imbriquée (englobante).
- Global : Le niveau supérieur du module ou du script.
- Built-in : Les noms pré-définis en Python, comme
print()oulen().
Cette règle mène à un concept puissant : les closures (fermetures). Une closure est une fonction qui se souvient de l'environnement dans lequel elle a été créée, même après que la fonction externe a terminé son exécution. Cela se produit lorsqu'une fonction imbriquée fait référence à une variable de sa fonction englobante (la portée "Enclosing").
def create_multiplier(n):
# 'n' est dans la portée englobante (Enclosing)
def multiplier(x):
# 'x' est dans la portée locale (Local)
return x * n # 'n' est capturé par la closure
return multiplier
# La fonction create_multiplier a terminé, mais 'n' est mémorisé.
double = create_multiplier(2)
triple = create_multiplier(3)
print(double(10)) # Sortie: 20
print(triple(10)) # Sortie: 30
Ici, double et triple sont des closures. Chacune se souvient de la valeur de n avec laquelle elle a été créée.
Fonctions Lambda et Décorateurs
Parfois, vous avez besoin d'une petite fonction anonyme pour une tâche rapide, sans la formalité d'une instruction def. Entrez les expressions : de petites fonctions d'une seule ligne.
# Trier une liste de tuples par le deuxième élément
points = [(1, 5), (4, 2), (9, 8)]
# Utilisation d'une lambda comme clé de tri
points.sort(key=lambda p: p[1])
print(points)
# Sortie: [(4, 2), (1, 5), (9, 8)]
Enfin, les décorateurs sont une manière très pythonique de modifier ou d'améliorer des fonctions. Un décorateur est une fonction qui prend une autre fonction en argument, y ajoute une fonctionnalité, et retourne la fonction modifiée. C'est comme emballer une fonction dans une autre.
def mon_decorateur(func):
def wrapper():
print("Quelque chose se passe avant l'appel de la fonction.")
func()
print("Quelque chose se passe après l'appel de la fonction.")
return wrapper
@mon_decorateur
def dis_bonjour():
print("Bonjour !")
dis_bonjour()
# Sortie:
# Quelque chose se passe avant l'appel de la fonction.
# Bonjour !
# Quelque chose se passe après l'appel de la fonction.
La syntaxe @mon_decorateur est juste un sucre syntaxique pour dis_bonjour = mon_decorateur(dis_bonjour). Les décorateurs sont largement utilisés en Python pour la journalisation, la gestion des permissions, la mise en cache, et bien plus encore.
Maintenant que vous comprenez ces concepts avancés, testons vos connaissances.
Que fait **kwargs dans la définition d'une fonction Python ?
Selon la règle LEGB, quel est l'ordre de recherche des variables en Python ?
Maîtriser ces techniques vous permettra d'écrire un code Python non seulement fonctionnel, mais aussi élégant, modulaire et réutilisable.