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
?
Are nested functions not closures because they are not used by the external world?
UPDATE: I was reading about closures and it got me thinking about this concept with respect to Python. I searched and found the article mentioned by someone in a comment below, but I couldn't completely understand the explanation in that article, so that is why I am asking this question.
Gives:
This is an example of what a closure is and how it can be used.
I had a situation where I needed a separate but persistent name space. I used classes. I don't otherwise. Segregated but persistent names are closures.
Python 2 didn't have closures - it had workarounds that resembled closures.
There are plenty of examples in answers already given - copying in variables to the inner function, modifying an object on the inner function, etc.
In Python 3, support is more explicit - and succinct:
Usage:
The
nonlocal
keyword binds the inner function to the outer variable explicitly mentioned, in effect enclosing it. Hence more explicitly a 'closure'.I'd like to offer another simple comparison between python and JS example, if this helps make things clearer.
JS:
and executing:
Python:
and executing:
Reason: As many others said above, in python, if there is an assignment in the inner scope to a variable with the same name, a new reference in the inner scope is created. Not so with JS, unless you explicitly declare one with the
var
keyword.A closure occurs when a function has access to a local variable from an enclosing scope that has finished its execution.
When
make_printer
is called, a new frame is put on the stack with the compiled code for theprinter
function as a constant and the value ofmsg
as a local. It then creates and returns the function. Because the functionprinter
references themsg
variable, it is kept alive after themake_printer
function has returned.So, if your nested functions don't
then they are not closures.
Here's an example of a nested function which is not a closure.
Here, we are binding the value to the default value of a parameter. This occurs when the function
printer
is created and so no reference to the value ofmsg
external toprinter
needs to be maintained aftermake_printer
returns.msg
is just a normal local variable of the functionprinter
in this context.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.
NB: FREE VARIABLE IS MUST TO CREATE A CLOSURE.
I will explain using the same snippet as above:
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 functionprinter
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.
Here in the above output you can see
cell_contents
, let's see what it stores:So, when we called the function
printer()
, it accesses the value stored inside thecell_contents
. This is how we got the output as 'Foo!'Again I will explain using the above snippet with some changes:
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
withClosure
: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"Here when we called
inn
, it will refer all the save free variables so we getI am free variable