bpo-39320: Fix changes in the evaluation logic of unpacking operations.#18264
bpo-39320: Fix changes in the evaluation logic of unpacking operations.#18264brandtbucher wants to merge 5 commits intopython:mainfrom
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