Es folgt den Regeln des Abschnitts " Zuweisungsanweisungen" aus der Dokumentation.
assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)
Wenn target list
es sich um eine durch Kommas getrennte Liste von Zielen handelt: Das Objekt muss iterierbar mit der gleichen Anzahl von Elementen sein, wie Ziele in der Zielliste vorhanden sind, und die Elemente werden von links nach rechts den entsprechenden Zielen zugewiesen.
Das Objekt muss eine Sequenz mit der gleichen Anzahl von Elementen sein, wie es Ziele in der Zielliste gibt, und die Elemente müssen von links nach rechts den entsprechenden Zielen zugewiesen werden.
Also, wenn du sagst
[] = ""
""
ist eine iterable (jede gültige Python-Zeichenfolge ist eine iterable) und wird über die Elemente der Liste entpackt.
Beispielsweise,
>>> [a, b, c] = "123"
>>> a, b, c
('1', '2', '3')
Da Sie eine leere Zeichenfolge und eine leere Liste haben, müssen Sie nichts entpacken. Also kein Fehler.
Aber versuchen Sie es
>>> [] = "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
In diesem [] = "1"
Fall versuchen Sie, die Zeichenfolge "1"
über eine leere Liste von Variablen zu entpacken . Es beschwert sich also mit "zu vielen Werten zum Entpacken (erwartete 0)".
Genauso wie für den [a] = ""
Fall, dass Sie eine leere Zeichenfolge haben, also nichts wirklich zu entpacken, aber Sie entpacken sie über eine Variable, was wiederum nicht möglich ist. Aus diesem Grund wird beanstandet, dass zum Entpacken mehr als 0 Werte erforderlich sind.
Abgesehen davon, wie Sie bemerkt haben,
>>> [] = ()
wirft auch keinen Fehler, da ()
es sich um ein leeres Tupel handelt.
>>> ()
()
>>> type(())
<class 'tuple'>
und wenn es über eine leere Liste entpackt wird, gibt es nichts zu entpacken. Also kein Fehler.
Aber wenn du es tust
>>> "" = []
File "<input>", line 1
SyntaxError: can't assign to literal
>>> "" = ()
File "<input>", line 1
SyntaxError: can't assign to literal
Wie in der Fehlermeldung angegeben, versuchen Sie, einem Zeichenfolgenliteral zuzuweisen. Welches ist nicht möglich. Deshalb erhalten Sie die Fehler. Es ist wie zu sagen
>>> 1 = "one"
File "<input>", line 1
SyntaxError: can't assign to literal
Interna
Intern wird diese Zuweisungsoperation in UNPACK_SEQUENCE
Op-Code übersetzt.
>>> dis(compile('[] = ""', "string", "exec"))
1 0 LOAD_CONST 0 ('')
3 UNPACK_SEQUENCE 0
6 LOAD_CONST 1 (None)
Hier wird, da die Zeichenfolge leer ist, mal UNPACK_SEQUENCE
entpackt 0
. Aber wenn Sie so etwas haben
>>> 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
Die Sequenz 123
wird von rechts nach links in den Stapel entpackt. Die Spitze des Stapels wäre also 1
und die nächste wäre 2
und die letzte wäre 3
. Anschließend werden die Variablen aus dem Ausdruck auf der linken Seite nacheinander von oben im Stapel zugewiesen.
Übrigens können Sie in Python auf diese Weise mehrere Zuweisungen in demselben Ausdruck vornehmen. Beispielsweise,
a, b, c, d, e, f = u, v, w, x, y, z
Dies funktioniert, weil die Werte auf der rechten Seite zum Erstellen eines Tupels verwendet werden und es dann über die Werte auf der linken Seite entpackt wird.
>>> 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
Bei der klassischen Austauschtechnik werden jedoch a, b = b, a
die Elemente oben im Stapel gedreht. Wenn Sie nur zwei oder drei Elemente haben dann werden sie mit speziellen behandelt ROT_TWO
und ROT_THREE
dafür , das Tupel des Konstruierens und Auspacken.
>>> 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('[] = ""')
ohne Anruf verwendencompile()
.