English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Tutoriel de base Python

Contrôle de flux Python

Fonction en Python

Types de données en Python

Opérations de fichiers Python

O

Objets et classes Python

Dates et heures Python

Connaissances avancées Python

Fermeture en Python

Manuel de référence Python

Dans cet article, vous découvrirez ce qu'est une fermeture en Python, comment la définir et les raisons pour lesquelles on utilise des fermetures.

Variable non locale dans une fonction imbriquée

Une fonction définie à l'intérieur d'une autre fonction est appelée fonction imbriquée. Une fonction imbriquée peut accéder aux variables de la portée fermée.

Dans Python, par défaut, ces variables non locales sont lecture-seule et nous devons les déclarer explicitement comme non locales (en utilisantmot-clé nonlocal) pour pouvoir les modifier.

Voici un exemple de fonction imbriquée accédant à des variables non locales.

def print_msg(msg):
# C'est la fonction fermée externe
    def printer():
# C'est une fonction imbriquée
        print(msg)
    printer()
# Nous exécutons cette fonction
# Sortie: Hello
print_msg("Hello")

Nous pouvons voir que la fonction imbriquée printer() peut accéder aux variables non locales de la fonction ferméemsg.

Définir une fonction de fermeture

Que se passe-t-il si la dernière ligne de la fonction print_msg() retourne la fonction printer() plutôt que de l'appeler ? Cela signifie que la définition de la fonction est la suivante.

def print_msg(msg):
# C'est la fonction fermée externe
    def printer():
# C'est une fonction imbriquée
        print(msg)
    return printer # Cela a changé
# Essayons d'appeler cette fonction maintenant.
# Sortie: Hello
another = print_msg("Hello")
another()

C'est inhabituel.

La fonction print_msg() est appelée avec une chaîne, "Hello" renvoie une fonction liée àAutreNom. Lorsque l'on appelle another(), bien que nous ayons terminé l'exécution de la fonction print_msg(), le message est toujours mémorisé.

Cette technique qui ajoute des données ("Hello") à du codedans PythonnomméeFermeture.

Même si la variable dépasse de sa plage ou que la fonction elle-même a été supprimée de l'espace de nom actuel, cette valeur dans la portée fermée est toujours mémorisée.

Tentez d'exécuter la commande suivante dans le Shell Python pour voir la sortie.

>>> del print_msg
>>> another()
Hello
>>> print_msg("Hello")
Traceback (most recent call last):
...
NameError: name 'print_msg' is not defined

What are the conditions for closure?

From the above example, we can see that in Python, when a nested function refers to a value in its enclosed scope, we have a closure.

The following points summarize the conditions that must be met to create closures in Python.

  • We must have a nested function (function inside a function).

  • The nested function must refer to values defined in the enclosed function.

  • The enclosed function must return an nested function.

When to use closures?

So, what is the use of closures?

Closures can avoid using global values and provide some form of data hiding. It can also provide an object-oriented solution to the problem.

When there are few methods implemented in a class (most of the time it is a single method), closure can provide another more elegant solution. However, when the number of properties and methods increases, it is best to implement a class.

This is a simple example where closure may be more preferable than defining a class and creating an object.

def make_multiplier_of(n):
    def multiplier(x):
        return x * n
    return multiplier
# 3multiplier
times3 = make_multiplier_of(3)
# 5multiplier
times5 = make_multiplier_of(5)
# Output: 27
print(times3(9))
# Output: 15
print(times5(3))
# Output: 30
print(times5(times3(2))

Python decorators alsoA large number of closures are used.

Finally, it is best to point out that you can find the values enclosed in the enclosed function.

All function objects have a __closure__ attribute, if it is a closure function, then this attribute returns a tuple of cell objects. Refer to the example above, we know that times3and times5It is a closure function.

>>> make_multiplier_of.__closure__
>>> times3__closure__
(<cell at 0x0000000002D155B8: int object at 0x000000001E39B6E0>,)

The cell object has an attribute cell_contents that stores closed values.

>>> times3__closure__[0].cell_contents
3
>>> times5__closure__[0].cell_contents
5