La question a déjà été répondue par aaronasterling
Cependant, quelqu'un pourrait être intéressé par la façon dont les variables sont stockées sous le capot.
Avant de venir à l'extrait:
Les fermetures sont des fonctions qui héritent des variables de leur environnement englobant. Lorsque vous passez un rappel de fonction comme argument à une autre fonction qui fera des E / S, cette fonction de rappel sera invoquée plus tard, et cette fonction se souviendra - presque comme par magie - du contexte dans lequel elle a été déclarée, ainsi que de toutes les variables disponibles dans ce contexte.
Si une fonction n'utilise pas de variables libres, elle ne forme pas de fermeture.
S'il existe un autre niveau interne qui utilise des variables libres - tous les niveaux précédents sauvegardent l'environnement lexical (exemple à la fin)
les attributs de fonction func_closure
en python <3.X ou __closure__
en python> 3.X enregistrent les variables libres.
Chaque fonction en python a ces attributs de fermeture, mais elle n'enregistre aucun contenu s'il n'y a pas de variables libres.
exemple: d'attributs de fermeture mais pas de contenu à l'intérieur car il n'y a pas de variable libre.
>>> def foo():
... def fii():
... pass
... return fii
...
>>> f = foo()
>>> f.func_closure
>>> 'func_closure' in dir(f)
True
>>>
NB: UNE VARIABLE GRATUITE EST OBLIGATOIRE POUR CRÉER UNE FERMETURE.
Je vais vous expliquer en utilisant le même extrait que ci-dessus:
>>> def make_printer(msg):
... def printer():
... print msg
... return printer
...
>>> printer = make_printer('Foo!')
>>> printer() #Output: Foo!
Et toutes les fonctions Python ont un attribut de fermeture, examinons donc les variables englobantes associées à une fonction de fermeture.
Voici l'attribut func_closure
de la fonctionprinter
>>> 'func_closure' in dir(printer)
True
>>> printer.func_closure
(<cell at 0x108154c90: str object at 0x108151de0>,)
>>>
L' closure
attribut renvoie un tuple d'objets de cellule qui contiennent des détails des variables définies dans la portée englobante.
Le premier élément de func_closure qui pourrait être None ou un tuple de cellules contenant des liaisons pour les variables libres de la fonction et il est en lecture seule.
>>> dir(printer.func_closure[0])
['__class__', '__cmp__', '__delattr__', '__doc__', '__format__', '__getattribute__',
'__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']
>>>
Ici, dans la sortie ci-dessus, vous pouvez voir cell_contents
, voyons ce qu'il stocke:
>>> printer.func_closure[0].cell_contents
'Foo!'
>>> type(printer.func_closure[0].cell_contents)
<type 'str'>
>>>
Ainsi, lorsque nous avons appelé la fonction printer()
, elle accède à la valeur stockée à l'intérieur du cell_contents
. C'est ainsi que nous avons obtenu la sortie en tant que 'Foo!'
Je vais à nouveau expliquer l'utilisation de l'extrait ci-dessus avec quelques modifications:
>>> def make_printer(msg):
... def printer():
... pass
... return printer
...
>>> printer = make_printer('Foo!')
>>> printer.func_closure
>>>
Dans l'extrait ci-dessus, je n'imprime pas le msg à l'intérieur de la fonction imprimante, donc il ne crée aucune variable libre. Comme il n'y a pas de variable libre, il n'y aura pas de contenu à l'intérieur de la fermeture. C'est exactement ce que nous voyons ci-dessus.
Je vais maintenant expliquer un autre extrait différent pour tout effacer Free Variable
avec Closure
:
>>> def outer(x):
... def intermediate(y):
... free = 'free'
... def inner(z):
... return '%s %s %s %s' % (x, y, free, z)
... return inner
... return intermediate
...
>>> outer('I')('am')('variable')
'I am free variable'
>>>
>>> inter = outer('I')
>>> inter.func_closure
(<cell at 0x10c989130: str object at 0x10c831b98>,)
>>> inter.func_closure[0].cell_contents
'I'
>>> inn = inter('am')
Donc, nous voyons qu'une func_closure
propriété est un tuple de cellules de fermeture , nous pouvons les référencer explicitement et leur contenu - une cellule a la propriété "cell_contents"
>>> inn.func_closure
(<cell at 0x10c9807c0: str object at 0x10c9b0990>,
<cell at 0x10c980f68: str object at 0x10c9eaf30>,
<cell at 0x10c989130: str object at 0x10c831b98>)
>>> for i in inn.func_closure:
... print i.cell_contents
...
free
am
I
>>>
Ici, lorsque nous avons appelé inn
, il fera référence à toutes les variables de sauvegarde gratuites afin que nous obtenionsI am free variable
>>> inn('variable')
'I am free variable'
>>>