# 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 `y`in 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