0

I'm writing some scientific code in Python which solves a complicated optimization problem and (ideally) returns a list of univariate functions which are a series of solution to the problem at particular points in time (a list of time-indexed, univariate policy functions, if you will).

The list of functions needs to be independent from the object which creates it. This is where I hit trouble -- inevitably, each function in the list needs to reference a value which was solved-for and stored in a list in the solver object.

Here's a quick little program that illustrates the problem I'm running into:

class test:
    def __init__(self):
        self.vals = np.arange(5)


    def testfxns(self):
        fxns = {}
        for i in range(len(self.vals)):
            def temp_func(x):
                Z = self.vals[i]
                return Z + x
            fxns[i] = temp_func
            #del temp_func   # doesn't help
        return fxns

t1 = test()
z = t1.testfxns()


print z[0](2)
print z[1](2)
print z[2](2)
print z[3](2)
print z[4](2)

The output of the print statements is all 6's -- I'd like it to be 2, 3, 4, 5, 6.

Is there any way to address this? I need those constants in the "Z" variable to be inserted into each iteration of the list of functions. The "poor man's" solution would be to print out each constant value and then just manually type out the list of functions, manually typing the constant values I need into different individual function definitions.

Is there any way to obtain the value of "self.vals[i]" in a "dereferenced" way, programatically? (Hopefully that makes sense.) Or alternatively, what's the terminology related to even solving this issue -- what terms should I be googling and/or researching in the documentation? (Some of the trouble is not even knowing where to be looking.)

Thanks so much. I know there may be multiple issues I'm running into here, so all help/guidance is appreciated.

CompEcon
  • 1,994
  • 1
  • 14
  • 12
  • In addition to the info in the question I linked to, it seems like here your function is really more than a function, since it needs to store data. You might be better off creating a class and using instances of it to store the data. The approach described in the linked question becomes unwieldy if you have to store more than one or two pieces of data per function. – BrenBarn Apr 08 '14 at 04:18
  • I contemplated a class and instanced as the solution. May still do that, although I was shying away from a potentially "heavy" solution (the functions are pretty simple past one or two manipulations). – CompEcon Apr 08 '14 at 04:29
  • Also, @ both BrenBarn and mgilson -- thanks for the links. I think closures is exactly the terminology I was looking for. It's a tricky think to search for if you don't already know the term. Super helpful, thanks! – CompEcon Apr 08 '14 at 04:31

1 Answers1

3

This is a common problem with closures. The value of i is picked up when the function is called, not when it is created. The solution is to provide it as a keyword:

def temp_func(x, i=i):
    Z = self.vals[i]
    return Z + x

The keyword gets evaluated (and stored on the function object) when the function is created as opposed to when it is called.

mgilson
  • 300,191
  • 65
  • 633
  • 696
  • Excellent. So this is nearly the solution I need. Just tried it with "def temp_func(x, Z = self.vals[i])" and seem to get what I need. The added wrinkle is that the instance of the "test" object may be overwritten/removed by the time I need to use the list of functions, so I'm trying to detach the "temp_func" entirely. Is there any reason putting Z as the default value would be a bad idea? – CompEcon Apr 08 '14 at 04:31