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

[Python-Dev] PEP 572: Assignment Expressions

On Tue, May 1, 2018 at 2:53 AM, Yury Selivanov <yselivanov.ml at gmail.com> wrote:
> On Mon, Apr 30, 2018 at 11:32 AM Chris Angelico <rosuav at gmail.com> wrote:
>> On Tue, May 1, 2018 at 12:30 AM, Mark Shannon <mark at hotpy.org> wrote:
>> > List comprehensions
>> > -------------------
>> > The PEP uses the term "simplifying" when it really means "shortening".
>> > One example is
>> > stuff = [[y := f(x), x/y] for x in range(5)]
>> > as a simplification of
>> > stuff = [(lambda y: [y,x/y])(f(x)) for x in range(5)]
>> Now try to craft the equivalent that captures the condition in an if:
>> results = [(x, y, x/y) for x in input_data if (y := f(x)) > 0]
> Easy:
>    results = []
>    for x in input_data:
>       y = f(x)
>       if y > 0:
>         results.append((x, y, x/y))
> Longer, but way more readable and debuggable if you're into that.  This has
> worked for us many years and only a handful of people complained about
> this.
> OTOH, I see plenty of people complaining that nested list comprehensions
> are hard to read.  In my own code reviews I ask people to avoid using
> complex comprehensions all the time.
>> Do that one with a lambda function.
> Why would I?  Is using lambda functions mandatory?

The claim was that assignment expressions were nothing more than a
shorthand for lambda functions. You can't rewrite my example with a
lambda function, ergo assignment expressions are not a shorthand for
lambda functions.

Do you agree?

>> > IMO, the "simplest" form of the above is the named helper function.
>> >
>> > def meaningful_name(x):
>> >     t = f(x)
>> >     return t, x/t
>> >
>> > [meaningful_name(i) for i in range(5)]
>> >
>> > Is longer, but much simpler to understand.
>> Okay, but what if there is no meaningful name? It's easy to say "pick
>> a meaningful name". It's much harder to come up with an actual name
>> that is sufficiently meaningful that a reader need not go look at the
>> definition of the function.
> That's a weird argument, Chris :-)
> If `f(x)` has no meaningful name, then *what* is the result of the
> comprehension?  Perhaps some meaningless data? ;)

f(x) might have side effects. Can you give a meaningful name to the
trivial helper function? Not every trivial helper can actually have a
name that saves people from having to read the body of the function.

>> > I am also concerned that the ability to put assignments anywhere
>> > allows weirdnesses like these:
>> >
>> > try:
>> >     ...
>> > except (x := Exception) as x:
>> >     ...
>> >
>> > with (x: = open(...)) as x:
>> >     ...
>> We've been over this argument plenty, and I'm not going to rehash it.
> Hand-waving the question the way you do simply alienates more core devs to
> the PEP.  And PEP 572 hand-waves a lot of questions and concerns.  Asking
> people to dig for answers in 700+ emails about the PEP is a bit too much,
> don't you agree?
> I think it's PEP's author responsibility to address questions right in
> their PEP.

If I answer every question, I make that number into 800+, then 900+,
then 1000+. If I don't, I'm alienating everyone by being dismissive.
If every question is answered in the PEP, the document itself becomes
so long that nobody reads it. Damned if I do, damned if I don't. Got
any alternative suggestions?

>> > def do_things(fire_missiles=False, plant_flowers=False): ...
>> > do_things(plant_flowers:=True) # whoops!
>> If you want your API to be keyword-only, make it keyword-only. If you
> Another hand-waving.  Should we deprecate passing arguments by name if
> their corresponding parameters are not keyword-only?
> Mark shows another potential confusion between '=' and ':=' that people
> will have, and it's an interesting one.

A very rare one compared to the confusions that we already have with
'=' and '=='. And this is another argument that we've been over,
multiple times.

>> want a linter that recognizes unused variables, get a linter that
>> recognizes unused variables.
> Many want Python to be readable and writeable without linters.

And it will be. But there are going to be certain types of bug that
you won't catch as quickly. You can't use language syntax to catch
every bug. That's provably impossible.

>> Neither of these is the fault of the
>> proposed syntax; you could just as easily write this:
>> do_things(plant_flowers==True)
>> but we don't see myriad reports of people typing too many characters
>> and blaming the language.
> Strange. I see people who struggle to format their code properly or use the
> language properly *every day* ;)

And do they blame the language for having a comparison operator that
is so easy to type? Or do they fix their bugs and move on? Again,
language syntax is not the solution to bugs.