Skip to content

Instantly share code, notes, and snippets.

@breuderink
Created December 30, 2012 11:43
Show Gist options
  • Save breuderink/4412463 to your computer and use it in GitHub Desktop.
Save breuderink/4412463 to your computer and use it in GitHub Desktop.
Closures, partial application caveats in Python
It can be convenient to generate a series of related, but different functions.
For example, I had to evaluate a statistical model with different parameters.
But the results were surprising, as can be seen with this simplified example:
>>> funs = [lambda : x for x in range(10)]
>>> print [f() for f in funs]
[9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
I would have expected each of these functions to return a different value.
The same problem occurs when we define a regular function:
>>> funs = []
>>> for i in range(10):
... def f():
... return i
... funs.append(f)
>>> print [f() for f in funs]
[9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
There are many tricks to avoid this issue, but they somehow feel clumsy since
they rely on subtle semantic properties. Enter the functools module in the
Python standard lib:
>>> import functools
>>> def f(x): return x
>>> funs = [functools.partial(f, x) for x in range(10)]
>>> print [f() for f in funs]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Now, the reason this works is probably because a new scope is defined with the
call to functools.partial. But I do like this solutions , since it clearly
communicates that want to specialize a common function --- which is often the
case if they are generated automatically.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment