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