Python generating a lookup table of lambda expressions
<p>I'm building a game and in order to make it work, I need to generate a list of "pre-built" or "ready to call" expressions.  I'm trying to do this with lambda expressions, but am running into an issue generating the lookup table.  The code I have is similar to the following:</p>

<pre><code>import inspect

def test(*args):
    string = "Test Function: "
    for i in args:
        string += str(i) + " "
    print(string)

funct_list = []

# The problem is in this for loop
for i in range(20):
    funct_list.append(lambda: test(i, "Hello World"))

for i in funct_list:
    print(inspect.getsource(i))
</code></pre>

<p>The output I get is:</p>

<pre><code>funct_list.append(lambda: test(i, "Hello World"))
funct_list.append(lambda: test(i, "Hello World"))
funct_list.append(lambda: test(i, "Hello World"))
funct_list.append(lambda: test(i, "Hello World"))
...
</code></pre>

<p>and I need it to go:</p>

<pre><code>funct_list.append(lambda: test(1, "Hello World"))
funct_list.append(lambda: test(2, "Hello World"))
funct_list.append(lambda: test(3, "Hello World"))
funct_list.append(lambda: test(4, "Hello World"))
...
</code></pre>

<p>I tried both of the following and neither work</p>

<pre><code>for i in range(20):
    funct_list.append(lambda: test(i, "Hello World"))

for i in range(20):
    x = (i, "Hello World")
    funct_list.append(lambda: test(*x))
</code></pre>

<p>My question is how do you generate lists of lambda expressions with some of the variables inside the lambda expression already set.</p>

<p>As others have mentioned, Python's closures are <em>late binding</em>, which means that variables from an outside scope referenced in a closure (in other words, the variables <em>closed over</em>) are looked up at the moment the closure is called and <em>not</em> at the time of definition.</p>

<p>In your example, the closure in question is formed when your lambda references the variable <code>i</code> from the outside scope. However, when your lambda is called later on, the loop has already finished and left the variable <code>i</code> with the value 19.</p>

<p>An easy but not particularly elegant fix is to use a default argument for the lambda:</p>

<pre><code>for i in range(20):
    funct_list.append(lambda x=i: test(x, "Hello World"))
</code></pre>

<p>Unlike closure variables, default arguments are bound early and therefore achieve the desired effect of capturing the value of the variable <code>i</code> at the time of lambda definition.</p>

<p>A better way is use <code>functools.partial</code> which allows you to partially apply some arguments of the function, "fixing" them to a certain value:</p>

<pre><code>from functools import partial

for i in range(20):
    funct_list.append(partial(lambda x: test(x, "Hello World"), i))
</code></pre>

python function lambda functional-programming anonymous-function