On Fri, Oct 23, 2020 at 11:10 AM Steven D'Aprano <steve@pearwood.info> wrote:
> but that doesn't make it make sense to write `... = **values` as you
> suggest.

Iterator unpacking on a dict already works:

    py> d = {'a': 10, 'b': 20}
    py> spam, eggs = d
    py> spam, eggs
    ('a', 'b')

so we need to distinguish the iterator unpacking case from the dict
unpacking case.

I understand that, I just don't think this particular method of distinguishing is sufficiently justified.

(Heretical question: do we *really* need to distinguish it in syntax? Iterator unpacking a dict seems like a dumb idea, I wouldn't be sad if we broke compatibility there)

To me it makes sense to use the same double star used in
dict unpacking inside dict displays and function calls.

It makes some sense, but overall it's still quite different to anything existing. Typically the mechanics of assignment are defined by symbols that come before the =. This applies to iterable unpacking, setting attributes and mapping items, and augmented assignment. Everything after = just a normal expression.

The most obvious syntax is to just assign to a dict display:

    {'spam': spam, 'eggs': eggs, **kw} = kwargs  # not **kwargs

The meaning seems intuitive and obvious at a glance. And it's flexible if the variable names don't always match the keys. But it's verbose and repetitive in the common case where the names match.

I think it would be great if we had a syntax for abbreviating normal dicts with 'same name' keys. We discussed a lot of options earlier this year, e.g:

    {**, spam, eggs}
    {:spam, :eggs}
    {{spam, eggs}}

Then using the same syntax in both dict unpacking and dict displays as expressions would be intuitive and obvious. This would be valid, although redundant:

    {**, spam, eggs} = {**, spam, eggs}

and it would still be easy to add cases where names don't match:

    {'sleep': duration, **, spam, eggs} = kwargs

Also, unpacking nested dicts follows naturally, whether we have an abbreviated syntax or not:

    {'spam': {'eggs': eggs, 'foo': foo}, 'bar': bar} = {'spam': {'eggs': eggs, 'foo': foo}, 'bar': bar}

As does unpacking in a loop:

    for {**, spam, eggs} in list_of_dicts:

whereas I'm not sure what would be done in your proposal. Something like this?

    for spam, eggs in **list_of_dicts: