[Python-Dev] Informal educator feedback on PEP 572 (was Re: 2018 Python Language Summit coverage, last part)
On Sat, Jun 30, 2018 at 11:32:03PM -0500, Tim Peters wrote:
> So, no, gaining performance is _not_ the motivation here. You already had
> a way to make it "run fast'. The motivation is the _brevity_ assignment
> expressions allow while _retaining_ all of the two-statement form's
> advantages in easier readability, easier reasoning, reduced redundancy, and
I think the two of you (Tim and Nick) are in violent agreement :-)
In fairness to Nick performance is _a_ motivation here, in the sense of
"how can we avoid making redundant multiple calls to a function in an
expression without splitting it into multiple statements?".
If performance were the *only* concern, then I agree with your point
that we already have a solution. Simply refactor this:
process(expensive_call(arg), expensive_call(arg) + 1)
useful_value = expensive_call(arg)
process(useful_value, useful_value + 1)
But since performance is not the *only* concern, all the other factors
you refer to (saving vertical space, DRY, side-effects, etc) count too.
Assignment expressions aren't valuable because they give us One Big Win.
They're valuable because they give us Many Little Wins, which we
(proponents of PEP 572) believe will outweigh the (minor) additional
costs in complexity and opportunities for abuse.
The closest (in my opinion) assignment expressions comes to a One Big
Win is to reduce the need for cascades of if... statements:
m = re.match(pattern, text)
m = re.match(other_pattern, text)
m = re.match(third_pattern, text)
if m: ...
which wastes both vertical and horizontal space.
If that were the *only* win, I'd consider dedicated syntax for if/elif
statements alone, but it isn't. Little wins include:
- use in while statement headers, "while x:= expr"
- DRY inside comprehensions, as an alternative to the neat but somewhat
[(x, x+1, x*2) for a in it for x in (func(a),) if x]
- running totals and similar inside comprehensions, where
we need a way to initialise the total on the first iteration
total = 0
[total := total + a for a in it]
- and examples such as Tim's use of Heron's Formula:
area = sqrt((s := (a+b+c)/2)*(s-a)*(s-b)*(s-c))
This last one is, I think, the only one where the postfix form
reads better, but maybe I only say that because I'm more
familiar with it:
area = sqrt(s*(s-a)*(s-b)*(s-c)) where s = (a+b+c)/2