On Sat, Apr 18, 2020 at 8:18 AM Steven D'Aprano <steve@pearwood.info> wrote:
This proposal is an alternative to Rodrigo's "Keyword arguments
self-assignment" thread.

Rodrigo, please feel free to mine this for useful nuggets in your PEP.

(I don't claim to have invented the syntax -- I think it might have been
Alex Hall?)

lol everyone thinks I invented things I didn't...

The idea was first suggested by Dominik: https://mail.python.org/archives/list/python-ideas@python.org/message/S44VDMZ4AFBSGIQEVWMKKWOW4P6WRVXY/

I just suggested making the brackets curly to make it a bit more dict-like.
 
Keyword Unpacking Shortcut
--------------------------

Inside function calls, the syntax

    **{identifier [, ...]}

expands to a set of `identifier=identifier` argument bindings.

This will be legal anywhere inside a function call that keyword
unpacking would be legal. That means that syntactically it will legal to
mix this between other keyword arguments:

    # currently legal
    func(z=5, **d1, x=0, y=6, **d2, w=7)

    # propose to allow Keyword Unpacking Shortcut as well
    func(z=5, **d1, x=0, **{u, v}, y=6, **d2, w=7)

    # which would be equivalent to:
    func(z=5, **d1, x=0, u=u, v=v, y=6, **d2, w=7)

My issue with this, and maybe it's what Andrew is also trying to say, is that it breaks our usual assumptions about composing expressions. `{u, v}` is an expression, it represents a set, and it always represents that wherever you put it. Under your proposal, these two programs are both valid syntax with different meanings:

    f(**{u, v})

    x = {u, v}
    f(**x)

Is there anything else similar in the language? Obviously there are cases where the same text has different meanings in different contexts, but I don't think you can ever refactor an expression (or text that looks like an expression) into a variable and change its meaning while keeping the program runnable.

This proposal makes it harder for beginners to understand how a program is interpreted. It breaks the simple mental model where building blocks are combined in a consistent fashion into larger parts.

The example above looks a bit dumb, but maybe users will try:

```
if flag:
    kwargs = {u, v}
else:
    kwargs = {w, x}
f(**kwargs)
```

Which is valid syntax but is wrong. Then they might try changing that to:

    f(**({u, v} if flag else {w, x}))

which is suddenly invalid syntax. This is a very weird user experience. On that note, is this valid?

    f(**({u, v}))