Temporary variables in list comprehensions

Tim Chase python.list at tim.thechases.com
Mon Jan 9 07:15:31 EST 2017


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
    ]
 
Otherwise, I like the cleanliness of ChrisA's function:

  def fn(x)
    tmp = expensive_calculation(x)
    return x, x + 1
  [fn(x) for x in data]

-tkc






More information about the Python-list mailing list