So, the style guidelines for this new feature -- and also ternary expressions and comprehension -- would need to mention that:

- debuggers have no idea what to do with all of this on one line
- left-to-right doesn't apply to comprehensions

  results = [(x, y, x/y) for x in input_data if (y := f(x)) > 0]

- left-to-right doesn't apply to ternary expressions

  if (y := func(x)) if (x := 3) else 0:
  while (y := func(x)) if (x := 3) else 0:

- left-to-right does apply to everything else?

- *these* are discouraged:

  if (x := 3) or (y := func(x)):
  if (3) or (func(3)):
  if ((x := 3) if 1 else (y := func(x))):

IDK, I could just be resistant to change, but this seems like something that will decrease readability -- and slow down code review -- without any real performance gain. So, while this would be useful for golfed-down (!) one-liners with pyline,
I'm -1 on PEP 572.

How do I step through this simple example with a debugger?

    if, text) as match:

How do I explain what ':=' is when teaching Python?

AFAIU, semantically: Python = ('equals') indicates a statement. What you are proposing is adding an ':=' ('colon equals') assignment operator which defines a variable which is limited in scope only in list, dict, and generator comprehensions.

From :

> In some languages the symbol used is regarded as an operator (meaning that the assignment has a value) while others define the assignment as a statement (meaning that it cannot be used in an expression).

PEP 572 -- Assignment Expressions
PEP 572 -- Assignment Operator (:=) and Assignment Expressions

On Friday, April 27, 2018, Steven D'Aprano <> wrote:
On Thu, Apr 26, 2018 at 08:48:12AM -0700, Łukasz Langa wrote:
> > On Apr 25, 2018, at 11:10 PM, Steven D'Aprano <> wrote:
> > Criticising binding-
> > expressions for that reason, especially implying that we must always use
> > parens, is simply FUD.
> The PEP has more examples with parentheses than without.

Yes? Parens aren't mandatory, and my point that other operators also
sometimes needs parens still holds.

> >> As soon as we have to wrap a part of an expression in parentheses,
> >> parsing the entire thing becomes more complex.
> >
> > Unless it becomes less complex to read and understand.
> You're ignoring the context of the discussion. The new parentheses are
> there because there's a new assignment there. That's more complex.

I'm not ignoring the context of the discussion. I'm comparing binding-
expression with and without parens. That's what I thought you were

If that wasn't your intended meaning, then I apologise but please
understand why I answered the way I did.

I still stand by my argument: parens are not always needed, and even
when they are not needed, adding them can sometimes make things
*easier* and *less complex* to read.

> If you think demonstrating cases where the end result won't be an
> improvement is picking at straws, then maybe the improvement of PEP
> 572 is as well.

Any feature can have cases where the end result is worse than not using
the feature. That *alone* isn't a strong argument against a feature.

Do you have much existing code using binding expressions? Of course not.
Will you be adding them to code that already exists? Probably not -- you
can't do so until you are using 3.8 at minimum, and if your code needs
to be backwards compatible, you can't use it until you've dropped
support for 3.7 and older. That might not be for five or ten years.

So it is likely that for most people only new code will use this
feature. It is not reasonable to say that if I have existing code like

    spam = expression
    if long_condition_that_takes_up_most_of_the_line == spam or spam:

that I'm going to immediately change it to a one-liner:

    if long_condition_that_takes_up_most_of_the_line == (spam := expression) or spam:

and push it over the maximum line width. With or without parentheses.
Why would I do something so silly? Using binding expressions isn't
mandatory and most coders don't intentionally do things that make their
code worse.

And if I wouldn't change existing code and push it over the limit, why
would I write new code that does it? Especially when there are much
better alternatives:

    if (long_condition_that_takes_up_most_of_the_line
            == (spam:=expression)
            or spam):

We have a history of adding features that can be abused, but aren't.
People hardly ever abuse list comps with overly long and complex
multiple-loop comprehensions:

    [... for a in sequence for b in something for c in another for d in something_else]

I'm sure we've all seen one or two of those. But it doesn't happen
enough to matter. Same with if...elif...else chains. People didn't
immediately run out and replace every single if chain into nested
ternary if expressions, pushing their lines out to beyond the maximum
line width:

    expression if condition else (expression if condition else (expression if condition else (expression if condition else expression)))

Real people don't abuse comprehensions or ternary if enough for us to
regret adding them to the language. I'm sure that they won't abuse this
feature either. The Python community simply doesn't have the culture of
abusing syntax in this way and writing overly dense one-liners, and I
don't think it is reasonable to say this feature will tip the balance.

It is reasonable to say that *some* code will be made worse by this,
because there's always *someone* who will abuse syntax. There are those
who insist on writing list comprehensions for their side-effects:

    # return and throw away a list of Nones
    [print(item) for item in bunch_of_stuff]

but I don't think this happens enough to make us regret adding
comprehensions to the language.

Python-Dev mailing list