detaching comprehensions

Ian Kelly ian.g.kelly at gmail.com
Fri Sep 8 16:46:16 EDT 2017


On Fri, Sep 8, 2017 at 2:24 PM, Stefan Ram <ram at zedat.fu-berlin.de> wrote:
>   Maybe you all know this, but to me this is something new.
>   I learnt it by trial and error in the Python 3.6.0 console.
>
>   Most will know list comprehensions:
>
> |>>> [ i for i in range( 3, 5 )]
> |[3, 4]
>
>   I found out that the comprehension can be detached from the list:
>
> |>>> k =( i for i in range( 3, 5 ))
>
>   but one must use an extra pair of parentheses around it in the
>   assignment.

You don't need an *extra* pair of parentheses per se. The generator
expression simply must be enclosed in parentheses. This is perfectly
valid:

py> sum(i for i in range(3, 5))

>   Now I can insert the "generator" »k« into a function call,
>   but a spread operator should cannot be used there.

If you mean the * syntax, certainly it can.

> |>>> sum( k )
> |7

But you don't want it in this case, because that would do the wrong thing.

>   »sum« expects exactly two arguments, and this is what »k«
>   provides.

Not exactly. sum(k) is only providing the first argument to sum. The
first argument is required to be an iterable, which is what k is. The
second argument, "start", takes its default value of 0. This is
effectively equivalent to calling sum([3, 4]).

sum(*k) on the other hand would spread the values of k over the
arguments of sum and would be equivalent to calling sum(3, 4), which
raises a TypeError because 3 is not iterable.

>   But to insert it again into the place where it was "taken
>   from", a spread operator is required!
>
> |>>> k =( i for i in range( 3, 5 ))
> |>>> [ *k ]
> |[3, 4]

Alternatively:

py> list(k)
[3, 4]

As a final aside, storing a generator in a temporary variable is
usually bad style because it sets up an expectation that the contents
of the variable could be used more than once, when in fact a generator
can only be iterated over once.



More information about the Python-list mailing list