开发者

lambda function don't closure the parameter in Python? [duplicate]

This question already has answers here: What do lambda function closures capture? (7 answers) 开发者_运维技巧 Closed 8 months ago.

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()


you need to do:

lambda i=i: pprint(i)

instead to capture the current value of i


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.


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.


The lambda functions create closures over the i variable. After the first for loop is finished, i has value 4.

Then the second for loop starts and all the lambda functions are executed. Each of them then prints the current value of i, which is 4.


The answer: Because the code inside the lambda is using your global variable i.

Your second variant will do the same as the first one with lambda if you remove the parameter i:

def closure():

Instead of

def closure(i):

I.e. the code inside the function will use the global variable i.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜