Python: assignment in lambdas

TL;DR Use default parameters to simulate assignment in lambdas.

Unlike C and C++, in Python assignment is an expression, not a statement. Python lambda can only return an expression, which means that there is no way to assign values for future reuse.

E.g., if we want to calculate (x2 + 2x + 7) + sqrt(x2 + 2x + 7), we can write a regular function as follows:

from math import sqrt
def mymath(x):
  y = x**2 + 2*x + 7
  return y + sqrt(y)

However, when defining a lambda, we cannot simply assign a variable like this:

from math import sqrt
# SyntaxError: invalid syntax
mymath = lambda x: (y = x**2 + 2*x + 7; y + sqrt(y))

Fortunately, there is a way to beat the system:

from math import sqrt
mymath = lambda x: (lambda y: y + sqrt(y))(x**2 + 2*x + 7)

Here the outer lambda creates an inner lambda, and then immediately executes it, supplying x**2 + 2*x + 7 as a parameter. It is bound to yin the inner lambda and is calculated only once. This works, but the order of calculations is counterintuitive: we first evaluate the expression on the right, and then the expression on the left. We can do better with default parameter values:

from math import sqrt
mymath = lambda x: (lambda y = x**2 + 2*x + 7: y + sqrt(y))()

Here we create an inner lambda where parameter y has default value of x**2+2*x+7, and then immediately execute it supplying no arguments. y takes the default value and is calculated only once. We can even create multiple variables this way, as long as they are independent:

from math import sqrt
mymath = lambda x: (lambda 
   y = x**2 + 2*x + 7, 
   z = x**3 + 12: 
   y - z + sqrt(y + z))()

This looks almost like a regular function with assignments, but it’s still a lambda.
Credit: https://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html

5 Comments


    1. Thank you! Very good point. I kind of knew about the walrus operator, but didn’t pay attention 🙂

      The background of this post was discussion on how safe “eval” is, and this is one of the techniques of simulating assignment that was discussed on the Internet. It probably predates the walrus operator, which, I believe was introduced in Python 3.8.

      Reply

Leave a Reply to fleming Cancel reply

Your email address will not be published. Required fields are marked *