News for hackers. Stuff that matters.
Re:PEP 572: Python assignment expressions has been accepted by sametmax on Tuesday July 03, 2018 @05:29AM (#17448716)
I will be happy to be able to do:

    while (bytes := io.get(x)): 
and:

    [bar(x) for z in stuff if (x := foo(z))] 
Every time Python adds an expression counterpart to an existing statement (lambdas, intensions, ternary...) there is a (legit) fear it will be abused.

But experience tells that the slow and gradual pace of the language evolution combined with the readability culture of the community don't lead that way.

While we will see code review breaking materials in the wild, I believe that the syntax will mostly be used sparingly, as other features, when the specific needs arise for it.

After all, it's been, as usual, designed with this in mind: "=" and ":=" are mutually exclusive. You don't use them in the same context.

The grammar makes sure of it most of the time, and for the rare ambiguities like:

    a = b
vs

    (a := b)
The parenthesis will discourage pointless usage.

My bet is that we will see essentially rare but useful and expressive use cases in productions, which is exactly the goal.

Given the month of debates around this, I think it's a fine compromise.

Like many, I would have preferred the use of the "as" keyword instead of a new operator, since it's already used to bind things to names in imports, context managers and try/except.

However, the new syntax has 2 advantages: it reads the same way than the original operator, and it supports type hints out of the box.

Re:PEP 572: Python assignment expressions has been accepted by gshulegaard on Tuesday July 03, 2018 @04:43PM (#17453473)
I agree that I would have preferred "as"...but that said I am struggling to think of a reason this is needed.

    while (bytes := io.get(x)):
Would currently be written:

    bytes = io.get(x)
    while bytes:
And likewise:

    [bar(x) for z in stuff if (x := foo(z))]
is equivalently:

    [bar(foo(z)) for z in stuff if foo(z)]
Perhaps this is just my personal opinion but I don't really think the ":=" (or "as" for that matter) adds much in the way of clarity or functionality. I guess at the end of the day I am neutral about this addition...but if there isn't a clear upside I usually think it's better to have less rather than add more.
Re:PEP 572: Python assignment expressions has been accepted by Dunnorandom on Tuesday July 03, 2018 @04:46PM (#17453490)
The first example would actually be equivalent to something like

    while True:
        bytes = io.get(x)
        if not bytes:
            break
        ...
which I think is objectively less readable.

In the second example, you have an extra call to foo for every element of stuff. If foo(z) is expensive, you'd probably want to write this as

    [bar(x) for x in map(foo, stuff) if x]
instead - which I personally don't mind, but it's arguably not as clear as having the in-line assignment expression.
Re:PEP 572: Python assignment expressions has been accepted by amorousf00p on Tuesday July 03, 2018 @07:56PM (#17454484)
Quibbles and bits. Python is the only language where I write logic and then massage data structures and outputs + design 'cooler' ways to create these for an extra hour -- a week after it is in production.
Re:PEP 572: Python assignment expressions has been accepted by gshulegaard on Tuesday July 03, 2018 @09:28PM (#17454765)
I wasn't really considering the repeated genearation on `io` in the `while` example...so now I see a clear benefit to the syntax. I guess I would say I am now lukewarm about adding this additional operator. It makes at least one logical structure nicer...but I wouldn't have been heartbroken if it wasn't accepted though.
Re:PEP 572: Python assignment expressions has been accepted by roman_g on Wednesday July 04, 2018 @05:13AM (#17456128)
And if foo(z) is consuming a generator somehow (e.g. it's next(g)) then you can't call it twice without side effects.
Re:PEP 572: Python assignment expressions has been accepted by mockingbirdy on Tuesday July 03, 2018 @04:59PM (#17453580)
I think I'll use this exactly to avoid duplication in while loops:

    bytes = next()
    while bytes:
        # do something ...
        bytes = next()

It's possible to use while True and break, but that isn't very elegant.
Re:PEP 572: Python assignment expressions has been accepted by wizpig64 on Tuesday July 03, 2018 @07:10PM (#17454284)
This second example:

    [bar(x) for z in stuff if (x := foo(z))]
is not equivalent to:

    [bar(foo(z)) for z in stuff if foo(z)]
because here, foo(z) will be called twice. If foo is an expensive operation or performs some other magic in the background that you don't want to call a second time, := lets you express this behavior without having to break your expression out into a huge for-if-append code block:

    output = []
    for z in stuff:
        x = foo(z)
        if x:
            output.append(bar(x))
Of course, the above verbose language might end up being a better code in the end, because mashing together a bunch of terse code is often not very readable. But in real life, transforming a comprehension into a loop is just a bunch of work that gets in the way of me trying to complete a task.

When I'm developing out an idea and just want to see if the code works and passes my tests, I would rather have the option to insert behavior swiftly without having to reformat an entire block of code. Then when reviewing my code or deciding whether to make it reusable for something else, I can go back and clean things up.

Re:PEP 572: Python assignment expressions has been accepted by gshulegaard on Tuesday July 03, 2018 @09:24PM (#17454756)
I'm aware `foo(z)` gets called twice, but I wouldn't choose to break it into the `for` loop you mention:

    [bar(x) for x in map(foo, stuff) if x]
I was just trying to be as close to the original as possible.

I do find it odd you call out the calling of `foo` twice as a performance drain but then use the chief example of:

> When I'm developing out an idea and just want to see if the code works and passes my tests, I would rather have the option to insert behavior swiftly without having to reformat an entire block of code.

Tests are not something I (personally) consider to be performance sensitive. But like I said I am sort of neutral on this change. I don't really see a massive benefit to it, so I would personally air on the side of "don't add" but I'm not mad it's being added. It's a "meh" for me.

Re:PEP 572: Python assignment expressions has been accepted by bjd2385 on Tuesday July 03, 2018 @07:41PM (#17454426)
Honestly, after seeing the first list comprehension, I can tell that this feature will probably increase code readability for me, but it's definitely going to take more thought to understand where values are coming from.
Re:PEP 572: Python assignment expressions has been accepted by LyndsySimon on Thursday July 12, 2018 @12:25PM (#17516119)
I think I would probably write

    [bar(foo(z)) for z in stuff if foo(z)]
as

    [bar(y) for y in (z for z in stuff if foo(z))]
or even as

    [bar(y) for y in filter(foo, stuff)]
... although, I get that `map`, `apply`, and `filter` aren't generally considered pythonic.

Overall, I think I agree with you - the new syntax in PEP572 might be handy, but it isn't necessary and I would say that the cognitive overhead of encountering yet another syntax doesn't justify the benefit, much less the technical overhead for the interpreter.

Re:PEP 572: Python assignment expressions has been accepted by eswoo on Thursday July 12, 2018 @08:21PM (#17519674)
It needs to be

    [bar(foo(y)) for y in (z for z in stuff if foo(z))]
(etc.) though, since `bar` takes as input the output of `foo`. This leads to the objectionable duplicate calls to `foo`, hence the new assignment expressions.

I like Dunnorandom's

    [bar(x) for x in map(foo, stuff) if x]
best for a correct result using existing syntax, or

    [bar(x) for y in (foo(x) for x in stuff) if y]
if you don't like `map`.
Re:PEP 572: Python assignment expressions has been accepted by smcl on Tuesday July 03, 2018 @08:38AM (#17449634)
> Every time Python adds an expression counterpart to an existing statement (lambdas, intensions, ternary...)

What do you mean by "intension"? I haven't seen this referred to in python and googling isn't turning out anything useful (also spelling it as "intention").

Re:PEP 572: Python assignment expressions has been accepted by sametmax on Tuesday July 03, 2018 @08:47AM (#17449683)
Sorry, french word for "comprehension". It pops up automatically. I can't edit my post anymore though.

The worst for me is OOP. In french it's POO, which, for obvious reasons, does not inspire confidence in an english reader.

Re:PEP 572: Python assignment expressions has been accepted by makapuf on Tuesday July 03, 2018 @04:15PM (#17453311)
Did you mean intention (french spelling) is a translation for list comprehension ? First time I've seen it used ( https://fr.m.wikipedia.org/wiki/Liste_en_compr%C3%A9hension ) Sorry if I misunderstood.
Re:PEP 572: Python assignment expressions has been accepted by sametmax on Wednesday July 04, 2018 @05:30AM (#17456163)
Not 'intention' (will/wish), but 'intension' (as the opposite of extension: see https://fr.wikipedia.org/wiki/Intension_et_extension).

"comprehension list" in french can be translated to "liste en intension"

Re:PEP 572: Python assignment expressions has been accepted by dorfsmay on Wednesday July 04, 2018 @09:10AM (#17457053)
Interesting, the word exist in English too, but I cannot find anywhere how it is supposed to be pronounced, in either language.
Re:PEP 572: Python assignment expressions has been accepted by misterkeys on Wednesday July 04, 2018 @12:29PM (#17458091)
Unfortunately, at least in English, it's pronounced the same as intention. This causes brief confusion in introductory logic and semantics classes everywhere.
Re:PEP 572: Python assignment expressions has been accepted by makapuf on Thursday July 05, 2018 @05:12PM (#17466890)
TIL, thanks. It seems to be the kind of perfectly adapted idiom (that no one uses or understand).
Re:PEP 572: Python assignment expressions has been accepted by smcl on Tuesday July 03, 2018 @08:49AM (#17449697)
Ahhhhhh - thanks!
Re:PEP 572: Python assignment expressions has been accepted by nuclear_eclipse on Tuesday July 03, 2018 @07:29PM (#17454371)
> and it supports type hints out of the box

From my reading of the PEP, assignment expressions specifically prohibit type annotations.

Re:PEP 572: Python assignment expressions has been accepted by alew1 on Wednesday July 04, 2018 @05:39AM (#17456196)
Question: in the list comprehension example, is `x` defined outside the loop comprehension? Will it overwrite an existing `x`? Or is it like `z` and only visible inside the loop comprehension? The latter would make more sense, I think.
Re:PEP 572: Python assignment expressions has been accepted by repsilat on Tuesday July 03, 2018 @04:40PM (#17453453)
> [bar(x) for z in stuff if (x := foo(z))]

Someone showed me this in a previous thread:

>> [bar(foo_z) for z in stuff for foo_z in [foo(z)] if foo_z]

Not a common idiom, though. Neither snippet is perfectly clear to me, but yours is closer.

Re:PEP 572: Python assignment expressions has been accepted by ehsankia on Wednesday July 04, 2018 @08:37AM (#17456895)
The iterating over map(foo, stuff) version is much cleaner and readable imo