ProgrammationDéveloppeur Python

Comment Python implémente-t-il le mécanisme des fonctions imbriquées (closures) ? À quoi servent les closures, quels sont les pièges à éviter et comment modifier correctement les variables de la fonction externe ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

En Python, une closure est une fonction qui "se souvient" des valeurs des variables externes, même lorsque elle est appelée en dehors de leur portée. Les closures sont créées lorsque la fonction interne fait référence aux variables définies dans la fonction externe. Pour modifier de telles variables à partir de la fonction imbriquée en Python 3, on utilise le mot clé nonlocal.

Exemple:

def make_accumulator(): total = 0 def add(value): nonlocal total total += value return total return add acc = make_accumulator() print(acc(10)) # 10 print(acc(5)) # 15

Sans nonlocal, la variable total ne serait pas accessible pour modification (erreur UnboundLocalError).

Question piège.

Question: "Peut-on augmenter une variable de la fonction externe à l'intérieur de la fonction imbriquée sans le mot clé nonlocal ?"

Réponse: Non, sans nonlocal, cela entraînera une erreur, car l'interpréteur considérera la variable comme locale à la fonction imbriquée. Exemple:

def outer(): count = 0 def inner(): count += 1 # Erreur UnboundLocalError return count return inner

Exemples d'erreurs réelles dues à l'ignorance des subtilités du sujet.


Histoire Dans une application web, on voulait implémenter un compteur local pour chaque gestionnaire via des fonctions imbriquées, mais on a oublié d’utiliser nonlocal. Le compteur renvoyait toujours 1, car il comptait count dans l’espace local et incrémentait un nouveau, sans lien avec la closure externe.


Histoire Dans les tâches de parallélisation (multithreading), on utilise souvent des closures et des lambdas. Sans comprendre les closures, une situation s'est créée où toutes les fonctions lambda "se rappelaient" de la dernière valeur de la variable de boucle, et les tâches se copiaient l'une l'autre, au lieu de traiter des tâches différentes.


Histoire Lors de l'écriture d'un décorateur sans utiliser la bonne closure (sans passer de paramètres dans le scope externe), une situation s'est produite où le décorateur ne pouvait pas accumuler d'état entre les appels, ce qui a entraîné des résultats inattendus et un fonctionnement instable de l'application.