[Python-Dev] (name := expression) doesn't fit the narrative of PEP 20

Tim Peters tim.peters at gmail.com
Thu Apr 26 01:57:44 EDT 2018


[Tim]
>> One language feature conspicuous by absence in newbie
>> confusions was, consistently, assignment expressions.  Read any book
>> or tutorial for such a language, and you'll find very little space
>> devoted to them too.

[Łukasz Langa <lukasz at langa.pl>]
> Well, you have an entire code style built around this feature called Yoda
> conditions. You teach people on Day 1 to never ever confuse == with =. Some
> compilers even warn about this because so many people did it wrong.

Sorry, I couldn't follow that.  In languages like C that use easily
confused operator symbols, sure, people are forever typing "=" when
they mean "==".  That's nothing to do with whether they _understand_
what the different operators do, though.  They do.  In languages like
Icon (that use "=" for numeric comparison and ":=" for assignment),
that never occurs.  But I'm not sure that addressed the point you were
making.


>> What's to learn?  If they understand "binding a name" _at all_ (which
>> they must to even begin to write a non-trivial program), the only
>> twist is that a binding expression returns the value being bound.

> Ha, not in Python! Here we have *different syntax* for assignments in
> expressions.

Yes, binding expressions in the current PEP support an extremely
limited subset of what Python's assignment statements support.  That
they use different operator symbols is irrelevant to that the meaning
of "binding a name" is exactly the same for both..  _That's_ the "hard
part" to learn.


> Well, you can also use it as a statement. But don't!

Why not?  _Every_ expression in Python can be used as a statement.
Nothing forbids it, and that's even (very!) useful at an interactive
prompt.


> We have a better one for that.

As a matter of style, sure, it's best to use the simplest thing that
works.  As a statement in a program (as opposed to typed at a shell),
"a := 3" has the unnecessary (in that context) property of returning
(and discarding 3), so it's better style to use "a = 3" in that
context.


> And that one supports type annotations, can unpack and assign to many
> targets at the same time, and can even increment, multiply and so on, at once.
> But the other one can't.

So?  math.sqrt() blows up when passed -1, but cmath.sqrt() doesn't.
Different tools for different tasks.


> So only use the Pascal one in expressions. But don't forget parentheses,
> otherwise it will bind the thing you probably didn't want anyway.

[Raymond]
>>> To my eyes, the examples give ample opportunity for being
>>> misunderstood and will create a need to puzzle-out the intended
>>> semantics.

>> Some do, many don't.

> As soon as we have to wrap a part of an expression in parentheses, parsing
> the entire thing becomes more complex. Often enough it will cause the
> expression to exceed whatever line length limit the codebase pledged not to
> exceed, causing one line to become three. And again, making it trickier for
> a regular Łukasz to understand what's going on.

At this point I think you must have a lower opinion of Python
programmers than I have ;-)  If adding even a dozen characters to a
line makes it exceed a reasonable line-length guide, the code was
almost certainly too confusingly dense to begin with.  All the
binding-expression examples I've given as "improvements" had _oceans_
of horizontal white space to swim in.

Guido's if/elif/elif/elif/ ... complex text-processing example didn't,
but because the current lack of an ability to bind-and-test in one
gulp forced the `elif` parts to be ever-more-deeply-indented `if`
blocks instead.

So, to match your sarcasm, here's mine:  try using a feature for what
it's good at instead of for what it's bad at ;-)


More information about the Python-Dev mailing list