Python - Closures: Guide Ultime pour les Débutants
Bonjour à toi, aspirant programmeur Python ! Aujourd'hui, nous allons entamer un voyage passionnant dans le monde des closures. Ne t'inquiète pas si tu n'as jamais entendu ce terme avant – à la fin de ce tutoriel, tu ne comprendras pas seulement ce qu'est une closure, mais tu seras également en mesure de les créer et de les utiliser dans ton propre code. Alors, plongeons-y !
Qu'est-ce qu'une Closure ?
Imagine que tu as une boîte magique qui peut se souvenir de choses même après l'avoir fermée. C'est essentiellement ce qu'est une closure en programmation ! En Python, une closure est un objet fonction qui se souvient des valeurs de la portée englobante même si elles ne sont pas présentes en mémoire.
Cela te semble confus ? Décomposons-le :
- C'est une fonction à l'intérieur d'une autre fonction.
- Elle peut accéder aux variables de la fonction extérieure.
- Elle se souvient de ces variables même lorsque la fonction extérieure a terminé son exécution.
Pense-y comme une manière de créer un petit paquet de fonctionnalité qui porte ses propres données privées. Cool, non ?
Fonctions Imbriquées
Avant de plonger plus profondément dans les closures, parlons des fonctions imbriquées. Ce sont simplement des fonctions définies à l'intérieur d'autres fonctions. Voici un exemple simple :
def outer_function(x):
def inner_function(y):
return x + y
return inner_function
result = outer_function(10)
print(result(5)) # Sortie : 15
Dans cet exemple, inner_function
est imbriquée à l'intérieur de outer_function
. La fonction intérieure peut accéder au paramètre x
de la fonction extérieure. C'est un concept clé pour comprendre les closures.
Portée des Variables
Pour véritablement saisir les closures, nous devons comprendre la portée des variables en Python. Il y a trois types de portée :
- Portée locale : Variables définies à l'intérieur d'une fonction
- Portée englobante : Variables dans la fonction extérieure des fonctions imbriquées
- Portée globale : Variables définies au niveau supérieur d'un module
Voici un exemple pour illustrer :
x = "Je suis global !" # Portée globale
def outer():
y = "Je suis de outer !" # Portée englobante
def inner():
z = "Je suis local !" # Portée locale
print(x, y, z)
inner()
outer()
Lorsque tu exécutes ce code, tu verras toutes les trois variables imprimées. La fonction inner
peut accéder aux variables de toutes les trois portées !
Création d'une Closure
Maintenant que nous comprenons les fonctions imbriquées et la portée des variables, créons une closure. Une closure se produit lorsqu'une fonction imbriquée fait référence à une valeur dans sa portée englobante. Voici un exemple :
def multiply_by(n):
def multiplier(x):
return x * n
return multiplier
times_two = multiply_by(2)
times_three = multiply_by(3)
print(times_two(5)) # Sortie : 10
print(times_three(5)) # Sortie : 15
Dans cet exemple, multiply_by
est notre fonction extérieure, et multiplier
est notre fonction intérieure. La magie se produit lorsque nous retournons multiplier
- il se souvient de la valeur de n
même après que multiply_by
ait terminé son exécution. C'est une closure !
Décomposons cela étape par étape :
- Nous définissons
multiply_by
qui prend un paramètren
. - À l'intérieur de
multiply_by
, nous définissonsmultiplier
qui prend un paramètrex
. -
multiplier
utilise à la foisx
(son propre paramètre) etn
(de la fonction extérieure). - Nous retournons
multiplier
demultiply_by
. - Lorsque nous appelons
multiply_by(2)
, il retourne une fonction qui multiplie toujours son entrée par 2. - De même,
multiply_by(3)
retourne une fonction qui multiplie toujours son entrée par 3.
C'est le pouvoir des closures - elles peuvent créer des fonctions spécialisées à la volée !
Le Mot-clé nonlocal
Parfois, tu pourrais vouloir modifier une variable de la portée englobante dans ta fonction intérieure. Python fournit le mot-clé nonlocal
à cette fin. Voici un exemple :
def counter():
count = 0
def increment():
nonlocal count
count += 1
return count
return increment
my_counter = counter()
print(my_counter()) # Sortie : 1
print(my_counter()) # Sortie : 2
print(my_counter()) # Sortie : 3
Dans cet exemple, increment
est une closure qui se souvient et modifie la variable count
de sa portée englobante. Le mot-clé nonlocal
indique à Python que count
n'est pas une variable locale, mais une de la portée englobante.
Utilisations Pratiques des Closures
Les closures ne sont pas seulement un truc cool - elles ont des applications pratiques ! Voici quelques-unes :
- Caché de données et encapsulation
- Création de fabriques de fonctions
- Implémentation de décorateurs
Regardons un exemple concret. Imagine que tu crées un système de remise pour une boutique en ligne :
def create_price_adjuster(discount):
def adjust_price(price):
return price * (1 - discount)
return adjust_price
black_friday_sale = create_price_adjuster(0.2) # 20% de réduction
cyber_monday_sale = create_price_adjuster(0.15) # 15% de réduction
original_price = 100
print(f"Prix du Black Friday : ${black_friday_sale(original_price)}")
print(f"Prix du Cyber Monday : ${cyber_monday_sale(original_price)}")
Ce code crée différentes fonctions de tarification pour différents événements de vente, toutes utilisant la même fonction de base. C'est le pouvoir des closures !
Résumé
Félicitations ! Tu viens de découvrir l'une des fonctionnalités plus avancées de Python. Récapitulons ce que nous avons couvert :
Concept | Description |
---|---|
Closure | Une fonction qui se souvient des valeurs de la portée englobante |
Fonction Imbriquée | Une fonction définie à l'intérieur d'une autre fonction |
Portée des Variables | La visibilité des variables (locale, englobante, globale) |
nonlocal |
Mot-clé pour modifier les variables de la portée englobante |
N'oublie pas, comme tout outil puissant, les closures devraient être utilisées avec discernement. Elles sont excellentes pour certaines tâches, mais en les utilisant excessivement, elles peuvent rendre ton code plus difficile à comprendre. Pratique, expérimente, et bientôt tu manieras les closures comme un pro de Python !
Bon codage, et souviens-toi - en Python, comme dans la vie, c'est ce qui se passe à l'intérieur (fonction) qui compte !
Credits: Image by storyset