Il suit les règles de la section Déclarations d' affectation de la documentation,
assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)
Si le target list
est une liste de cibles séparées par des virgules: L'objet doit être un itérable avec le même nombre d'éléments qu'il y a de cibles dans la liste de cibles, et les éléments sont affectés, de gauche à droite, aux cibles correspondantes.
L'objet doit être une séquence avec le même nombre d'éléments qu'il y a de cibles dans la liste cible, et les éléments sont affectés, de gauche à droite, aux cibles correspondantes.
Alors, quand tu dis
[] = ""
""
est un itérable (toute chaîne python valide est un itérable) et il est décompressé sur les éléments de la liste.
Par exemple,
>>> [a, b, c] = "123"
>>> a, b, c
('1', '2', '3')
Puisque vous avez une chaîne vide et une liste vide, il n'y a rien à décompresser. Donc, pas d'erreur.
Mais essayez ceci
>>> [] = "1"
Traceback (most recent call last):
File "<input>", line 1, in <module>
ValueError: too many values to unpack (expected 0)
>>> [a] = ""
Traceback (most recent call last):
File "<input>", line 1, in <module>
ValueError: need more than 0 values to unpack
Dans ce [] = "1"
cas, vous essayez de décompresser la chaîne "1"
sur une liste vide de variables. Donc, il se plaint de "trop de valeurs à décompresser (0 attendu)".
De la même manière, au [a] = ""
cas où vous auriez une chaîne vide, donc rien à décompresser vraiment, mais vous la décompressez sur une variable, ce qui, encore une fois, n'est pas possible. C'est pourquoi il se plaint "d'avoir besoin de plus de 0 valeurs pour décompresser".
En dehors de cela, comme vous l'avez remarqué,
>>> [] = ()
ne jette également aucune erreur, car ()
est un tuple vide.
>>> ()
()
>>> type(())
<class 'tuple'>
et quand il est décompressé sur une liste vide, il n'y a rien à décompresser. Donc pas d'erreur.
Mais, quand tu fais
>>> "" = []
File "<input>", line 1
SyntaxError: can't assign to literal
>>> "" = ()
File "<input>", line 1
SyntaxError: can't assign to literal
comme le message d'erreur l'indique, vous essayez d'affecter à une chaîne littérale. Ce qui n'est pas possible. C'est pourquoi vous obtenez les erreurs. C'est comme dire
>>> 1 = "one"
File "<input>", line 1
SyntaxError: can't assign to literal
Internes
En interne, cette opération d'affectation sera traduite en UNPACK_SEQUENCE
code opération,
>>> dis(compile('[] = ""', "string", "exec"))
1 0 LOAD_CONST 0 ('')
3 UNPACK_SEQUENCE 0
6 LOAD_CONST 1 (None)
Ici, puisque la chaîne est vide, UNPACK_SEQUENCE
décompresse les 0
temps. Mais quand tu as quelque chose comme ça
>>> dis(compile('[a, b, c] = "123"', "string", "exec"))
1 0 LOAD_CONST 0 ('123')
3 UNPACK_SEQUENCE 3
6 STORE_NAME 0 (a)
9 STORE_NAME 1 (b)
12 STORE_NAME 2 (c)
15 LOAD_CONST 1 (None)
18 RETURN_VALUE
la séquence 123
est décompressée dans la pile, de droite à gauche. Ainsi, le haut de la pile serait 1
et le suivant serait 2
et le dernier serait 3
. Ensuite, il affecte à partir du haut de la pile les variables de l'expression de gauche une par une.
BTW, en Python, voici comment vous pouvez faire plusieurs affectations dans la même expression. Par exemple,
a, b, c, d, e, f = u, v, w, x, y, z
cela fonctionne parce que les valeurs de droite sont utilisées pour construire un tuple, puis il sera décompressé sur les valeurs de gauche.
>>> dis(compile('a, b, c, d, e, f = u, v, w, x, y, z', "string", "exec"))
1 0 LOAD_NAME 0 (u)
3 LOAD_NAME 1 (v)
6 LOAD_NAME 2 (w)
9 LOAD_NAME 3 (x)
12 LOAD_NAME 4 (y)
15 LOAD_NAME 5 (z)
18 BUILD_TUPLE 6
21 UNPACK_SEQUENCE 6
24 STORE_NAME 6 (a)
27 STORE_NAME 7 (b)
30 STORE_NAME 8 (c)
33 STORE_NAME 9 (d)
36 STORE_NAME 10 (e)
39 STORE_NAME 11 (f)
42 LOAD_CONST 0 (None)
45 RETURN_VALUE
mais la technique d'échange classique a, b = b, a
utilise la rotation des éléments en haut de la pile. Si vous n'avez que deux ou trois éléments, ils sont traités avec des instructions spéciales ROT_TWO
et ROT_THREE
au lieu de construire le tuple et de le décompresser.
>>> dis(compile('a, b = b, a', "string", "exec"))
1 0 LOAD_NAME 0 (b)
3 LOAD_NAME 1 (a)
6 ROT_TWO
7 STORE_NAME 1 (a)
10 STORE_NAME 0 (b)
13 LOAD_CONST 0 (None)
16 RETURN_VALUE
dis('[] = ""')
sans appelercompile()
.