[Python-Dev] PEP 572: Assignment Expressions (original) (raw)
Tim Peters tim.peters at gmail.com
Fri Apr 20 21:44:46 EDT 2018
- Previous message (by thread): [Python-Dev] PEP 572: Assignment Expressions
- Next message (by thread): [Python-Dev] PEP 572: Assignment Expressions
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
[Chris Angelico <rosuav at gmail.com>]
I don't see much value in restricting the assignment target to names only, but if that's what it takes, it can be restricted, at least initially.
I believe this point was made most clearly before by Terry Reedy, but it bears repeating :-) This is from the PEP's motivation:
""" Naming the result of an expression is an important part of programming, allowing a descriptive name to be used in place of a longer expression, and permitting reuse. """
As "head arguments" go, that's a good one! But restricting assignment expressions to
identifier ":=" expression
satisfies it. If what's of value is to name the result of an expression, that single case handles that and only that. In a sense, it's "the simplest thing that could possibly work", and that's generally a good thing to aim for.
Python assignment statements are way more complex than that. Besides just giving names to expression results, they can also implicitly invoke arbitrarily complex setitem and setattr methods on targets, rely on all sorts of side effects across chained assignments, and support funky syntax for magically iterating over an expression's iterable result.
While that can all be useful in an assignment statement, the PEP's motivation doesn't say a word about why any of that would also be useful buried inside an assignment expression. There doesn't appear to be a good "head argument" for why, besides "why not?". That's not enough.
I think it's no coincidence that every example of an intended use is of the simple
identifier ":=" expression
form. There are no examples of fancier targets in the PEP, and - more importantly - also none I saw in the hundreds of mailing-list messages since this started. Except for a few of mine, where I tried to demonstrate why trying fancier targets in examples derived from real code made the original "loop and a half" code worse And where other people were illustrating how incomprehensibly code could be written (which isn't a real interest of mine).
Short course: e.g., while a general assignment expression can
"unpack" an iterable expression result, giving names to its elements,
there's no clean way to use the names bound by the unpacking in
the "if" or "while" tests. That's fine for for
loops (only the
body of the loop needs the names), but in conditional constructs you
typically want to use the names in the condition being tested.
if ((a, b, c) := func_returning_triple()) and b > 0:
process(a+b, b+c, a+c)
seems to be as good as it gets, but inherently relies on "a trick": that a 3-tuple is always truthy, regardless of content. OTOH,
if ((a, b, c) := func_returning_triple())[1] > 0:
doesn't rely on a trick, but can't use the name b
in the test(!).
if [((a, b, c) := func_returning_triple()), b > 0][-1]::
manages to avoid "a trick", and to use the natural b > 0
, but is ...
strained ;-)
So, to my eyes, this is a clear improvement over all of those:
a, b, c = func_returning_triple()
if b > 0:
process(a+b, b+c, a+c)
Of course I could be cherry-picking a bad example there, but that's not the intent: I'm still waiting for anyone to post an example where a "fancy" assignment-expression target would actually make code clearer. I haven't found one.
There are lots of examples when the target is a plain single name.
Why the stark difference? I don't need deep theoretical reasons to see that there is one, or to conclude that - in the absence of compelling use cases - complex assignment-expression targets are probably a Poor Idea.
- Previous message (by thread): [Python-Dev] PEP 572: Assignment Expressions
- Next message (by thread): [Python-Dev] PEP 572: Assignment Expressions
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]