Beazley pg 100 mentions:
>>>python.__closure__
(<cell at 0x67f50: str object at 0x69230>,)
>>>python.__closure__[0].cell_contents
my understanding is that __closure__
is a list but what's all this
cell stuff and str object?? That looks like a 1-ary tuple?
It is the new Python 3 name for the old
func_closure
.http://docs.python.org/3.0/whatsnew/3.0.html
In a nutshell:
__closure__
isNone
or atuple
of cells that contain binding for the function's free variables.Also, it is NOT writable.
Reference: http://docs.python.org/ref/types.html
Example Python < 3 (so I am using
func_closure
)Output:
As
foo
is returning the functionbar
which is using its own valuex
, but noty
orz
. So, they come under__closure__
.when a nested function(
closure
) is defined in python:the outer function uses
co_cellvars
to note variables defined in the outer function that could be referenced by inner function.the inner function uses
co_freevars
to note variables defined in the outer function, which could be referenced for later use.Example:
I have never seen the cell type used anywhere else. It seems to be purpose-built to hold closure variables.
Closure cells refer to values needed by the function but are taken from the surrounding scope.
When Python compiles a nested function, it notes any variables that it references but are only defined in a parent function (not globals) in the code objects for both the nested function and the parent scope. These are the
co_freevars
andco_cellvars
attributes on the__code__
objects of these functions, respectively.Then, when you actually create the nested function (which happens when the parent function is executed), those references are then used to attach a closure to the nested function.
A function closure holds a tuple of cells, one each for each free variable (named in
co_freevars
); cells are special references to local variables of a parent scope, that follow the values those local variables point to. This is best illustrated with an example:In the above example, the function
bar
has one closure cell, which points tospam
in the functionfoo
. The cell follows the value ofspam
. More importantly, oncefoo()
completes andbar
is returned, the cell continues to reference the value (the stringeggs
) even though the variablespam
insidefoo
no longer exists.Thus, the above code outputs:
and
b.__closure__[0].cell_contents
is'eggs'
.Note that the closure is dereferenced when
bar()
is called; the closure doesn't capture the value here. That makes a difference when you produce nested functions (withlambda
expressions ordef
statements) that reference the loop variable:The above will print
salad
three times in a row, because all threelambda
functions reference thespam
variable, not the value it was bound to when the function object was created. By the time thefor
loop finishes,spam
was bound to'salad'
, so all three closures will resolve to that value.