2012-04-06 4 views
3

Warum ist die nächste Python-Zeile kein Syntaxfehler? Wenn es wirklich nicht so ist, wie kann ich es benutzen und in welcher Situation wird es nützlich sein?Warum ist diese Python-Zeile kein Fehler?

a= range(10)[1:3]=[2,3] 
+0

Python3 gibt einen Fehler seit (glaube ich) Bereich wird durch Xrange ersetzt, die keine Zuweisungen unterstützt –

+0

Es hängt von der Python 3-Version, in 3.2 ist völlig legal. Ich bin mir nicht sicher, an welcher Stelle Slicing 'Range' unterstützt wurde. –

+0

Es wurde nur seit 3.2 unterstützt :-) http://docs.python.org/dev/whatsnew/3.2.html –

Antwort

6

Python unterstützt auf der gleichen Linie mehrere Zuweisungen:

>>> a = b = c = 2 
>>> a 
2 
>>> b 
2 
>>> c 
2 

Da Sie eine erste einer Liste zuweisen (ein veränderliches Objekt in Python) und dann beide Teile dieser Liste (die veränderbar ist) und a auf den Inhalt eines dritten Elements, python ist ok damit. Wenn Sie Ihren mittleren Wert durch etwas ersetzt haben, das nicht änderbar war, würden Sie einen Fehler erhalten.

>>> a = 'foo' = 'bar' 
    File "<input>", line 1 
SyntaxError: can't assign to literal 

>>> a = {}['foo'] = 'bar' 
>>> a 
'bar' 

Interessanterweise eine Zeile wie diese wirft noch einen Fehler, weil Sie die Werte 3 und 4 mit den tatsächlichen Werten 1 und 2.

>>> a = [1, 2] = [3, 4] 
    File "<input>", line 1 
SyntaxError: can't assign to literal 

zuweisen versuchen Während dies nicht:

>>> a = [1, 2][:] = [3, 4] 
>>> a 
[3, 4] 
>>> a = [1, 2][:] = [3, 4] 
>>> a 
[3, 4] 

Der Schlüssel in diesem Fall ist, dass Sie mithilfe der Slice-Notation den Bereich innerhalb der Liste zuweisen, anstatt die Literalwerte in der Liste neu zuzuweisen.

Zusätzlich sind die Linien

>>> a = [[], []] = [{}, {}] 
>>> a 
[{}, {}] 

und

>>> a = [b, c] = 3, 4 
>>> b 
3 
>>> c 
4 

gültig sind, die erste, da die inneren Listen und dicts beide wandelbar sind und iterable, und die zweite, weil Sie 3 für die Zuweisung und 4 zu den Variablen b und c anstelle von Literalen (danke Sven: D).

Edit Um die letzte Frage des Op zu beantworten.

Dies kommt nur auf die endgültige (rechts) Zuweisung von b, a = a, b. Beachten Sie:

>>> a, b = 'a', 'b' 
>>> a, b = b, a = a, b = b, a 
>>> a 
'b' 
>>> b 
'a' 
>>> a, b = b, a = b, a 
>>> a 
'a' 
>>> b 
'b' 

Es ist verwirrend, aber die Art, wie ich dies zu interpretieren ist, dass a und b nicht neu bewertet/zugewiesen neue Werte, bis die Anweisung abgeschlossen ist, so dass die Zuordnung, die die ein am weitesten rechts zählt, ist, . Wenn die letzte Aussage a ist, b = a, b oder b, a = b, ändern sich die Werte von a, a und b nicht. Wenn es a, b = b, a oder b, a = a, b ist, werden die Werte umgeschaltet.

+0

Beachten Sie, dass während 'a = [1, 2] = [3, 4] 'ist nicht gültig Python,' a = [b, c] = [3, 4] 'ist. :) –

+0

Ja, es sieht sehr seltsam aus, da a = [1, 2] [:] = [3, 4] ist "gültig" –

+0

@SvenMarnach Ich habe nur versucht, ein Beispiel zu finden! Ich werde es bearbeiten in. –

2

Diese Zeile ist zwar kein Fehler, aber sie ist nie nützlich. Es macht das gleiche wie

a = [2, 3] 

Darüber hinaus ist es eine neue Liste mit dem Inhalt [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] erstellt und setzt das zweite und dritte Element dieser Liste 2 und 3, und schließlich fällt diese neue Liste wieder, da keine sind Referenzen überhaupt dazu.

Hier ist ein vollständiger Code, der das gleiche tut. Die Reihenfolge der Aussagen gewählt wird, um die Ausführungsreihenfolge von Ihrer ursprünglichen Anweisung zum Spiel:

a = [2, 3] 
b = range(10) 
b[1:3] = a 
del b 
2

Nun lassen Sie uns ein wenig brechen, beginnend mit der Bereichsfunktion. Die Range-Funktion erstellt eine Liste von ganzen Zahlen von 0 - 9. Damit Sie am Ende mit diesem

[0,1,2,3,4,5,6,7,8,9] 

Als nächstes wird eine Scheibe Notation in die Liste der ganzen Zahlen angewendet wird. Wenn Sie vor dem Doppelpunkt eine Zahl angeben, die den Python als Startindex verwenden soll, und weil die Listen nicht indexiert sind, erhalten Sie das zweite Element in der Liste, das den Wert 1 hat. Außerdem haben Sie einen zweiten Wert angegeben ein zusätzlicher Index, so dass Sie Werte bis zu diesem Index erhalten. Aber das führt nur zum dritten Element, das direkt auf den Startindex folgt. Jetzt haben Sie das:

[1,2] 

Traditionell in Programmiersprachen werden Werte von rechts nach links zugewiesen. Es scheint, dass die Bereichs/Slice-Operationen vor der Zuweisung abgeschlossen sind, da die Liste ganz rechts den durch die Bereichsoperation erzeugten Wert ersetzt. Dann wird der Wert wieder a zugewiesen.

Do not immer doppelt so zuweisen, es sei denn, Sie müssen unbedingt. Das ist schrecklich zu lesen und zu verstehen. Es ist besser, lesbaren/einfacheren Code zu haben. Ich musste nie etwas auf diese Weise zuordnen. Und ehrlich gesagt, gab es keinen Grund, den Range-Betrieb überhaupt zu bearbeiten, weil er sowieso ersetzt wurde. Es ist nur eine Kuriosität, die man am besten nicht benutzt. IMO.