scoping with lambda in loops

Christos TZOTZIOY Georgiou tzot at sil-tec.gr
Tue Sep 16 23:48:41 CEST 2003


On 16 Sep 2003 14:38:16 -0700, rumours say that imcmeans at telus.net (Ian
McMeans) might have written:

>First, I made multiple lambda functions inside a loop, each of which
>depended on the current loop variable.
>
>>>> a = []
>>>> for index in range(5):
>	a.append(lambda: index)
>
>Now, see if you can guess what the output was for each of the
>functions in the list a:
>>>> a[0](), a[1](), a[2](), a[3](), a[4]()
>I had expected it to be (0, 1, 2, 3, 4), but actually, it's:
>
>(4, 4, 4, 4, 4)
>
>This really surprised me. I guess what is happening is that each
>lambda knows what the context of execution is where it was defined,
>and doesn't actually evaluate until the function is called, and when
>it does evaluate, it uses the current value of the variable. Is this
>related to static scoping? A similar thing would happen if you defined
>a nested function that used a variable declared in the outer function,
>then changed that variable, and called the nested function.
>
>Can someone recommend a way to code around this gotcha? I'm having
>trouble. I want the functions created inside the loop to execute with
>the value of the loop index at the moment when the function is made.

I think this is a FAQ (perhaps it was FAQ 6.10?), and you can find many
threads on the subject if you do a search on groups.google.com.

The typical way to deal with this, IIRC, is to change your lambda
declaration into:

>	a.append(lambda index=index: index)

so that index gets evaluated at definition time.
-- 
TZOTZIOY, I speak England very best,
Microsoft Security Alert: the Matrix began as open source.




More information about the Python-list mailing list