Подтвердить что ты не робот

Что именно содержится в obj.__ clos__?

Beazley pg 100 упоминает:

>>>python.__closure__
(<cell at 0x67f50: str object at 0x69230>,)
>>>python.__closure__[0].cell_contents

Я понимаю, что __closure__ - это список, но что все это ячейка и объект str? Это похоже на 1-й кортеж?

4b9b3361

Ответ 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', поэтому все три закрытия будут разрешены к этому значению.

Ответ 2

Это новое имя 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__.

Ответ 3

>>> 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

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