Temporary variables in Python's list comprehension
Although list comprehensions are very handy, it is difficult to write non-trivial expressions, mostly because it is not possible to use variables to store temporary results. Or is it?
Consider a somewhat silly example:
[
2 * x
for x in range(10)
if x % 2 == 0 and 2 * x % 8 == 0
]
Here, we are filtering elements of an iterable, applying a transformation, and filtering the result. In particular, note that we are writing the transformation twice: when filtering, and when computing the result. Can we avoid this repetition?
Turns out it’s possible with a simple trick: put the transformed item into a list and use a nested comprehension:
[
y
for x in range(10)
if x % 2 == 0
for y in [2 * x]
if y % 8 == 0
]
This trick is straightforward to apply to multiple transformations and conditions, so that each step has access to the variables defined (and filtered) earlier:
[
process(each, tmp1, tmp2, tmp3)
for each in lst
if cond(each)
for tmp1 [ compute_tmp1(each) ]
if cond1(tmp1)
for tmp2 [ compute_tmp2(each, tmp1) ]
if cond2(tmp1, tmp2)
for tmp3 [ compute_tmp3(each, tmp1, tmp2) ]
if cond3(tmp1, tmp2, tmp3)
]
I leave it to you to decide whether this is a good idea in “serious” code. It’s uncommon enough to trigger a WTF in pretty much everybody reading this for the first time.