3.1 Introduction aux closures
Un closure est une fonction qui capture les variables de son environnement immédiat, même après que cet environnement a terminé son exécution. Cela signifie que le closure peut « se souvenir » des valeurs des variables de son environnement extérieur et continuer à travailler avec elles, même lorsque cet environnement n'est plus actif.
Pour comprendre comment fonctionnent les closures, examinons l'exemple suivant :
def outer_function(x):
def inner_function(y):
return x + y
return inner_function
closure = outer_function(10)
print(closure(5)) # Sortie: 15
Voyons ce qui est écrit ici :
La fonction extérieure (outer_function)
: Cette fonction prend
un argument x
et définit une fonction interne inner_function
,
qui prend un argument y
et retourne la somme de x
et y
. La fonction
inner_function
n'est pas appelée à l'intérieur de
outer_function
, mais seulement déclarée.
La fonction interne (inner_function)
: Cette fonction
est retournée par outer_function
et conserve une référence à la valeur
de x
, qui a été passée à outer_function
.
Closure: La variable closure
devient
un closure qui « se souvient » de la valeur de x
(dans ce cas, 10) et peut
l'utiliser lors de l'appel.
Habituellement, personne ne parvient à travailler correctement avec les closures dès la première fois. Alors essayons d'améliorer votre compréhension des closures avec des exemples.
3.2 Exemples d'utilisation des closures
Création d'une fonction génératrice
Les closures peuvent être utilisées pour créer des fonctions génératrices qui génèrent des séquences de valeurs.
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
counter = make_counter()
print(counter()) # Sortie: 1
print(counter()) # Sortie: 2
print(counter()) # Sortie: 3
Explication :
La fonction génératrice (make_counter)
: Cette fonction crée
une variable count
et renvoie une fonction interne counter
, qui
augmente la valeur de count
et la retourne.
Closure: La fonction counter
conserve l'état de la variable
count
et peut la modifier à chaque appel.
Création d'une fonction avec configuration
Les closures peuvent être utilisées pour créer des fonctions avec une configuration prédéfinie.
def make_multiplier(factor):
def multiplier(x):
return x * factor
return multiplier
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5)) # Sortie: 10
print(triple(5)) # Sortie: 15
Explication :
La fonction configuratrice (make_multiplier)
: Cette fonction
prend un multiplicateur factor
et renvoie une fonction interne multiplier
,
qui multiplie la valeur d'entrée par factor
.
Closures: Les fonctions double
et triple
sont des closures,
qui conservent leurs propres valeurs de factor
et les utilisent pour
la multiplication.
Filtrage de données avec paramètres
Les closures peuvent être utiles pour créer des fonctions de filtrage avec paramètres.
def make_filter(threshold):
def filter_func(value):
return value > threshold
return filter_func
filter_above_10 = make_filter(10)
data = [5, 10, 15, 20]
filtered_data = list(filter(filter_above_10, data))
print(filtered_data) # Sortie: [15, 20]
Explication :
La fonction filtre (make_filter)
: Cette fonction prend
une valeur seuil threshold
et renvoie une fonction interne filter_func
,
qui vérifie si la valeur dépasse le seuil.
Closure: La fonction filter_func
conserve la valeur de threshold
et l'utilise pour filtrer les données.
3.3 Avantages et inconvénients des closures
Avantages de l'utilisation des closures
Encapsulation de l'état: Les closures permettent d'encapsuler l'état dans une fonction, évitant les variables globales et améliorant la lisibilité et la maintenance du code.
Flexibilité: Les closures peuvent être utilisées pour créer des fonctions avec une configuration ou un comportement spécifique, rendant le code plus flexible et adaptable.
Programmation fonctionnelle: Les closures sont une notion importante en programmation fonctionnelle, permettant de créer des fonctions d'ordre supérieur et d'autres constructions fonctionnelles.
Limitations et problèmes potentiels
Malgré de nombreux avantages, les closures ont aussi leurs limitations :
Utilisation de la mémoire: Les closures peuvent conserver des références à des objets qui ne sont plus utilisés, ce qui peut entraîner des fuites de mémoire.
Complexité du débogage: Les closures peuvent compliquer le débogage du code, car les états des variables peuvent ne pas être évidents.
GO TO FULL VERSION