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
Я никогда не видел тип ячейки, который использовался где-либо еще. Кажется, что было создано специально для хранения переменных закрытия.