Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

lambda function don't closure the parameter in Python?

Tags:

python

lambda

Code talks more:


from pprint import pprint

li = []

for i in range(5):
        li.append(lambda : pprint(i))

for k in li:
        k()

yield:

4
4
4
4
4

why not

0
1
2
3
4

??

Thanks.

P.S. If I write the complete decorator, it works as expected:



from pprint import pprint

li = []

#for i in range(5):
        #li.append(lambda : pprint(i))

def closure(i):
        def _func():
                pprint(i)
        return _func

for i in range(5):
        li.append(closure(i))

for k in li:
        k()
like image 374
Grissiom Avatar asked Sep 22 '11 11:09

Grissiom


3 Answers

you need to do:

lambda i=i: pprint(i)

instead to capture the current value of i

like image 149
Dan D. Avatar answered Sep 28 '22 00:09

Dan D.


It does properly reference i, only the thing is, that by the time your list gets populated, i would have the value assigned form the last item in the sequence when the iteration ended, so that's why your seeing 4 all over.

like image 45
Filip Dupanović Avatar answered Sep 28 '22 01:09

Filip Dupanović


If you don't want to use a default argument -- which could introduce bugs if accidentally called with an argument -- you can use a nested lambda:

from pprint import pprint

li = []

for i in range(5):
    li.append((lambda x: lambda: pprint(x))(i))

for k in li:
    k()

This is an anonymous version of your closure function.

like image 44
Eryk Sun Avatar answered Sep 28 '22 00:09

Eryk Sun