The Python Oracle

Deferred evaluation with lambda in Python

Become part of the top 3% of the developers by applying to Toptal https://topt.al/25cXVn

--

Music by Eric Matyas
https://www.soundimage.org
Track title: Switch On Looping

--

Chapters
00:00 Question
00:59 Accepted answer (Score 17)
01:29 Answer 2 (Score 9)
01:55 Answer 3 (Score 4)
02:14 Thank you

--

Full question
https://stackoverflow.com/questions/1108...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #lambda #deferredexecution

#avk47



ACCEPTED ANSWER

Score 18


To bind the current values of i and j to the function instead of having it look in the outer scope, you can use either a closure or default argument values. The easiest way to do this is to use default argument values in your lambda:

for i in [0, 1, 2]:
    j = i + 3
    results.append(lambda i=i, j=j: nodes[i].value() == nodes[j].value())

Here is how it would look as a closure:

def make_comp_func(i, j):
    return lambda: nodes[i].value() == nodes[j].value()

for i in [0, 1, 2]:
    j = i + 3
    results.append(make_comp_func(i, j))



ANSWER 2

Score 10


Wrap it in another lambda:

results.append((lambda x, y: lambda: nodes[x].value() == nodes[y].value()) (i, j))

or in a nicer way, with partial:

from functools import partial

results.append(partial(lambda x, y: nodes[x].value() == nodes[y].value(), i, j))

Default arguments trick is, well... a trick, and I'd suggest to avoid it.




ANSWER 3

Score 5


The idiomatic way is to use a default argument:

[f() for f in [lambda: i for i in range(3)]]
[2, 2, 2]

Change this to:

[f() for f in [lambda i=i: i for i in range(3)]]
[0, 1, 2]