I am interested in creating a list / array of functions "G" consisting of many small functions "g". This essentially should correspond to a series of functions 'evolving' in time.
Each "g" takes-in two variables and returns the product of these variables with an outside global variable indexed at the same time-step.
obs_mat (T x 1) is a pre-defined global array, and
t corresponds to the time-steps
G = 
for t in range(T):
# tried declaring obs here too.
def g(current_state, observation_noise):
obs = obs_mat[t]
return current_state * observation_noise * obs
Unfortunately when I test the resultant functions, they do not seem to pick up on the difference in the
obs time-varying constant i.e. (Got
G(100,100) same as
G(100,100)). I tried playing around with the scope of
obs but without much luck. Would anyone be able to help guide me in the right direction?
Best How To :
This is a common "gotcha" to referencing variables from an outer scope when in an inner function. The outer variable is looked up when the inner function is run, not when the inner function is defined (so all versions of the function see the variable's last value). For each function to see a different value, you either need to make sure they're looking in separate namespaces, or you need to bind the value to a default parameter of the inner function.
Here's an approach that uses an extra namespace:
def func(a, b):
list_of_funcs = [make_func(i) for i in range(10)]
Each inner function
func has access to the
x parameter in the enclosing
make_func function. Since they're all created by separate calls to
make_func, they each see separate namespaces with different
Here's the other approach that uses a default argument (with functions created by a lambda expression):
list_of_funcs = [lambda a, b, x=i: a*b*x for i in range(10)]
In this version, the
i variable from the list comprehension is bound to the default value of the
x parameter in the lambda expression. This binding means that the functions wont care about the value of
i changing later on. The downside to this solution is that any code that accidentally calls one of the functions with three arguments instead of two may work without an exception (perhaps with odd results).