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

אלעזר elazarg at gmail.com
Wed Oct 12 16:39:41 EDT 2016


To be honest, I don't have a clear picture of what {**x for x in d.items()}
should be. But I do have such picture for

    dict(**x for x in many_dictionaries)

Elazar

‪On Wed, Oct 12, 2016 at 11:37 PM ‫אלעזר‬‎ <elazarg at gmail.com> wrote:‬

> On Wed, Oct 12, 2016 at 11:26 PM David Mertz <mertz at gnosis.cx> wrote:
>
> On Wed, Oct 12, 2016 at 12:38 PM, אלעזר <elazarg at gmail.com> wrote:
>
> What is the intuition behind [1, *x, 5]? The starred expression is
> replaced with a comma-separated sequence of its elements.
>
> I've never actually used the `[1, *x, 5]` form.  And therefore, of course,
> I've never taught it either (I teach Python for a living nowadays).  I
> think that syntax already perhaps goes too far, actually; but I can
> understand it relatively easily by analogy with:
>
>      a, *b, c = range(10)
>
>
> It's not exactly "analogy" as such - it is the dual notion. Here you are
> using the "destructor" (functional terminology) but we are talking about
> "constructors". But nevermind.
>
>
> But the way I think about or explain either of those is "gather the extra
> items from the sequence." That works in both those contexts.  In contrast:
>
>     >>> *b = range(10)
>     SyntaxError: starred assignment target must be in a list or tuple
>
> Since nothing was assigned to a non-unpacked variable, nothing is "extra
> items" in the same sense.  So failure feels right to me.  I understand that
> "convert an iterable to a list" is conceptually available for that line,
> but we already have `list(it)` around, so it would be redundant and
> slightly confusing.
>
>
> But that's not a uniform treatment. It might have good reasons from
> readability point of view, but it is an explicit exception for the rule.
> The desired behavior would be equivalent to
>
>     b = tuple(range(10))
>
> and yes, there are Two Ways To Do It. I would think it should have been
> prohibited by PEP-8 and not by the compiler. Oh well.
>
> What seems to be wanted with `[*foo for foo in bar]` is basically just
> `flatten(bar)`.  The latter feels like a better spelling, and the recipes
> in itertools docs give an implementation already (a one-liner).
>
> We do have a possibility of writing this:
>
>     >>>  [(*stuff,) for stuff in [range(-5,-1), range(5)]]
>     [(-5, -4, -3, -2), (0, 1, 2, 3, 4)]
>
> That's not flattened, as it should not be.  But it is very confusing to
> have `[(*stuff) for stuff in ...]` behave differently than that.  It's much
> more natural—and much more explicit—to write:
>
>     >>> [item for seq in [range(-5,-1), range(5)] for item in seq]
>     [-5, -4, -3, -2, 0, 1, 2, 3, 4]
>
>
> The distinction between (x) and (x,) is already deep in the language. It
> has nothing to do with this thread
>
> >>> [1, *([2],), 3]
> [1, [2], 3]
> >>> [1, *([2]), 3]
> [1, 2, 3]
>
> So there. Just like in this proposal.
>
> Elazar.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20161012/ed2a3b19/attachment-0001.html>


More information about the Python-ideas mailing list