[Question]
  [
*This is a tips question for golfing in Python.*
In Python golfing, it's common for a submission to be a function defined as a lambda. For example, 
```
f=lambda x:0**x or x*f(x-1)
```
[computes the factorial](https://codegolf.stackexchange.com/a/3133/20260) of x.
The lambda format has two [big advantages](https://codegolf.stackexchange.com/a/61526/20260):
* The boilerplate of `f=lambda x:...` or `lambda x:...` is shorter than the `def f(x):...return...` or `x=input()...print...`
* A recursive call can be used to loop with little byte overhead.
However, lambdas have the big drawback of allowing only a single expression, no statements. In particular, this means no assignments like `c=chr(x+65)`. This is problematic when one has a long expression whose value needs to be referenced twice (or more).
Assignments like `E=enumerate` are possible outside the function or as an optional argument, but only if they don't depend on the function inputs. Optional arguments like `f=lambda n,k=min(n,0):...` fail because input `n` hasn't been defined when `k` is evaluated at definition time. 
The result is that sometimes you suck up repeating a long expression in a lambda because the alternative is a lengthy non-lambda.
```
lambda s:s.strip()+s.strip()[::-1]
def f(s):t=s.strip();print t+t[::-1]
```
The break even point is about 11 characters ([details](https://codegolf.stackexchange.com/a/52317/20260)), past which you switch to a `def` or `program`. Compare this to the usual break-even point of length 5 for a repeated expression:
```
range(a)+range(b)
r=range;r(a)+r(b)
print s[1:],s[1:]*2
r=s[1:];print r,r*2
```
Other languages have workarounds, [Octave for example](https://codegolf.stackexchange.com/a/104753/20260). There are known tricks for Python, but they are long, clunky, and/or limited-use. A short, general-purpose method to simulate assignment in a lambda would revolutionize Python golfing. 
---
What are ways for a Python golfer to overcome or work around this limitation? What potential ideas should they have in mind when they see a long expression repeated twice in a lambda?
My goal with this tips question is to dive deep into this problem and:
* Catalog and analyze golfing workarounds to fake assignment inside a lambda
* Explore new leads for better methods
Each answer should explain a workaround or potential lead.
  
[Answer]
## Assignment expressions in Python 3.8
[Python 3.8](https://www.python.org/downloads/release/python-380a1/) ([TIO](https://tio.run/#python38pr)) introduces [assignment expressions](https://www.python.org/dev/peps/pep-0572/), which use `:=` to assign a variable inline as part of expression.
```
>>> (n:=2, n+1)
(2, 3)
```
This can be used inside a `lambda`, where assignments are not ordinarily allowed. Compare:
```
lambda s:(t:=s.strip())+t[::-1]
lambda s:s.strip()+s.strip()[::-1]
def f(s):t=s.strip();return t+t[::-1]
```
See [this tip](https://codegolf.stackexchange.com/a/180041/20260) for more.
[Answer]
### `eval`
This is not that great in of itself, but if your solution already uses `eval` in some way or form you can usually use this technique.
```
eval("%f*%f+%f"%((5**.5,)*3))
```
[Answer]
## Inner lambdas
These allow you to define multiple variables at once.
```
lambda s:s.strip()+s.strip()[::-1]
```
vs.
```
lambda s:(lambda t:t+t[::-1])(s.strip())
```
is much longer, but if you have multiple variables, or variables that are longer, which are repeated many times:
```
lambda a,b,c:a.upper()*int(c)+b.lower()*int(c)+a.upper()[::-1]+b.lower()[::-1]+a.upper()*int(c)+a.lower()*int(c)
```
vs.
```
lambda a,B,c:(lambda A,b,n:A*n+b*n+A[::-1]+b[::-1]+A*n+b*c)(a.upper(),B.lower(),int(c))
```
### Character count
Initial: `(lambda:)()` (11 bytes)  
First variable: `[space]a` (2 bytes)  
Subsequent variables: `,b,` (3 bytes)  
Use: `a` (1 byte).
```
(lambda* a*_,b_:)(*<value a>*_,<value b>_)
```
(Also saves on brackets)
So, this takes `3n + 10` bytes, where `n` is the number of variables. This is a high initial cost, but can pay off in the end. It even returns it's inner value,so you can nest multiple (Though this will quickly become not worth it.)
This is really only useful for long intermediate calculations in nested list comprehensions, as a `def f():a=...;b=...;return` will usually be shorter.
For 1 value, this saves: `uses * length - length - uses - 13`, so is only useful when that expression is positive.  
For a `n` different expressions used `u` times in total, where their combined length is `l`, this saves:  
`l - (3 * n) - u - 10 ( + brackets removed )`
[Answer]
# Use a List
Declare a list as parameter and use `.append() or` to store the value:  
`lambda s:s.lower()+s.lower()[::-1]`  
turns into  
`lambda s,l=[]:l.append(s.lower())or l[-1]+l[-1][::-1]`
### Character count:
`,l=[]` 5 characters  
`l.append()or`  13 characters  
`l[-1]` 5 characters for each use
### Break Even
The amount of added character is :  
`uses*(5-length) + 18 + length`  
In the previous example the statement is `s.lower()` is 9 characters long and is used 2 times, applying this technique added 19 characters.
If it was used 7 times, there would be a 1 character reduction.  
The amount of minimal uses to this technique be worth is  
`min_uses = (18+length)/(length-5)`
## Upsides
* Allow a new assignment at a slightly reduced cost (the list already is declared)
* Is a `list` object so `[0]`, `.pop()`, `[x:y]` and other list functions can be used for tricks. *highly situational*
## Downsides
* High initial cost
* High use cost
* Only works for uses with the length higher than `5`
---
# Use a Dictionary
thanks [@Zgarb](https://codegolf.stackexchange.com/users/32014/zgarb)  
Same idea as above
Declare a dictionary as parameter and use `.setdefault()` to store (and return) the value:  
`lambda s:s.lower()+s.lower()[::-1]`  
turns into  
`lambda s,d={}:d.setdefault(0,s.lower())+d[0][::-1]`  
Note that, unlike the `list` counterpart, `setdefault` returns the value assigned.
### Character count:
`,d={}` 5 characters  
`d.setdefault(k,)` 16 characters  
`d[k]` 4 characters for each use
### Break Even
The amount of added character is :  
`(uses-1)*(4-length) + 21`  
In the previous example the statement is `s.lower()` is 9 characters long and is used 2 times, applying this technique added 16 characters.
If it was used 7 times, there would be a 1 character reduction.  
The amount of minimal uses to this technique be worth is  
`min_uses = 1-21/(4-length)`
## Upsides/Downsides
* Basically the same as the list
* Only works for uses with the length higher than `4`
---
[Answer]
Use to set variables and return the data after operation like such:
```
add = lambda x, y: exec("x+=y")
```
[Answer]
# List comprehensions
This is more of a last resort since it's so ungolfy, but you can do  
`[<expression> for <variable> in <value>]`  
to pseudo-set a variable in a lambda. Basically the only good point about this method is that the inner expression can stay readable, which is obviously the least of your concern when golfing.
]