A pergunta já foi respondida por aaronasterling
No entanto, alguém pode estar interessado em como as variáveis são armazenadas sob o capô.
Antes de vir para o trecho:
Encerramentos são funções que herdam variáveis de seu ambiente anexo. Quando você passa um retorno de chamada de função como argumento para outra função que executará E / S, essa função de retorno de chamada será chamada posteriormente, e essa função - quase magicamente - lembrará o contexto em que foi declarado, juntamente com todas as variáveis disponíveis. nesse contexto.
Se uma função não usa variáveis livres, ela não forma um fechamento.
Se houver outro nível interno que utilize variáveis livres - todos os níveis anteriores salvam o ambiente lexical (exemplo no final)
atributos de função func_closure
em python <3.X ou __closure__
em python> 3.X salvam as variáveis livres.
Toda função no python possui esses atributos de fechamento, mas não salva nenhum conteúdo se não houver variáveis livres.
exemplo: de atributos de fechamento, mas nenhum conteúdo interno, pois não há variável livre.
>>> def foo():
... def fii():
... pass
... return fii
...
>>> f = foo()
>>> f.func_closure
>>> 'func_closure' in dir(f)
True
>>>
NB: VARIÁVEL GRÁTIS É DEVE CRIAR UM ENCERRAMENTO.
Vou explicar usando o mesmo trecho como acima:
>>> def make_printer(msg):
... def printer():
... print msg
... return printer
...
>>> printer = make_printer('Foo!')
>>> printer() #Output: Foo!
E todas as funções Python têm um atributo de fechamento, então vamos examinar as variáveis anexas associadas a uma função de fechamento.
Aqui está o atributo func_closure
para a funçãoprinter
>>> 'func_closure' in dir(printer)
True
>>> printer.func_closure
(<cell at 0x108154c90: str object at 0x108151de0>,)
>>>
o closure
atributo retorna uma tupla de objetos de célula que contêm detalhes das variáveis definidas no escopo em anexo.
O primeiro elemento no func_closure que poderia ser None ou uma tupla de células que contêm ligações para as variáveis livres da função e é somente leitura.
>>> dir(printer.func_closure[0])
['__class__', '__cmp__', '__delattr__', '__doc__', '__format__', '__getattribute__',
'__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']
>>>
Aqui na saída acima, você pode ver cell_contents
, vamos ver o que ele armazena:
>>> printer.func_closure[0].cell_contents
'Foo!'
>>> type(printer.func_closure[0].cell_contents)
<type 'str'>
>>>
Então, quando chamamos a função printer()
, ela acessa o valor armazenado dentro do cell_contents
. Foi assim que obtivemos o resultado como 'Foo!'
Mais uma vez, explicarei o uso do snippet acima com algumas alterações:
>>> def make_printer(msg):
... def printer():
... pass
... return printer
...
>>> printer = make_printer('Foo!')
>>> printer.func_closure
>>>
No snippet acima, não imprimo msg dentro da função da impressora, para que não crie nenhuma variável livre. Como não há variável livre, não haverá conteúdo dentro do fechamento. Isso é exatamente o que vemos acima.
Agora vou explicar outro trecho diferente para limpar tudo Free Variable
com 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')
Portanto, vemos que uma func_closure
propriedade é uma tupla de células de fechamento , podemos referenciá-las e seu conteúdo explicitamente - uma célula tem a propriedade "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
>>>
Aqui quando chamamos inn
, ele se refere a todas as variáveis livres de salvamento, paraI am free variable
>>> inn('variable')
'I am free variable'
>>>