Aaronasterling ha già risposto alla domanda
Tuttavia, qualcuno potrebbe essere interessato a come le variabili sono memorizzate sotto il cofano.
Prima di venire allo snippet:
Le chiusure sono funzioni che ereditano le variabili dal loro ambiente di chiusura. Quando si passa un callback di funzione come argomento a un'altra funzione che eseguirà I / O, questa funzione di callback verrà invocata in seguito e questa funzione - quasi magicamente - ricorderà il contesto in cui è stata dichiarata, insieme a tutte le variabili disponibili in quel contesto.
Se una funzione non utilizza variabili libere non costituisce una chiusura.
Se esiste un altro livello interno che utilizza variabili libere, tutti i livelli precedenti salvano l'ambiente lessicale (esempio alla fine)
gli attributi della funzione func_closure
in python <3.X o __closure__
in python> 3.X salvano le variabili libere.
Ogni funzione in Python ha questi attributi di chiusura, ma non salva alcun contenuto se non ci sono variabili libere.
esempio: di attributi di chiusura ma nessun contenuto all'interno in quanto non esiste una variabile libera.
>>> def foo():
... def fii():
... pass
... return fii
...
>>> f = foo()
>>> f.func_closure
>>> 'func_closure' in dir(f)
True
>>>
NB: LA VARIABILE GRATUITA DEVE CREARE UNA CHIUSURA.
Spiegherò usando lo stesso frammento di cui sopra:
>>> def make_printer(msg):
... def printer():
... print msg
... return printer
...
>>> printer = make_printer('Foo!')
>>> printer() #Output: Foo!
E tutte le funzioni di Python hanno un attributo di chiusura, quindi esaminiamo le variabili di chiusura associate a una funzione di chiusura.
Ecco l'attributo func_closure
per la funzioneprinter
>>> 'func_closure' in dir(printer)
True
>>> printer.func_closure
(<cell at 0x108154c90: str object at 0x108151de0>,)
>>>
L' closure
attributo restituisce una tupla di oggetti cella che contengono dettagli delle variabili definite nell'ambito compreso.
Il primo elemento in func_closure che potrebbe essere None o una tupla di celle che contengono associazioni per le variabili libere della funzione ed è di sola lettura.
>>> dir(printer.func_closure[0])
['__class__', '__cmp__', '__delattr__', '__doc__', '__format__', '__getattribute__',
'__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']
>>>
Qui nell'output sopra puoi vedere cell_contents
, vediamo cosa memorizza:
>>> printer.func_closure[0].cell_contents
'Foo!'
>>> type(printer.func_closure[0].cell_contents)
<type 'str'>
>>>
Quindi, quando abbiamo chiamato la funzione printer()
, accede al valore memorizzato all'interno di cell_contents
. Ecco come abbiamo ottenuto l'output come "Foo!"
Spiegherò ancora usando lo snippet sopra con alcune modifiche:
>>> def make_printer(msg):
... def printer():
... pass
... return printer
...
>>> printer = make_printer('Foo!')
>>> printer.func_closure
>>>
Nel frammento sopra, non stampo msg all'interno della funzione stampante, quindi non crea alcuna variabile libera. Poiché non esiste una variabile libera, non ci sarà contenuto all'interno della chiusura. Questo è esattamente ciò che vediamo sopra.
Ora spiegherò un altro frammento diverso per cancellare tutto Free Variable
con 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')
Quindi, vediamo che una func_closure
proprietà è una tupla di celle di chiusura , possiamo riferirle esplicitamente e il loro contenuto - una cella ha proprietà "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
>>>
Qui quando abbiamo chiamato inn
, farà riferimento a tutte le variabili libere di salvataggio in modo da ottenereI am free variable
>>> inn('variable')
'I am free variable'
>>>