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 !

Python - Closures

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 :

  1. C'est une fonction à l'intérieur d'une autre fonction.
  2. Elle peut accéder aux variables de la fonction extérieure.
  3. 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 :

  1. Portée locale : Variables définies à l'intérieur d'une fonction
  2. Portée englobante : Variables dans la fonction extérieure des fonctions imbriquées
  3. 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 :

  1. Nous définissons multiply_by qui prend un paramètre n.
  2. À l'intérieur de multiply_by, nous définissons multiplier qui prend un paramètre x.
  3. multiplier utilise à la fois x (son propre paramètre) et n (de la fonction extérieure).
  4. Nous retournons multiplier de multiply_by.
  5. Lorsque nous appelons multiply_by(2), il retourne une fonction qui multiplie toujours son entrée par 2.
  6. 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 :

  1. Caché de données et encapsulation
  2. Création de fabriques de fonctions
  3. 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