[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Python-Dev] Call for prudence about PEP-572

On Sun, Jul 8, 2018 at 7:24 PM Chris Angelico <rosuav at gmail.com> wrote:
> On Mon, Jul 9, 2018 at 3:14 AM, Giampaolo Rodola' <g.rodola at gmail.com> wrote:
> >
> >
> > On Sun, Jul 8, 2018 at 6:45 PM Steve Holden <steve at holdenweb.com> wrote:
> >>
> >> On Sun, Jul 8, 2018 at 10:41 AM, Giampaolo Rodola' <g.rodola at gmail.com>
> >> wrote:
> >>>
> >>> [...]
> >>> I find that (space between the parentheses of a function call statement)
> >>> too unnatural as a place where to put an assignment. It is not even
> >>> "guarded" by a keyword like "if" or  "while" which can help as indicators
> >>> that an assignment may occur. Also, I think it's way too easy to confuse it
> >>> with a keyword argument:
> >>>
> >>>     >>> foo(x = 1)  # keyword arg
> >>>     >>> foo(x := 1)  # assignment + value passing
> >>> [...]
> >>
> >>
> >> But the PEP 8 spellings are
> >>
> >>     foo(x=1)
> >>
> >> and
> >>
> >>    f(x := 1).
> >>
> >> The extra spacing makes it obvious that this isn't a regular named
> >> argument.
> >
> >
> > What if the author of the code I'm reading didn't respect PEP-8? I don't
> > think it's fair to invoke PEP-8 as a counter-measure to obviate a syntax
> > which can clearly be mistaken with something else simply by omitting 2
> > spaces. Not to mention that I don't see why anyone would want to declare a
> > variable in there in the first place.
> >
> It's not about why someone would want to assign inside a function
> call. It's about why it should be forbidden. Perhaps nobody has a good
> reason to use THlS_OBJECT as a variable name, and it's potentially
> very confusing; but should the grammar of Python forbid it? No.
> Because there is no value in forbidding it.

I'll try to give some reasons on why I think it should be forbidden.
In order of importance, more or less:

1) Because of readability and because it's ambiguous. foo(x := 1) and
foo(x = 1) are visually too similar and mean 2 completely different
things. And no, I don't think PEP-8 compliant variants are much
    >>> foo(x := 1)
    >>> foo(x=1)
Good luck explaining the difference between the two to a beginner
including the introduction of PEP-8 concepts and why spaces are so
important in this case. The fact that spaces are more important here
than in other places alone makes me think this is unlikely a good

2) It's an incentive to write more compact code at the expense of
readability. I see := being used in "if" and "while" statements as
different in this regard. They imply an indented code block will
follow and the variables being set in the "if/while" statement will be
used right after that, supposedly in the very next line and *in that
block only*. This is what
https://github.com/python/cpython/pull/8122/files is all about,
really. There is no block in this case hence AFAICT this syntax is
only meant for writing one-liners.

3) := assignments in {if, while, yield, assert} statements are more
clearly noticeable because delimited by such keywords whereas a
function call can appear anywhere in the code. The only way to easily
track assignments such as foo(x := 1) is via linting.

4) IMO this is the main bit of PEP-572 which can be subject to serious
abuse. The value of "explicit is better than implicit" is an advanced
concept. We can't expect it can be grasped by everybody. Many folks
may be tempted to write one-liners at the top of a function and even
feel good about it because a bunch of lines were saved. Potentially *a
lot* of lines can be saved so it even more advanced users may be
tempted to use it. After all the language allows it +  "it's brand new
syntax so it must be good".

5) It has no keyword argument correspondence. If foo(x := 1) is
allowed then why this one is not?
    >>> foo(x=(x := 1))
(I don't think it should BTW: it's not pretty)

6) Differently from := usage in {if, while, comprehensions} no valid
use case which would justify its usage has been provided so far.
AFAICT the only valid use case is for writing one-liners.

7) Defining something in there just feels wrong (to me at least)

8) I'm pretty sure any linter would emit a warning by default so why
bother adding support for a brand new syntax which we already know it
would be discouraged anyway?

9) It goes against half of the Python Zen.

Giampaolo - http://grodola.blogspot.com