Ааронастерлинг уже ответил на вопрос
Тем не менее, кто-то может быть заинтересован в том, как переменные хранятся под капотом.
Прежде чем перейти к фрагменту:
Замыкания - это функции, которые наследуют переменные из окружающей их среды. Когда вы передаете функцию обратного вызова в качестве аргумента другой функции, которая будет выполнять ввод / вывод, эта функция обратного вызова будет вызвана позже, и эта функция - почти волшебным образом - запомнит контекст, в котором она была объявлена, вместе со всеми доступными переменными в этом контексте.
Если функция не использует свободные переменные, она не образует замыкание.
Если есть другой внутренний уровень, который использует свободные переменные - все предыдущие уровни сохраняют лексическую среду (пример в конце)
Атрибуты функций func_closure
в python <3.X или __closure__
в python> 3.X сохраняют свободные переменные.
Каждая функция в python имеет атрибуты замыкания, но не сохраняет никакого содержимого, если нет свободных переменных.
пример: атрибутов замыкания, но внутри нет содержимого, так как нет свободной переменной.
>>> def foo():
... def fii():
... pass
... return fii
...
>>> f = foo()
>>> f.func_closure
>>> 'func_closure' in dir(f)
True
>>>
NB: БЕСПЛАТНАЯ ПЕРЕМЕННАЯ ДОЛЖНА СОЗДАТЬ ЗАКРЫТИЕ.
Я объясню, используя тот же фрагмент, что и выше:
>>> def make_printer(msg):
... def printer():
... print msg
... return printer
...
>>> printer = make_printer('Foo!')
>>> printer() #Output: Foo!
И все функции Python имеют атрибут замыкания, поэтому давайте рассмотрим переменные, связанные с функцией замыкания.
Вот атрибут func_closure
для функцииprinter
>>> 'func_closure' in dir(printer)
True
>>> printer.func_closure
(<cell at 0x108154c90: str object at 0x108151de0>,)
>>>
closure
Атрибут возвращает кортеж объектов клеток , которые содержат информацию о переменных , определенных в рамках вмещающих.
Первый элемент в func_closure, который может быть None или набором ячеек, которые содержат привязки для свободных переменных функции и доступны только для чтения.
>>> dir(printer.func_closure[0])
['__class__', '__cmp__', '__delattr__', '__doc__', '__format__', '__getattribute__',
'__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']
>>>
Здесь в приведенном выше выводе вы можете увидеть cell_contents
, давайте посмотрим, что он хранит:
>>> printer.func_closure[0].cell_contents
'Foo!'
>>> type(printer.func_closure[0].cell_contents)
<type 'str'>
>>>
Итак, когда мы вызвали функцию printer()
, она получает доступ к значению, хранящемуся внутри cell_contents
. Вот как мы получили вывод «Foo!»
Я снова объясню использование приведенного выше фрагмента с некоторыми изменениями:
>>> def make_printer(msg):
... def printer():
... pass
... return printer
...
>>> printer = make_printer('Foo!')
>>> printer.func_closure
>>>
В приведенном выше фрагменте я не печатаю msg внутри функции принтера, поэтому она не создает свободной переменной. Поскольку свободной переменной нет, внутри замыкания не будет содержимого. Это именно то, что мы видим выше.
Теперь я объясню еще другой фрагмент кода , чтобы очистить все Free Variable
с 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')
Итак, мы видим, что func_closure
свойство - это кортеж ячеек замыкания , мы можем явно ссылаться на них и их содержимое - ячейка имеет свойство «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
>>>
Здесь, когда мы вызывали inn
, он будет ссылаться на все переменные сохранения, поэтому мы получаемI am free variable
>>> inn('variable')
'I am free variable'
>>>