На питання вже відповів ааронастерлінг
Однак когось може зацікавити, як змінні зберігаються під кришкою.
Перш ніж прийти до фрагменту:
Закриття - це функції, які успадковують змінні зі свого оточуючого середовища. Якщо ви передаєте функцію зворотного виклику функції як аргумент іншій функції, яка виконуватиме введення-виведення, ця функція зворотного виклику буде викликана пізніше, і ця функція - майже магічно - запам’ятає контекст, в якому вона була оголошена разом із усіма доступними змінними в цьому контексті.
Якщо функція не використовує вільних змінних, вона не утворює закриття.
Якщо є інший внутрішній рівень, який використовує вільні змінні - всі попередні рівні зберігають лексичне середовище (приклад наприкінці)
атрибути функції 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
>>>
Примітка: БЕЗКОШТОВНА ВІДМІННА ПОВИННА СТВОРИТИ ЗАКРИТИЙ
Я поясню, використовуючи той же фрагмент, що і вище:
>>> 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'
>>>