-
- Notifications
You must be signed in to change notification settings - Fork 33.5k
bpo-39320: Fix changes in the evaluation logic of unpacking operations. #18264
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Codecov Report
@@ Coverage Diff @@ ## master #18264 +/- ## =========================================== + Coverage 82.12% 83.19% +1.07% =========================================== Files 1955 1570 -385 Lines 588723 414212 -174511 Branches 44383 44401 +18 =========================================== - Hits 483465 344607 -138858 + Misses 95630 59966 -35664 - Partials 9628 9639 +11
Continue to review full report at Codecov.
|
| According to https://docs.python.org/3/reference/expressions.html#evaluation-order expressions within a list are evaluated left to right. So, In the expression The same rationale applies to |
| I don't think I agree.
Absolutely, 100%. And in "Unary I think one of the examples in the link you provided is the most clarifying here:
Note that the stars are not part of expressions 1-5, but are a part of the top-level call expression that operates on them all. |
| Why do you say that |
Hm, I've always read that as "starred expression" (an expression that has been "starred"), as in: >>> *expr File "<stdin>", line 1 SyntaxError: can't use starred expression hereRegardless, this is a breaking semantic change, and one that is so subtle it's going to be a huge pain to debug for the few people it hits. Imagine you had the following working code in 3.8: >>> def rotate(stuff): ... i = iter(stuff) ... return [*i, next(i)] ... >>> rotate(2*i for i in range(5)) [2, 4, 6, 8, 0]Sure it's ugly, but it's worked the same since PEP 448 was first landed. Then you upgrade to 3.9, and some time later this happens: >>> rotate(2*i for i in range(5)) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in rotate StopIterationGood luck figuring that one out. |
| I didn't realize this would be such a controversial fix though. If you still disagree @markshannon, I can open a thread on python-dev explaining my reasoning, and you can reply with what you feel the behavior should be, why, why it's worth changing, etc...? |
| In your example, I would be very surprised to find that I think a discussion on Python-dev is the way forward. |
| Why is "expression that has been starred" not an an expression? |
| Sounds good, I'll open a thread there later today. |
| Brandt's pydev thread, 2020/2/6, is "Clarification of unpacking semantics." I read his post and the discussion above and agree that the semantic change is a mistake. My long response is on pydev.
|
7f65751 to 34f9208 Compare
Commits 13bc139 and 8a4cd70 introduced subtle changes in the evaluation logic of unpacking operations. Previously, all elements were evaluated prior to being collected in a container. Now, these operations are interleaved.
For example, the code
[*foo, print("XXX")]used to print "XXX" before callingfoo.__iter__. This is no longer the case.I've included several similar regression tests in this PR. @markshannon, your intuition about keeping the opargs for the
DICT_UPDATE/DICT_MERGEops was good.https://bugs.python.org/issue39320