I have seen and used nested functions in Python, and they match the definition of a closure. So why are they called nested functions
instead of closures<
The question has already been answered by aaronasterling
However, someone might be interested in how the variables are stored under the hood.
Before coming to the snippet:
Closures are functions that inherit variables from their enclosing environment. When you pass a function callback as an argument to another function that will do I/O, this callback function will be invoked later, and this function will — almost magically — remember the context in which it was declared, along with all the variables available in that context.
If a function does not use free variables it doesn't form a closure.
If there is another inner level which uses free variables -- all previous levels save the lexical environment ( example at the end )
function attributes func_closure
in python < 3.X or __closure__
in python > 3.X save the free variables.
Every function in python has this closure attributes, but it doesn't save any content if there is no free variables.
example: of closure attributes but no content inside as there is no free variable.
>>> def foo():
... def fii():
... pass
... return fii
...
>>> f = foo()
>>> f.func_closure
>>> 'func_closure' in dir(f)
True
>>>
NB: FREE VARIABLE IS MUST TO CREATE A CLOSURE.
I will explain using the same snippet as above:
>>> def make_printer(msg):
... def printer():
... print msg
... return printer
...
>>> printer = make_printer('Foo!')
>>> printer() #Output: Foo!
And all Python functions have a closure attribute so let's examine the enclosing variables associated with a closure function.
Here is the attribute func_closure
for the function printer
>>> 'func_closure' in dir(printer)
True
>>> printer.func_closure
(,)
>>>
|
The closure
attribute returns a tuple of cell objects which contain details of the variables defined in the enclosing scope.
The first element in the func_closure which could be None or a tuple of cells that contain bindings for the function’s free variables and it is read-only.
>>> dir(printer.func_closure[0])
['__class__', '__cmp__', '__delattr__', '__doc__', '__format__', '__getattribute__',
'__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']
>>>
Here in the above output you can see cell_contents
, let's see what it stores:
>>> printer.func_closure[0].cell_contents
'Foo!'
>>> type(printer.func_closure[0].cell_contents)
>>>
So, when we called the function printer()
, it accesses the value stored inside the cell_contents
. This is how we got the output as 'Foo!'
Again I will explain using the above snippet with some changes:
>>> def make_printer(msg):
... def printer():
... pass
... return printer
...
>>> printer = make_printer('Foo!')
>>> printer.func_closure
>>>
In the above snippet, I din't print msg inside the printer function, so it doesn't create any free variable. As there is no free variable, there will be no content inside the closure. Thats exactly what we see above.
Now I will explain another different snippet to clear out everything Free Variable
with 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
(,)
>>> inter.func_closure[0].cell_contents
'I'
>>> inn = inter('am')
|
So, we see that a func_closure
property is a tuple of closure cells, we can refer them and their contents explicitly -- a cell has property "cell_contents"
>>> inn.func_closure
(,
,
)
>>> for i in inn.func_closure:
... print i.cell_contents
...
free
am
I
>>>
| | |
Here when we called inn
, it will refer all the save free variables so we get I am free variable
>>> inn('variable')
'I am free variable'
>>>