[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