Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capturing Value instead of Reference in Lambdas

I was slightly surprised by this example given by Eli Bendersky (http://eli.thegreenplace.net/2015/the-scope-of-index-variables-in-pythons-for-loops/)

>>> def foo():
...     lst = []
...     for i in range(4):
...         lst.append(lambda: i)
...     print([f() for f in lst])
...
>>> foo()
[3, 3, 3, 3]

But when I thought about it, it made some sense — the lambda is capturing a reference to i rather than i's value.

So a way to get around this is the following:

>>> def foo():
...     lst = []
...     for i in range(4):
...         lst.append((lambda a: lambda: a)(i))
...     print([f() for f in lst])
...
>>> foo()
[0, 1, 2, 3]

It appears that the reason that this works is that when i is provided to the outer lambda, the outer lambda creates a scope and dereferences i, setting a to i. Then, the inner lambda, which is returned, holds a reference to a.

Is this a correct explanation?

like image 364
abhillman Avatar asked Jan 18 '15 21:01

abhillman


1 Answers

Default param is an another way to catch a value:

lst.append(lambda i=i: i)
like image 120
bav Avatar answered Nov 11 '22 19:11

bav