0

what's wrong with the following code?

arrs={}
def func(i):
    print i
for i in range(1,5):
    arrs[i]=lambda:func(i)
for key in arrs.keys():
    arrs[key]()

I want it to print 1 2 3 4. instead it prints 4 4 4 4

1 Answers1

0

This is a common issue encountered when using lambda. When you run arrs[i]=lambda: func(i), lambda does not produce a function that retains the current i value. This is actually exactly the same as if you did a normal function definition:

def func(i):
    return i

i = 5
def anon():
    return func(i)

i = 0
anon()

i is treated like any standard variable, whose value is originally searched for in the local namespace of the function, and because it's not there, it'll search for the name at the global level. At which point it finds the current value of i, not the value of i when the function was originally defined.

A way around this (and a common idiom) is to create the lambda function with an input, and assign the current value of i as the default parameter.

arrs={}
def func(i):
    print i
for i in range(1,5):
    arrs[i]=lambda i=i:func(i)
for key in arrs.keys():
    arrs[key]()

This binds the value of i at function definition time as the default parameter, so is not affected by the global i value.

zehnpaard
  • 6,003
  • 2
  • 25
  • 40