Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deferred evaluation with lambda in Python

In a loop, I am trying to defer the comparison the two value()s of two Nodes to a later time.

class Node():
    def __init__(self, v):
        self.v = v
    def value(self):
        return self.v

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

for result in results:
    print result

The results are all True (because i,j==2,5 for all the lambdas). How can I defer the execution of the lambda until it is actually called, but with the correct variable bindings? And the expressions in the lambda are not all necessarily equality... there are a bunch of other more involved expressions.

Thanks for any help!

like image 316
Albeit Avatar asked Jun 18 '12 16:06

Albeit


People also ask

What is Lamda function in Python?

Python Lambda Functions are anonymous function means that the function is without a name. As we already know that the def keyword is used to define a normal function in Python. Similarly, the lambda keyword is used to define an anonymous function in Python.

Can lambda function evaluate multiple expressions?

Lambda functions can only have one expression in their body. Regular functions can have multiple expressions and statements in their body.

Is it good practice to use lambda in Python?

Best practices for using Python lambdas Certainly, lambdas have the advantage of making our code concise, but their overuse in our projects can lead to misuses that reduce our code's readability and maintainability.

Can Python lambda take two arguments?

A lambda function can take any number of arguments, but can only have one expression.


2 Answers

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.

like image 126
georg Avatar answered Nov 05 '22 05:11

georg


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]
like image 40
ecatmur Avatar answered Nov 05 '22 07:11

ecatmur