I read an example on closure
def outer():
x = 1
def inner():
print x # 1
return inner
The life of our variable x is only till the time the function outer runs . When i call outer and it returns the adress of inner , the variable x should have died because the function outer has exited but still how can i acess it through the returned inner function ?
python variable scope in nested functions
This link answered that the value of variables used by inner is stored when outer returns inner function to caller , but
Now see this code
def outer():
x = 1
def inner():
print x*n # n not defined anywhere
return inner
I ran this code and This piece of code doesn't give any error when i call outer , that means that python doesn't checks the variables used by inner function while running outer . so how does it know it has to retain 'x' , after exiting ?
The life of our variable x is only till the time the function outer runs
No. x
lives as long as it's reachable from somewhere. And, it is — from the inner
function.
This piece of code doesn't give any error when i call outer , that means that python doesn't checks the variables used by inner function while running outer
n
could be defined after calling outer
, but before calling its result, inner
. In that case inner
's body if perfectly legitimate.
If you didn't return inner
, then there'd be no reason to keep x
, because you can't reach inner
, thus can't somehow involve x
into computation.
The way x
is remembered is because python has a special __closure__
attribute that remembers the object from the enclosing scope that the local function needs and keeps a reference
to it so it can be used in the local function:
def outer():
x = 1
def inner():
print(x)
return inner
o = outer()
print(o.__closure__)
(<cell at 0x7fa18a2fc588: int object at 0x9f8800>,)
If you assign o = outer()
and then call o()
you are then calling the inner
function and you will get an error, calling outer()
does not call the inner function.
If you were to declare a function f
and put a print(n)
in the body then unless you actually call f
you won't get an error so the same logic applies to your inner function, you are not actually calling it with outer()
so you don't get an error:
def f():
print(n) # will only error when we actually call `f()`
If calling the inner
function happened when you called outer
it would defeat the purpose, consider the following function factory where we take in an exponent e
to raise i
to:
def raise_exp(e):
def power(i):
return i ** e # n not defined anywhere
return power
sq = raise_exp(2) # set exponent but does not call power
print(sq(2)) # now we actually all power
cube = raise_exp(3)
print(cube(3))
25
27
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