def maker(n):
def action(x):
return x ** n
return action
f = maker(2)
print(f)
print(f(3))
print(f(4))
g = maker(3)
print(g(3))
print(f(3)) # stil
People answered correctly about the closure, that is: the valid value for "n" inside action is the last value it had whenever "maker" was called.
One ease way to overcome this is to make your freevar (n) a variable inside the "action" function, which receives a copy of "n" in the moment it is run:
The easiest way to do this is to set "n" as a parameter whose default value is "n" at the moment of creation. This value for "n" stays fixed because default parameters for a function are stored in a tuple which is an attribute of the function itself (action.func_defaults in this case):
def maker(n):
def action(x, k=n):
return x ** k
return action
Usage:
f = maker(2) # f is action(x, k=2)
f(3) # returns 3^2 = 9
f(3,3) # returns 3^3 = 27
One use is to return a function that maintains a parameter.
def outer_closure(a):
# parm = a <- saving a here isn't needed
def inner_closure():
#return parm
return a # <- a is remembered
return inner_closure
# set parm to 5 and return address of inner_closure function
x5 = outer_closure(5)
x5()
>5
x6 = outer_closure(6)
x6()
>6
# x5 inner closure function instance of parm persists
x5()
>5
Because at the time when you create the function, n
was 2
, so your function is:
def action(x):
return x ** 2
When you call f(3), x
is set to 3
, so your function will return 3 ** 2