Monday, October 11, 2010

Stupid novice error in closures in Python

I am wrapping a bunch of functions in python, so that they could take different arguments:


for fun in functions:
def wrapper(state):
return fun(state.current)
# store wrapper as wrapped function


What's wrong with this picture? All wrappers end up calling the same function - the last in the list.

Took me about half an hour to figure it out. Closure in Python wraps a _variable_, not the object that the variable holds like it does in Java. The variable is shared between all wrappers - it's "fun". So all wrappers end up calling whatever is the value of "fun" at the time of call to the wrapper - the last function in the list. At the time of call to the wrapper, not wrapper creation!

The solution is of course



def wrap_function(fun):
def wrapper(state):
return fun(state.current)
return wrapper

for fun in functions:
wrapped_function = wrap_function(fun)



Now each wrapper gets its own "fun" variable - the one inside the particular invocation of wrap_function. Hurray!

No comments: