Die Frage wurde bereits von aaronasterling beantwortet
Es könnte jedoch jemand interessiert sein, wie die Variablen unter der Haube gespeichert werden.
Bevor Sie zum Snippet kommen:
Closures sind Funktionen, die Variablen von ihrer umgebenden Umgebung erben. Wenn Sie einen Funktionsrückruf als Argument an eine andere Funktion übergeben, die E / A ausführt, wird diese Rückruffunktion später aufgerufen, und diese Funktion merkt sich - fast auf magische Weise - den Kontext, in dem sie deklariert wurde, sowie alle verfügbaren Variablen in diesem Zusammenhang.
Wenn eine Funktion keine freien Variablen verwendet, bildet sie keinen Abschluss.
Wenn es eine andere innere Ebene gibt, die freie Variablen verwendet , speichern alle vorherigen Ebenen die lexikalische Umgebung (Beispiel am Ende).
Funktionsattribute func_closure
in Python <3.X oder __closure__
in Python> 3.X speichern die freien Variablen.
Jede Funktion in Python verfügt über diese Abschlussattribute, speichert jedoch keinen Inhalt, wenn keine freien Variablen vorhanden sind.
Beispiel: von Abschlussattributen, aber ohne Inhalt, da keine freie Variable vorhanden ist.
>>> def foo():
... def fii():
... pass
... return fii
...
>>> f = foo()
>>> f.func_closure
>>> 'func_closure' in dir(f)
True
>>>
NB: KOSTENLOSE VARIABLE MÜSSEN EINEN SCHLUSS SCHAFFEN.
Ich werde das gleiche Snippet wie oben erklären:
>>> def make_printer(msg):
... def printer():
... print msg
... return printer
...
>>> printer = make_printer('Foo!')
>>> printer() #Output: Foo!
Und alle Python-Funktionen haben ein Closure-Attribut. Untersuchen wir also die einschließenden Variablen, die einer Closure-Funktion zugeordnet sind.
Hier ist das Attribut func_closure
für die Funktionprinter
>>> 'func_closure' in dir(printer)
True
>>> printer.func_closure
(<cell at 0x108154c90: str object at 0x108151de0>,)
>>>
Das closure
Attribut gibt ein Tupel von Zellenobjekten zurück, die Details der im umschließenden Bereich definierten Variablen enthalten.
Das erste Element in func_closure, das None oder ein Tupel von Zellen sein kann, die Bindungen für die freien Variablen der Funktion enthalten, ist schreibgeschützt.
>>> dir(printer.func_closure[0])
['__class__', '__cmp__', '__delattr__', '__doc__', '__format__', '__getattribute__',
'__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']
>>>
Hier in der obigen Ausgabe sehen Sie cell_contents
, was darin gespeichert ist:
>>> printer.func_closure[0].cell_contents
'Foo!'
>>> type(printer.func_closure[0].cell_contents)
<type 'str'>
>>>
Wenn wir die Funktion printer()
aufrufen, greift sie auf den Wert zu, der in der Funktion gespeichert ist cell_contents
. So haben wir die Ausgabe als 'Foo!'
Wieder werde ich die Verwendung des obigen Snippets mit einigen Änderungen erklären:
>>> def make_printer(msg):
... def printer():
... pass
... return printer
...
>>> printer = make_printer('Foo!')
>>> printer.func_closure
>>>
Im obigen Snippet drucke ich keine Nachricht innerhalb der Druckerfunktion, sodass keine freie Variable erstellt wird. Da es keine freie Variable gibt, enthält der Abschluss keinen Inhalt. Genau das sehen wir oben.
Jetzt werde ich ein anderes Snippet erklären, um alles zu klären Free Variable
mit 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')
Wir sehen also, dass eine func_closure
Eigenschaft ein Tupel von Abschlusszellen ist . Wir können sie und ihren Inhalt explizit referenzieren - eine Zelle hat die Eigenschaft "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
>>>
Wenn wir hier aufrufen inn
, werden alle speicherfreien Variablen referenziert, damit wir sie erhaltenI am free variable
>>> inn('variable')
'I am free variable'
>>>