Sigue las reglas de la sección Declaraciones de asignación de la documentación,
assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)
Si target list
es una lista de destinos separados por comas: el objeto debe ser iterable con el mismo número de elementos que hay en la lista de destinos y los elementos se asignan, de izquierda a derecha, a los destinos correspondientes.
El objeto debe ser una secuencia con el mismo número de elementos que los objetivos que hay en la lista de objetivos, y los elementos se asignan, de izquierda a derecha, a los objetivos correspondientes.
Entonces, cuando dices
[] = ""
""
es iterable (cualquier cadena de Python válida es iterable) y se está desempaquetando sobre los elementos de la lista.
Por ejemplo,
>>> [a, b, c] = "123"
>>> a, b, c
('1', '2', '3')
Dado que tiene una cadena vacía y una lista vacía, no hay nada que descomprimir. Entonces, no hay error.
Pero prueba esto
>>> [] = "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
En el [] = "1"
caso, está intentando descomprimir la cadena "1"
sobre una lista vacía de variables. Entonces se queja con "demasiados valores para descomprimir (esperado 0)".
De la misma manera, en [a] = ""
caso de que tenga una cadena vacía, no hay nada que descomprimir realmente, pero lo está descomprimiendo en una variable, lo cual, nuevamente, no es posible. Es por eso que se queja de que "se necesitan más de 0 valores para descomprimir".
Aparte de eso, como habrás notado,
>>> [] = ()
tampoco arroja ningún error, porque ()
es una tupla vacía.
>>> ()
()
>>> type(())
<class 'tuple'>
y cuando se desempaqueta sobre una lista vacía, no hay nada que descomprimir. Así que no hay error.
Pero, cuando lo haces
>>> "" = []
File "<input>", line 1
SyntaxError: can't assign to literal
>>> "" = ()
File "<input>", line 1
SyntaxError: can't assign to literal
como dice el mensaje de error, está intentando asignar a una cadena literal. Lo cual no es posible. Es por eso que está recibiendo los errores. Es como decir
>>> 1 = "one"
File "<input>", line 1
SyntaxError: can't assign to literal
Internos
Internamente, esta operación de asignación se traducirá al UNPACK_SEQUENCE
código de operación ,
>>> dis(compile('[] = ""', "string", "exec"))
1 0 LOAD_CONST 0 ('')
3 UNPACK_SEQUENCE 0
6 LOAD_CONST 1 (None)
Aquí, dado que la cadena está vacía, UNPACK_SEQUENCE
descomprime los 0
tiempos. Pero cuando tienes algo como esto
>>> 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 secuencia 123
se desempaqueta en la pila, de derecha a izquierda. Entonces, la parte superior de la pila sería 1
y la siguiente sería 2
y la última sería 3
. Luego asigna desde la parte superior de la pila a las variables de la expresión del lado izquierdo una por una.
Por cierto, en Python, así es como puede hacer múltiples asignaciones en la misma expresión. Por ejemplo,
a, b, c, d, e, f = u, v, w, x, y, z
esto funciona porque los valores de la derecha se utilizan para construir una tupla y luego se descomprime sobre los valores de la izquierda.
>>> 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
pero la técnica de intercambio clásica a, b = b, a
usa la rotación de elementos en la parte superior de la pila. Si usted tiene sólo dos o tres elementos, entonces se trata con especial ROT_TWO
e ROT_THREE
instrucciones en lugar de construir la tupla y desembalaje.
>>> 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('[] = ""')
sin llamarcompile()
.