For example, why does this work?
def func1(func1var):
def innerfunc(innerfuncvar):
if func1var == 1:
print innerfuncvar
else:
print 5
func2(innerfunc)
def func2(function):
function(9)
When innerfunc
is called in func2
, how does it know the values of func1var
?
You've created a closure. Basically, think of it like this, from the point of view of the inner function:
func1var = whatever
def func2(function):
function(9)
def innerfunc(innerfuncvar):
if func1var = 1:
print innerfuncvar
else:
print 5
func2(innerfunc)
It doesn't care whether func1var
is in an outer or global scope -- it just looks for it in each scope outward, starting with it's own local scope. It's just like when you reference a module global variable from inside a class or function in that module.
Python actually goes to some lengths to do this for you. When you define a function inside a function, you may use variables from the outer function in the inner function. This is true for any depth of nesting (that is, you can have a function inside a function inside a function inside a function... to any depth... and the innermost function can use variables from any of the enclosing functions). If there are conflicting names, the innermost variable with the name requested is used.
What's more, Python actually captures any variables you use from the outer function and stores them in the inner function, which is called a closure. So you can not only pass a function to another function, as you are doing, but you can return a function from a function, and variables you use from the outer function that were in effect when the function was defined will still be accessible from the returned function, even though the outer function isn't running any more. This is a fairly advanced feature, but it lets you do something like this:
def make_adder(increment):
def adder(number):
return number + increment
adder.__name__ = "adder(%s)" % increment
return adder
This function is a function that creates a function that adds the specified value to it. For example:
add1 = make_adder(1)
add5 = make_adder(5)
print add1(10) # 11
print add5(10) # 15
In this case, the value you pass to make_adder
is captured and stored in the function that gets returned. This allows you to create a bunch of functions that add any number to their arguments. Which is a trivial example that isn't actually very useful in real life, but serves to illustrate the feature.
Each time you call func1(func1var)
, Python actually builds a new function innerfunc()
. Since func1var
is perfectly defined when innerfunc()
is created, the code of the new innerfunc()
function contains the correct value of func1var
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With