Beazley pg 100 упоминает:
>>>python.__closure__
(<cell at 0x67f50: str object at 0x69230>,)
>>>python.__closure__[0].cell_contents
Я понимаю, что __closure__ - это список, но что все это
ячейка и объект str? Это похоже на 1-й кортеж?
Beazley pg 100 упоминает:
>>>python.__closure__
(<cell at 0x67f50: str object at 0x69230>,)
>>>python.__closure__[0].cell_contents
Я понимаю, что __closure__ - это список, но что все это
ячейка и объект str? Это похоже на 1-й кортеж?
Ключи закрытия относятся к значениям, необходимым для функции, но они берутся из окружающей области.
Когда Python компилирует вложенную функцию, он замечает любые переменные, которые он ссылается, но определяется только родительской функцией (а не глобальными) в объектах кода как для вложенной функции, так и для родительской области. Это атрибуты co_freevars и co_cellvars для объектов __code__ этих функций соответственно.
Затем, когда вы фактически создаете вложенную функцию (которая происходит при выполнении родительской функции), эти ссылки затем используются для присоединения закрытия к вложенной функции.
Закрытие функции содержит набор ячеек, по одному для каждой свободной переменной (названный в co_freevars); ячейки являются специальными ссылками на локальные переменные родительской области, которые соответствуют значениям, на которые указывают эти локальные переменные. Это лучше всего иллюстрируется примером:
def foo():
def bar():
print(spam)
spam = 'ham'
bar()
spam = 'eggs'
bar()
return bar
b = foo()
b()
В приведенном выше примере функция bar имеет одну замыкающую ячейку, которая указывает на spam в функции foo. Ячейка следует за значением spam. Что еще более важно, как только foo() завершается и возвращается bar, ячейка продолжает ссылаться на значение (строка eggs), даже если переменная spam внутри foo больше не существует.
Таким образом, приведенный выше код выводит:
>>> b=foo()
ham
eggs
>>> b()
eggs
и b.__closure__[0].cell_contents - 'eggs'.
Обратите внимание, что замыкание разыменовывается при вызове bar(); закрытие не фиксирует здесь значение. Это имеет значение, когда вы создаете вложенные функции (с выражениями lambda или def), которые ссылаются на переменную цикла:
def foo():
bar = []
for spam in ('ham', 'eggs', 'salad'):
bar.append(lambda: spam)
return bar
for bar in foo():
print bar()
Вышеуказанное будет печатать salad три раза подряд, потому что все три функции lambda ссылаются на переменную spam, а не на значение, с которым она была связана, когда был создан объект функции. По завершении цикла for spam привязан к 'salad', поэтому все три закрытия будут разрешены к этому значению.
Это новое имя Python 3 для старого func_closure.
http://docs.python.org/3.0/whatsnew/3.0.html
Атрибуты функции с именем
func_Xбыли переименованы для использования формы__X__, освободив эти имена в пространстве имен атрибутов функции для определяемых пользователем атрибутов. Для этогоfunc_closure,func_code,func_defaults,func_dict,func_doc,func_globals,func_nameбыли переименованы в__closure__,__code__,__defaults__,__dict__,__doc__,__globals__,__name__соответственно.
В двух словах:
__closure__ - это None или tuple для ячеек, которые содержат привязку для функций свободных переменных.
Кроме того, он НЕ доступен для записи.
Ссылка: http://docs.python.org/ref/types.html
Пример Python < 3 (поэтому я использую func_closure)
def foo():
x = "I am used"
y = "I am free"
z = "I am free too"
def bar(x):
return x, y, z
return bar
c = foo().func_closure
print [i.cell_contents for i in c]
Вывод:
>>>
['I am free', 'I am free too']
В качестве foo возвращается функция bar, которая использует свое собственное значение x, но не y или z. Таким образом, они попадают под __closure__.
>>> def f():
... a = "HELO"
... b = 1.0
... def w(c):
... return a,b,c
... return w
>>> w = f()
>>> w.__closure__
(<cell at 0xa05c4ac: str object at 0x9e91b74>, <cell at 0xa05c3bc: float object at 0xb733dde8>)
>>> w.__closure__[0].cell_contents
'HELO'
>>> w.__closure__[1].cell_contents
1.0
Я никогда не видел тип ячейки, который использовался где-либо еще. Кажется, что было создано специально для хранения переменных закрытия.