Temporary variables in list comprehensions

Rustom Mody rustompmody at gmail.com
Mon Jan 9 07:59:56 EST 2017


On Monday, January 9, 2017 at 5:54:15 PM UTC+5:30, Tim Chase wrote:
> On 2017-01-09 02:46, Paul Rubin wrote:
> > > gen = (expensive_calculation(x) for x in data)
> > > result = [(tmp, tmp + 1) for tmp in gen]  
> > 
> > result = [(tmp, tmp+1) for tmp in map(expensive_calculation, data)]
> 
> As charmingly expressive as map() is, the wildly different behavior in
> py3 (it's a generator that evaluates lazily) vs py2 (it consumes the
> entire iterable in one go) leads me to avoid it in general,
> especially when Python gives me list-comprehensions and generators
> that can do what I intend explicitly.  E.g., passing in
> itertools.count() as an iterable to map() will kill py2 but is
> perfectly fine in py3 (a horrible example):
> 
>   import itertools as i
>   for x in i.takewhile(
>       lambda n: n < 100, 
>       map(lambda g: g**2, i.count())
>       ):
>     print(x)
> 
> But yes, both ChrisA's pass-it-to-a-function and Serhiy's nested
> generate-the-tmp-values-then-operate-on-those are good solutions
> depending on how they feel in any particular context.  If I need to
> use an "if" clause in the outer generator that tests the resulting
> temp values, I use Serhiy's solution:
> 
>   [(tmp, tmp + 1)
>     for tmp in (
>       expensive_calculation(x)
>       for x in data
>       )
>     if tmp > 42
>     ]

What happens when the expensive is on an inner generator?
Something like:

[expensive₂(y)  for x in data for y in foo(x)]

[The ₂ representing the 2 or more occurrences in Steven's eg]


More information about the Python-list mailing list