[Python-ideas] Fwd: Fwd: unpacking generalisations for list comprehension

Steven D'Aprano steve at pearwood.info
Thu Oct 13 18:15:26 EDT 2016


On Thu, Oct 13, 2016 at 10:40:19PM +0200, Sjoerd Job Postmus wrote:

> Likewise,
> 
>     l = [f(t) for t in iterable]
> 
> can be seen as sugar for
> 
>     def gen():
>         for t in iterable:
>             yield f(t)
>     l = list(gen())

But that is *not* how list comprehensions are treated today. Perhaps 
they should be?

https://docs.python.org/3.6/reference/expressions.html#displays-for-lists-sets-and-dictionaries


(Aside: earlier I contrasted "list display" from "list comprehension". 
In fact according to the docs, a comprehension is a kind of display, a 
special case of display. Nevertheless, my major point still holds: a 
list display like [1, 2, 3] is not the same as a list comprehension like 
[a+1 for a in (0, 1, 2)].)

There may be some conceptual benefits to switching to a model where 
list/set/dict displays are treated as list(gen_expr) etc. But that still 
leaves the question of what "yield *t" is supposed to mean?

Consider the analogy with f(*t), where t = (a, b, c). We *don't* have:

    f(*t) is equivalent to f(a); f(b); f(c)

So why would yield *t give us this?

    yield a; yield b; yield c

By analogy with the function call syntax, it should mean:

    yield (a, b, c)

That is, t is unpacked, then repacked to a tuple, then yielded.


 
> Now the suggested spelling
> 
>     l = [*f(t) for t in iterable]
> 
> is very confusing, from what I understand: what does the `*` even mean
> here.

Indeed. The reader may be forgiven for thinking that this is yet another 
unrelated and arbitrary use of * to join the many other uses:

- mathematical operator;
- glob and regex wild-card;
- unpacking;
- import all
- and now yield from


> However, consider the following spelling:
> 
>     l = [from f(t) for t in iterable]
> 
> To me, it does not seem far-fetched that this would mean:
> 
>     def gen():
>         for t in iterable:
>             yield from f(t)
>     l = list(gen())


Now we're starting to move towards a reasonable proposal. It still 
requires a conceptual shift in how list comprehensions are documented, 
but at least now the syntax is no longer so arbitrary.


-- 
Steve


More information about the Python-ideas mailing list