Python’s lambda is broken!

I quite like Python for teaching. And people praise it for the lambda construct which is a bit like $\lambda$-abstraction in functional languages. However, it is broken!

To see how lambda is broken, try generating a list of functions $[f_0, …, f_9]$ where $f_i(n) = i + n$. First attempt:

>>> fs = [(lambda n: i + n) for i in range(10)]
>>> fs[3](4)
13


Wait a minute, fs[3](4) ought to be 3 + 4 = 7! It looks like all 10 functions share the same “last” value of i, which is 9. Indeed:

>>> [f(4) for f in fs]
[13, 13, 13, 13, 13, 13, 13, 13, 13, 13]


This is certainly unexpected. Let us try to get around the problem by not using lambda:

>>> fs = []
>>> for i in range(10):
...    def f(n): return i+n
...    fs.append(f)
...
>>> [f(4) for f in fs]
[13, 13, 13, 13, 13, 13, 13, 13, 13, 13]


Still not working, so the reason is deeper, probably in the way environments are handled. Maybe like this:

>>> fs = []
>>> for i in range(10):
...    def f(n, i=i): return i+n
...    fs.append(f)
...
>>> [f(4) for f in fs]
[4, 5, 6, 7, 8, 9, 10, 11, 12, 13]


Victory! But try explaining to students what is going on.

Just to be sure, Haskell does the right thing, of course!

Prelude> let fs = [(\n -&gt; i + n) | i &lt;- [0..9]]
Prelude> [f(4) | f &lt;- fs]
[4,5,6,7,8,9,10,11,12,13]


What were the implementors of Python thinking?!

57 thoughts on “Python’s lambda is broken!”

1. @Aaron: yes, I think someone else pointed out a similar solution. But really, that doesn’t clarify anything. It’s a workaround.