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 אלעזר
On Wed, Oct 12, 2016 at 11:26 PM David Mertz
wrote: On Wed, Oct 12, 2016 at 12:38 PM, אלעזר
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.