3

I want to create a list of functions consisting of function objects created by a fixed base function but with different input parameters. I have written such code:

def f_base(name):
    print "I am %s" % name

f_list = []
for name in ['A', 'B']:
    f_list.append(
        lambda : f_base(name)
    )

f_list[0]()
f_list[1]()

The result is:

I am B
I am B

But I want to get:

I am A
I am B

Can someone explain why Python produces such output and what is the easiest way to get the result I need?

2 Answers 2

4

All you're doing with the lambda functions now is calling f_base on the variable name in the body. The name variable is determined at the time you call those lambda functions and not at the time you create each function.

The variable name refers to 'B' after you finish looping since python keeps variables defined in for loops around after the loop is done.

This is particularly obvious if you do,

name = 'C'

after the loop and before calling the functions. Then you get,

I am C
I am C

To do what you want you need to create a closure function or, probably better, use functools.partial.

import functools

def f_base(name):
    print "I am %s" % name

f_list = []
for name in ['A', 'B']:
    f_list.append(
        functools.partial(f_base, name)
    )

f_list[0]()
f_list[1]()

Which produces,

I am A
I am B
Sign up to request clarification or add additional context in comments.

2 Comments

Also known as infamous 'late binding gotcha'
Great! Thanks for the answer!
1

You can create closure:

def f_base(name):
    def closure():
        print "I am %s" % name
    return closure

f_list = []
for name in ['A', 'B']:
    f_list.append( f_base(name) )

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.