Je soupçonne qu'il s'agit d'un accident, mais je préfère le nouveau comportement.
Ce nouveau comportement est la conséquence d'une modification de la façon dont le bytecode de l'application *
les arguments fonctionnent. Le changement se situe dans le journal des modifications sous Python 3.9.0 alpha 3 :
bpo-39320 : Remplacer quatre bytecodes complexes pour construire des séquences par trois plus simples.
Les quatre bytecodes suivants ont été supprimés :
- CONSTRUIRE_LISTE_DÉBALLER
- CONSTRUIRE_TUPLE_DÉBALLER
- CONSTRUIRE_SET_DÉBALLER
- CONSTRUIRE_TUPLE_DÉBALLER_AVEC_APPEL
Les trois bytecodes suivants ont été ajoutés :
- LIST_TO_TUPLE
- LIST_EXTEND
- SET_UPDATE
Sous Python 3.7 (je n'ai pas de version 3.8 à tester), le bytecode de la fonction f(*a, a.pop())
ressemble à ça :
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
alors que sur 3.9, ça ressemble à ça :
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
Dans l'ancien bytecode, le code pousse a
y (a.pop(),)
sur la pile, puis dépaquette ces deux itérables en un tuple. Dans le nouveau bytecode, le code pousse une liste sur la pile, puis fait l.extend(a)
y l.append(a.pop())
puis appelle tuple(l)
.
Ce changement a pour effet de décaler le déballage de l'article a
avant le pop
mais cela ne semble pas avoir été délibéré. En regardant bpo-39320 l'intention était de simplifier les instructions du bytecode, pas de changer le comportement, et le fil de discussion de bpo n'a aucune discussion sur les changements de comportement.