La pregunta ya ha sido respondida por aaronasterling
Sin embargo, alguien podría estar interesado en cómo se almacenan las variables bajo el capó.
Antes de llegar al fragmento:
Los cierres son funciones que heredan variables de su entorno envolvente. Cuando pasa una devolución de llamada de función como argumento a otra función que hará E / S, esta función de devolución de llamada se invocará más tarde, y esta función, casi mágicamente, recordará el contexto en el que se declaró, junto con todas las variables disponibles en ese contexto
Si una función no utiliza variables libres, no forma un cierre.
Si hay otro nivel interno que utiliza variables libres, todos los niveles anteriores guardan el entorno léxico (ejemplo al final)
Los atributos de función func_closure
en python <3.X o __closure__
en python> 3.X guardan las variables libres.
Cada función en python tiene los atributos de este cierre, pero no guarda ningún contenido si no hay variables libres.
ejemplo: de atributos de cierre pero sin contenido dentro ya que no hay variable libre.
>>> def foo():
... def fii():
... pass
... return fii
...
>>> f = foo()
>>> f.func_closure
>>> 'func_closure' in dir(f)
True
>>>
NB: LA VARIABLE GRATUITA DEBE CREAR UN CIERRE.
Explicaré usando el mismo fragmento que el anterior:
>>> def make_printer(msg):
... def printer():
... print msg
... return printer
...
>>> printer = make_printer('Foo!')
>>> printer() #Output: Foo!
Y todas las funciones de Python tienen un atributo de cierre, así que examinemos las variables de cierre asociadas con una función de cierre.
Aquí está el atributo func_closure
para la funciónprinter
>>> 'func_closure' in dir(printer)
True
>>> printer.func_closure
(<cell at 0x108154c90: str object at 0x108151de0>,)
>>>
El closure
atributo devuelve una tupla de objetos de celda que contienen detalles de las variables definidas en el ámbito de inclusión.
El primer elemento en el func_closure que podría ser None o una tupla de celdas que contienen enlaces para las variables libres de la función y es de solo lectura.
>>> dir(printer.func_closure[0])
['__class__', '__cmp__', '__delattr__', '__doc__', '__format__', '__getattribute__',
'__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']
>>>
Aquí, en el resultado anterior, puede ver cell_contents
, veamos qué almacena:
>>> printer.func_closure[0].cell_contents
'Foo!'
>>> type(printer.func_closure[0].cell_contents)
<type 'str'>
>>>
Entonces, cuando llamamos a la función printer()
, accede al valor almacenado dentro de cell_contents
. Así es como obtuvimos la salida como 'Foo!'
Nuevamente, explicaré el uso del fragmento anterior con algunos cambios:
>>> def make_printer(msg):
... def printer():
... pass
... return printer
...
>>> printer = make_printer('Foo!')
>>> printer.func_closure
>>>
En el fragmento anterior, no imprimo msg dentro de la función de impresora, por lo que no crea ninguna variable libre. Como no hay una variable libre, no habrá contenido dentro del cierre. Eso es exactamente lo que vemos arriba.
Ahora explicaré otro fragmento diferente para aclarar todo 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')
Entonces, vemos que una func_closure
propiedad es una tupla de celdas de cierre , podemos referirlas explícitamente y su contenido: una celda tiene la propiedad "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
>>>
Aquí, cuando llamamos inn
, referirá todas las variables libres de guardado para que obtengamosI am free variable
>>> inn('variable')
'I am free variable'
>>>