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

Steven D'Aprano steve at pearwood.info
Wed Oct 12 11:42:26 EDT 2016


On Tue, Oct 11, 2016 at 02:42:54PM +0200, Martti Kühne wrote:
> Hello list
> 
> I love the "new" unpacking generalisations as of pep448. And I found
> myself using them rather regularly, both with lists and dict.
> Today I somehow expected that [*foo for foo in bar] was equivalent to
> itertools.chain(*[foo for foo in bar]), which it turned out to be a
> SyntaxError.

To me, that's a very strange thing to expect. Why would you expect that 
unpacking items in a list comprehension would magically lead to extra 
items in the resulting list? I don't think that makes any sense.

Obviously we could program list comprehensions to act that way if we 
wanted to, but that would not be consistent with the ordinary use of 
list comprehensions. It would introduce a special case of magical 
behaviour that people will have to memorise, because it doesn't follow 
logically from the standard list comprehension design.

The fundamental design principle of list comps is that they are 
equivalent to a for-loop with a single append per loop:

    [expr for t in iterable]

is equivalent to:

    result = []
    for t in iterable:
        result.append(expr)


If I had seen a list comprehension with an unpacked loop variable:

    [*t for t in [(1, 'a'), (2, 'b'), (3, 'c')]]


I never in a million years would expect that running a list 
comprehension over a three-item sequence would magically expand to six 
items:

    [1, 'a', 2, 'b', 3, 'c']


I would expect that using the unpacking operator would give some sort 
of error, or *at best*, be a no-op and the result would be:

    [(1, 'a'), (2, 'b'), (3, 'c')]


append() doesn't take multiple arguments, hence a error should be the 
most obvious result. But if not an error, imagine the tuple unpacked to 
two arguments 1 and 'a' (on the first iteration), then automatically 
packed back into a tuple (1, 'a') just as you started with.

I think it is a clear, obvious and, most importantly, desirable property 
of list comprehensions with a single loop that they cannot be longer 
than the initial iterable that feeds them. They might be shorter, if you 
use the form

    [expr for t in iterable if condition]

but they cannot be longer.

So I'm afraid I cannot understand what reasoning lead you to 
expect that unpacking would apply this way. Wishful thinking 
perhaps?




-- 
Steve


More information about the Python-ideas mailing list