Wednesday, March 17, 2010

More Python weirdness

You can almost use Python as a functional language, but ... you run into trouble.  The following code, discovered by Nithin Reddy, will raise an exception:

funs = [lambda i: i + j for j in [1,2,3,4,5]]
del j
funs[0](1)


The issue is that lambda, which executes in the context of the lambda call rather than the lambda creation. Using a proper def won't work either -- the following code fails in precisely the same way:
funs = []
for j in [1,2,3,4,5]:
  def f(a): return a + j
  funs.append(f)
del j
funs[0](1)



The fix is to curry your function:

def partial(f, *args, **kwargs):
  def bound_f(*args2, **kwargs2):
    x = kwargs.copy()
    x.update(kwargs2)
    return f(*(args + args2), **x)
  return bound_f

import operator
funs = [partial(operator.add,j) for j in [1,2,3,4,5]]
del j
funs[0](1)


I'm not quite sure what to make of this. Is function context bound on return?

No comments: