classification
Title: PEP 572: Assignment Expressions
Type: enhancement Stage: patch review
Components: Interpreter Core Versions: Python 3.8
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: emilyemorehouse Nosy List: emilyemorehouse, eric.smith, gvanrossum, koobs, rhettinger, steven.daprano, tim.peters, veky, willingc, xtreak
Priority: normal Keywords: patch, patch

Created on 2018-11-13 00:52 by emilyemorehouse, last changed 2019-03-30 05:09 by veky.

Pull Requests
URL Status Linked Edit
PR 10497 merged emilyemorehouse, 2018-11-13 01:08
PR 10497 merged emilyemorehouse, 2018-11-13 01:08
PR 11670 merged vstinner, 2019-01-25 00:27
PR 11670 merged vstinner, 2019-01-25 00:27
PR 11670 merged vstinner, 2019-01-25 00:27
Messages (22)
msg329781 - (view) Author: Emily Morehouse (emilyemorehouse) * (Python committer) Date: 2018-11-13 00:52
This issue will serve to track development and PRs for the implementation of PEP 572: Assignment Expressions.
msg334325 - (view) Author: Emily Morehouse (emilyemorehouse) * (Python committer) Date: 2019-01-24 23:50
New changeset 8f59ee01be3d83d5513a9a3f654a237d77d80d9a by Emily Morehouse in branch 'master':
bpo-35224: PEP 572 Implementation (#10497)
https://github.com/python/cpython/commit/8f59ee01be3d83d5513a9a3f654a237d77d80d9a
msg334328 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2019-01-25 00:01
This is huge!

I do recall there are some minor edge cases where the implementation currently doesn't match the PEP. Could you summarize those here, and add your recommendation (e.g. change the PEP, fix the code, wait and see) with motivation?
msg334330 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2019-01-25 00:29
The change broke most buildbots: congrats Emily, each core dev has to do their as part of their training ;-) Don't worry, it's fine.

I wrote PR #11670 which should fix test_tools.
msg334331 - (view) Author: Emily Morehouse (emilyemorehouse) * (Python committer) Date: 2019-01-25 00:36
@vstinner Is there something I could/should have checked other than the CI displayed in GitHub before merging? Let me know if I can help.



Here's a brief summary of the differences between the PEP spec and implementation:

From the "Scope of the target" section of the PEP, there are two cases that should raise a TargetScopeError: when an assignment expression is used in a comprehension inside a class body or for special cases in comprehensions.

Invalid examples for the latter include:

    [i := i+1 for i in range(5)]
    [[(j := j) for i in range(5)] for j in range(5)]
    [i := 0 for i, j in stuff]
    [i+1 for i in i := stuff]

However, the following work in the implementation,though the PEP states they should be invalid:

    >>> [i := i+1 for i in range(5)]
    [1, 2, 3, 4, 5]
    >>> i
    5

    >>> [i := 0 for i, j in [(1, 2)]]
    [0]

The following does not work in the implementation (as desired), but does not throw a TargetScopeError as defined in the PEP:

    >>> [i+1 for i in i := range(5)]
    File "<stdin>", line 1
        [i+1 for i in i := range(5)]
                        ^
    SyntaxError: invalid syntax


IMO, I was leaning towards advocating for changing the PEP to match the implementation. I think the error messages are clear and expected, and restricting what already works would require significant special cases. I'm open to discussion though.

There's also documentation that should certainly be added (and I believe a spot where assignment expressions are explicitly mentioned as not being included in the language, which is no longer the case)
msg334332 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2019-01-25 00:39
> @vstinner Is there something I could/should have checked other than the CI displayed in GitHub before merging? Let me know if I can help.

It wasn't your fault. Our pre-commit checks on pull requests is incomplete on purpose: it has to be fast. It's fine to break buildbots sometimes. It's a tradeoff.

If you want to help, please merge https://github.com/python/cpython/pull/11670 as soon as the CI test pass since I'm going to bed :-)

You are the victim of a very very specific annoying test, test_unparse with its annoying "randomly pick 10 files from the stdlib" feature...
msg334334 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2019-01-25 00:50
New changeset 1396d8fab4d0ae830d45f4937322bbb43ce0c30e by Victor Stinner in branch 'master':
bpo-35224: Add support for NamedExpr to unparse.py (GH-11670)
https://github.com/python/cpython/commit/1396d8fab4d0ae830d45f4937322bbb43ce0c30e
msg334341 - (view) Author: Karthikeyan Singaravelan (xtreak) * (Python triager) Date: 2019-01-25 06:18
I don't know if this is the correct issue for questions/clarifications but it seems parens are mandatory while using named expressions in while statement which makes some of the examples invalid like https://www.python.org/dev/peps/pep-0572/#sysconfig-py . From my limited knowledge while statement Grammar was not modified at https://github.com/python/cpython/pull/10497/files#diff-cb0b9d6312c0d67f6d4aa1966766ceddR73 and no tests for while statement which made me assume it's intentional. I haven't followed the full discussion about PEP 572 so feel free to correct me if it's a conscious decision and in that case the PEP 572 can be updated.

# python info

➜  cpython git:(master) ./python.exe
Python 3.8.0a0 (heads/bpo35113-dirty:49329a217e, Jan 25 2019, 09:57:53)
[Clang 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>

# Example as in PEP 572 to create a simple file that reads itself and prints lines that matches "foo"

➜  cpython git:(master) cat /tmp/foo.py
import re

with open("/tmp/foo.py") as f:
    while line := f.readline():
        if match := re.search(r"foo", line):
            print(match.string.strip("\n"))
➜  cpython git:(master) ./python.exe /tmp/foo.py
  File "/tmp/foo.py", line 4
    while line := f.readline():
               ^
SyntaxError: invalid syntax

# Wrapping named expression with parens for while makes this valid

➜  cpython git:(master) cat /tmp/foo.py
import re

with open("/tmp/foo.py") as f:
    while (line := f.readline()):
        if match := re.search(r"foo", line):
            print(match.string.strip("\n"))
➜  cpython git:(master) ./python.exe /tmp/foo.py
with open("/tmp/foo.py") as f:
        if match := re.search(r"foo", line):


As a user I think parens shouldn't be mandatory in while statement since if statement works fine. Parens can cause while statement to be superfluous in some cases and an extra case to remember while teaching.
msg334358 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2019-01-25 12:36
Note: I checked and 3.x buildbots are back to green (ignoring the ones which already failed previously). Good.
msg334839 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2019-02-04 20:08
FYI, we need a prominent Whatsnew entry for this.
msg334840 - (view) Author: Emily Morehouse (emilyemorehouse) * (Python committer) Date: 2019-02-04 20:42
@rhettinger absolutely, I'm going to include that in my documentation PR which is currently in progress. :)
msg335437 - (view) Author: Miro Hrončok (hroncok) * Date: 2019-02-13 13:24
PEP 572 is nowhere to be found in https://docs.python.org/3.8/whatsnew/3.8.html

Should I open a separate issue for that?
msg335438 - (view) Author: Miro Hrončok (hroncok) * Date: 2019-02-13 13:32
(I've somehow missed the previous comments about the same, sorry about that.)
msg335452 - (view) Author: Emily Morehouse (emilyemorehouse) * (Python committer) Date: 2019-02-13 15:29
I have a work-in-progress (WIP) documentation branch I've been working on that I'll push up this week to address the following:

- Add summary to What's New in Doc/whatsnew/3.8.rst
- Add to list of delimiters in Doc/reference/lexical_analysis.rst
- Add usage documentation in Doc/reference/expressions.rst
- Update FAQ in Doc/faq/design.rst (https://bugs.python.org/issue35666)

If anyone has another area they think the documentation should be updated, please let me know!
msg335458 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2019-02-13 15:48
> If anyone has another area they think the documentation should be updated, please let me know!

If we forget something, it's not an issue: it can be added later!
msg339098 - (view) Author: Vedran Čačić (veky) * Date: 2019-03-29 07:30
Now I had the opportunity to play with the walrus (as it is affectionately called in some parts of the community), I have to ask you for a reconsideration of one part of PEP 572.

    Unparenthesized assignment expressions are prohibited at the top level of an expression statement. This rule is included to simplify the choice for the user between an assignment statement and an assignment expression -- there is no syntactic position where both are valid.

Correct, but the motivation rests on a wrong premise, that the effect is the same. In one very important case, it is not: in REPL (including things like Jupyter notebooks), the values of expressions are printed (if not None). I really hoped that the walrus would enable me to both assign and see the result at once. (Now it does, but I have to parenthesize, and that just looks ugly.)

More than half of the cells in my Jupyter notebooks are of the form

    name = some.complicated.method(of={some: arguments})
    name

    another_name = another.method(name, [additional, arguments])
    another_name

And while I understand why I had to write them like this before PEP 572, now I really think they would look much tidier as

    name := some.complicated.method(of={some: arguments})

    another_name := another.method(name, [additional, arguments])

Please reconsider.
msg339112 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2019-03-29 13:42
@veky -- please take this up on python-ideas.
msg339121 - (view) Author: Vedran Čačić (veky) * Date: 2019-03-29 15:19
Sorry, I don't have the energy for endless discussions without any result that almost always happen there. If you - of all people - don't see an obvious benefit of this (not even a feature - just a removal of a quite pointless limitation), then I'm probably wrong and there's no point in that.
msg339131 - (view) Author: Carol Willing (willingc) * (Python committer) Date: 2019-03-29 18:40
@veky As a Jupyter notebook maintainer, I can see your point and I suspect some would like it. I'm not sure how big a benefit it would be for folks based on current notebook usage and practices. I just don't know. It's worth a discussion, but it should take place on python-ideas first to see how much traction your proposal would have.

Let's keep this issue focused on the implementation of 572 as accepted.
msg339159 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2019-03-29 22:45
You are one person, who has used this feature for what, a month elapsed 
time? 300 person-hours actual experience with it? Allowing top-level 
unparenthisized walrus expressions will affect hundreds of thousands of 
people, for collectively millions of hours over a decade or more of 
elapsed time. What's the rush about lifting this restriction?

If the restriction turns out to be "pointless", then we can remove it 
later, and no harm done. You say this is ugly in the notebooks:

    (variable := expression)

but it is surely still an improvement over the status quo:

    variable = expression; variable

But if we remove it now, and it turns out that it wasn't as pointless as 
you thought, then we're stuck with a design mistake that will be very 
hard to fix without breaking people's code.

I'm glad you've found an excellent use-case for unbracketed assignment 
expressions, and I don't oppose your suggested change, I'm just 
advocating caution.

Besides, Jypiter already allows interactive code that would be a syntax 
error outside of their environment. They can probably relax that 
restriction within Jypiter, while still leaving the language alone.
msg339160 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2019-03-29 23:04
The bug tracker is not the appropriate place to discuss a PEP. This issue is about the implementation of the PEP.
msg339172 - (view) Author: Vedran Čačić (veky) * Date: 2019-03-30 05:09
Carol, if you're willing to go into the lion's den that is Python-ideas with this, you have my eternal gratitude. :-)

Steven, sorry, there really is no rush. I really don't think I ever said there is. However, I think it would be much easier to change the behavior while the thing is in alpha. Isn't that the purpose of alpha? 

(If I'm wrong here, please disregard. I would be fine to see this happening few years from now. I believe in "Python in the limit", not actual versions, but too many times I have been said "what you ask makes sense in the ideal world, but that ship has sailed long ago".)

Yes, of course (name := expression) is an improvement over what we have now, and I'm grateful for that. It's just that when I explain it to my students (" = is just assignment, := is for assignment and displaying"), I have no good reason to tell them why they must put the parentheses---except "Python is too worried you will make a mistake", and that just doesn't seem like something Python usually does. (That's something Java would do to people.:)

Yes, Jupyter sometimes does allow things that would otherwise be SyntaxErrors (though much less than they used to, since Python gave them a lot of headache by introducing decorators---if you remember that story;), and going to Jupyter was the next thing on my mind after I'm rejected here. I just thought it would be much easier to just allow this "at the source", so Jupyter people don't have to think "what if they finally allow toplevel walruses, but with different semantics (e.g., printing result even if it is None)?".

Carol and Victor, I'm sorry I have usurped a bugtracker issue for this discussion. First, I really thought this is about implementation of assignment expressions, and this is the best place to put it. Second, I didn't expect a discussion---I thought it would be either "that makes no sense, go away" or "yeah, good idea, we'll do it". For the next such issue (there will probably be one:), do you suggest that the more appropriate thing would be to open a new issue?

(Let me just reiterate that I'm not going to python-ideas. You probably can't understand how stressful that place is, but believe me, it is. I'm not the only one that thinks so. If that's the only sanctioned method to improve Python, even when it is about details, then I'll just withdraw from the game.)
History
Date User Action Args
2019-03-30 05:09:47vekysetmessages: + msg339172
2019-03-29 23:36:08vstinnersetkeywords: patch, patch
nosy: - vstinner
2019-03-29 23:04:30vstinnersetkeywords: patch, patch

messages: + msg339160
2019-03-29 22:45:15steven.dapranosetmessages: + msg339159
2019-03-29 18:40:49willingcsetkeywords: patch, patch
nosy: + willingc
messages: + msg339131

2019-03-29 17:18:14hroncoksetnosy: - hroncok
2019-03-29 15:19:00vekysetmessages: + msg339121
2019-03-29 13:42:54gvanrossumsetkeywords: patch, patch

messages: + msg339112
2019-03-29 07:30:09vekysetnosy: + veky
messages: + msg339098
2019-02-20 02:13:24koobssetkeywords: patch, patch
nosy: + koobs
2019-02-13 15:48:34vstinnersetkeywords: patch, patch

messages: + msg335458
2019-02-13 15:29:17emilyemorehousesetkeywords: patch, patch

messages: + msg335452
2019-02-13 13:32:41hroncoksetmessages: + msg335438
2019-02-13 13:24:31hroncoksetnosy: + hroncok
messages: + msg335437
2019-02-04 20:42:34emilyemorehousesetkeywords: patch, patch

messages: + msg334840
2019-02-04 20:08:01rhettingersetkeywords: patch, patch
nosy: + rhettinger
messages: + msg334839

2019-01-25 12:36:00vstinnersetkeywords: patch, patch

messages: + msg334358
2019-01-25 06:18:34xtreaksetkeywords: patch, patch

messages: + msg334341
2019-01-25 00:50:09vstinnersetmessages: + msg334334
2019-01-25 00:39:46vstinnersetkeywords: patch, patch

messages: + msg334332
2019-01-25 00:36:34emilyemorehousesetkeywords: patch, patch

messages: + msg334331
2019-01-25 00:29:27vstinnersetkeywords: patch, patch
nosy: + vstinner
messages: + msg334330

2019-01-25 00:27:54vstinnersetpull_requests: + pull_request11483
2019-01-25 00:27:47vstinnersetpull_requests: + pull_request11482
2019-01-25 00:27:38vstinnersetpull_requests: + pull_request11481
2019-01-25 00:01:04gvanrossumsetkeywords: patch, patch

messages: + msg334328
2019-01-24 23:50:00emilyemorehousesetmessages: + msg334325
2019-01-05 16:29:59serhiy.storchakalinkissue35666 dependencies
2018-11-13 10:15:10steven.dapranosetkeywords: patch, patch
nosy: + steven.daprano
2018-11-13 05:43:59xtreaksetkeywords: patch, patch
nosy: + xtreak
2018-11-13 01:32:02eric.smithsetkeywords: patch, patch
nosy: + eric.smith
2018-11-13 01:08:12emilyemorehousesetkeywords: + patch
stage: patch review
pull_requests: + pull_request9759
2018-11-13 01:08:10emilyemorehousesetkeywords: + patch
stage: (no value)
pull_requests: + pull_request9758
2018-11-13 00:52:17emilyemorehousecreate