Unexpected behaviour of lambda function?

Howdy Folks,

I am a little baffled:

2022-08-31_PythonFctList

I would have expected an output of 0…9 - not 10 times 9… Can someone explain me why this happens - I do not get it?

Thanks and Cheers
Dominik

OK, I obviously had some minutes of dumbness - now I think, I can answer it for myself - ‘indexI’ is not ‘replaced’ by the integer 0…9 but instead refers to the object containing an integer - said 9 - after the loop. This is due to the fact, that the lambda expression is not evaluated at the time of definition, but at the time of execution - right? Any ideas for a nice solution getting 0…9?

You’ve found your way into an issue common enough to be a FAQ :slight_smile:

Note: in future, please post code directly using a preformatted text “code block” (see the </> button in the edit toolbar) rather than posting a screenshot of code.

2 Likes

This seems to work

fctL = []
for indexI in range(10):
    fctL.append( eval("lambda x: %d" % indexI) )

for fct in fctL:
    print (fct(0))

A simple solution would be something like

fctL = []
for indexI in range(10):
    fctL.append(lambda x=indexI: x)

for fct in fctL:
    print(fct())

By using indexI as the default value for your lambda, you’re capturing its value at the time of creating your lambda, rather than capturing a reference to the variable itself (which will be modified), as in the original.

2 Likes

It seems like the same applies for locally defined functions, which is very similar to lambdas - but should be explicitly document as well.

Example:

def outer():

    fd = {}

    for _ in range(5):
    
        s = f"{_}"
        
        def inner():
            return s

        fd[_] = inner

    return fd

if __name__ == '__main__':
    for k,v in outer().items():
        print(f'{v()} should be {k}')

Unfortunately this is really annoying when the inner() function is supposed to be a callback that is passed from the loop

Yes; the behaviour you’re seeing isn’t special to lambda, and in fact, there’s nothing special about lambda functions at all (at least, not in any technical sense). Whatever you can do with a lambda function, you can do with a def function, and the effect will be the same. The lambda keyword just gives you a convenient way of inlining a function definition in the place where it’s going to be used.