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

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