How to set local variable in list comprehension?
Solution 1:
Use nested list comprehension:
[x for x in [map_to_obj(v) for v in v_list] if x]
or better still, a list comprehension around a generator expression:
[x for x in (map_to_obj(v) for v in v_list) if x]
Solution 2:
Starting Python 3.8
, and the introduction of assignment expressions (PEP 572) (:=
operator), it's possible to use a local variable within a list comprehension in order to avoid calling twice the same function:
In our case, we can name the evaluation of map_to_obj(v)
as a variable o
while using the result of the expression to filter the list; and thus use o
as the mapped value:
[o for v in [v1, v2, v3, v4] if (o := map_to_obj(v))]
Solution 3:
A variable assignment is just a singular binding:
[x for v in l for x in [v]]
This is a more general answer and also closer to what you proposed. So for your problem you can write:
[x for v in v_list for x in [map_to_obj(v)] if x]
Solution 4:
You can avoid re-calculation by using python built-in filter
:
list(filter(lambda t: t is not None, map(map_to_obj, v_list)))
Solution 5:
A local variable can be set within a comprehension by cheating a bit and using an extra 'for' which "iterates" through a 1-element tuple containing the desired value for the local variable. Here's a solution to the OP's problem using this approach:
[o for v in v_list for o in (map_to_obj(v),) if o]
Here, o
is the local variable being set equal to map_to_obj(v)
for each v
.
In my tests this is slightly faster than Lying Dog's nested generator expression (and also faster than the OP's double-call to map_to_obj(v)
, which, surprisingly, can be faster than the nested generator expression if the map_to_obj
function isn't too slow).