On Thu, Apr 26, 2018 at 08:48:12AM -0700, Łukasz Langa wrote:
On Apr 25, 2018, at 11:10 PM, Steven D'Aprano email@example.com 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 doing.
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 this:
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.