a = [1, 2, 3] print(*a, a.pop(0))
Python 3.8 prints
2 3 1 (does the
pop before unpacking).
Python 3.9 prints
1 2 3 1 (does the
pop after unpacking).
What caused the change? I didn't find it in the changelog.
Edit: Not just in function calls but also for example in a list display:
a = [1, 2, 3] b = [*a, a.pop(0)] print(b)
[2, 3, 1] vs
[1, 2, 3, 1]. And Expression lists says "The expressions are evaluated from left to right" (that's the link to Python 3.8 documentation), so I'd expect the unpacking expression to happen first.
I suspect this may have been an accident, though I prefer the new behavior.
The new behavior is a consequence of a change to how the bytecode for
* arguments works. The change is in the changelog under Python 3.9.0 alpha 3:
bpo-39320: Replace four complex bytecodes for building sequences with three simpler ones.
The following four bytecodes have been removed:
The following three bytecodes have been added:
On Python 3.8, the bytecode for
f(*a, a.pop()) looks like this:
1 0 LOAD_NAME 0 (f) 2 LOAD_NAME 1 (a) 4 LOAD_NAME 1 (a) 6 LOAD_METHOD 2 (pop) 8 CALL_METHOD 0 10 BUILD_TUPLE 1 12 BUILD_TUPLE_UNPACK_WITH_CALL 2 14 CALL_FUNCTION_EX 0 16 RETURN_VALUE
while on 3.9, it looks like this:
1 0 LOAD_NAME 0 (f) 2 BUILD_LIST 0 4 LOAD_NAME 1 (a) 6 LIST_EXTEND 1 8 LOAD_NAME 1 (a) 10 LOAD_METHOD 2 (pop) 12 CALL_METHOD 0 14 LIST_APPEND 1 16 LIST_TO_TUPLE 18 CALL_FUNCTION_EX 0 20 RETURN_VALUE
In the old bytecode, the code pushes
(a.pop(),) onto the stack, then unpacks those two iterables into a tuple. In the new bytecode, the code pushes a list onto the stack, then does
l.append(a.pop()), then calls
This change has the effect of shifting the unpacking of
a to before the
pop call, but this doesn't seem to have been deliberate. Looking at bpo-39320, the intent was to simplify the bytecode instructions, not to change the behavior, and the bpo thread has no discussion of behavior changes.