Fasziniert von dieser Frage nach Endlosschleifen in Perl: while (1) Vs. für (;;) Gibt es einen Geschwindigkeitsunterschied? Ich habe beschlossen, einen ähnlichen Vergleich in Python durchzuführen. Ich habe erwartet, dass der Compiler den gleichen Bytecode für while(True): pass
und generiert while(1): pass
, aber dies ist in Python2.7 eigentlich nicht der Fall.
Das folgende Skript:
import dis
def while_one():
while 1:
pass
def while_true():
while True:
pass
print("while 1")
print("----------------------------")
dis.dis(while_one)
print("while True")
print("----------------------------")
dis.dis(while_true)
führt zu folgenden Ergebnissen:
while 1
----------------------------
4 0 SETUP_LOOP 3 (to 6)
5 >> 3 JUMP_ABSOLUTE 3
>> 6 LOAD_CONST 0 (None)
9 RETURN_VALUE
while True
----------------------------
8 0 SETUP_LOOP 12 (to 15)
>> 3 LOAD_GLOBAL 0 (True)
6 JUMP_IF_FALSE 4 (to 13)
9 POP_TOP
9 10 JUMP_ABSOLUTE 3
>> 13 POP_TOP
14 POP_BLOCK
>> 15 LOAD_CONST 0 (None)
18 RETURN_VALUE
Die Verwendung while True
ist spürbar komplizierter. Warum ist das?
In anderen Kontexten verhält sich Python so, als wäre es True
gleich 1:
>>> True == 1
True
>>> True + True
2
Warum while
unterscheidet man die beiden?
Mir ist aufgefallen, dass python3 die Anweisungen mit identischen Operationen auswertet:
while 1
----------------------------
4 0 SETUP_LOOP 3 (to 6)
5 >> 3 JUMP_ABSOLUTE 3
>> 6 LOAD_CONST 0 (None)
9 RETURN_VALUE
while True
----------------------------
8 0 SETUP_LOOP 3 (to 6)
9 >> 3 JUMP_ABSOLUTE 3
>> 6 LOAD_CONST 0 (None)
9 RETURN_VALUE
Gibt es in Python3 eine Änderung in der Art und Weise, wie Boolesche Werte ausgewertet werden?
Antworten:
In Python 2.x
True
ist dies kein Schlüsselwort, sondern nur eine integrierte globale Konstante , die imbool
Typ auf 1 definiert ist . Daher muss der Interpreter noch den Inhalt von ladenTrue
. Mit anderen Worten,True
ist neu zuweisbar:In Python 3.x wird es wirklich zu einem Schlüsselwort und einer echten Konstante:
Somit kann der Interpreter die
while True:
Schleife durch eine Endlosschleife ersetzen .quelle
while 1
undwhile True
sind in Python 3 identisch?Das ist nicht ganz richtig,
da kann man noch aus der schleife ausbrechen. Es ist jedoch richtig, dass auf eine solche Schleifenklausel
else
in Python 3 niemals zugegriffen werden würde. Und es ist auch wahr, dass die Vereinfachung der Wertesuche dazu führt, dass sie genauso schnell ausgeführt wird wiewhile 1
in Python 2.Leistungsvergleich
Demonstration des Zeitunterschieds für eine etwas nicht triviale while-Schleife:
Konfiguration
Python 2
Python 3
Erläuterung
Um den Unterschied in Python 2 zu erklären:
aber in Python 3:
Da
True
es sich in Python 3 um ein Schlüsselwort handelt, muss der Interpreter den Wert nicht nachschlagen, um festzustellen, ob jemand ihn durch einen anderen Wert ersetzt hat. Da man jedoch einenTrue
anderen Wert zuweisen kann, muss der Interpreter ihn jedes Mal nachschlagen.Fazit für Python 2
Wenn Sie in Python 2 eine enge, lang laufende Schleife haben, sollten Sie wahrscheinlich
while 1:
anstelle von verwendenwhile True:
.Fazit für Python 3
Verwenden
while True:
Sie diese Option, wenn Sie keine Bedingung zum Ausbrechen Ihrer Schleife haben.quelle
Dies ist eine 7 Jahre alte Frage, die bereits eine gute Antwort hat, aber ein Missverständnis in der Frage, das in keiner der Antworten angesprochen wird, macht sie möglicherweise verwirrend für einige der anderen Fragen, die als Duplikate markiert sind.
Tatsächlich
while
macht man hier überhaupt nichts anderes. Es unterscheidet1
undTrue
genauso wie das+
Beispiel.Hier ist 2.7:
Vergleichen Sie nun:
Es gibt
LOAD_GLOBAL (True)
für jeden ein a ausTrue
, und der Optimierer kann mit einem globalen Objekt nichts anfangen. Also,while
unterscheidet1
undTrue
aus genau dem gleichen Grund, der es+
tut. (Und==
unterscheidet sie nicht, weil der Optimierer Vergleiche nicht optimiert.)Vergleichen Sie nun 3.6:
Hier wird ein
LOAD_CONST (True)
Schlüsselwort für das Schlüsselwort ausgegeben, das der Optimierer nutzen kann . AlsoTrue + 1
nicht unterscheiden, aus genau dem gleichen Grundwhile True
nicht. (Und==
unterscheidet sie immer noch nicht, weil der Optimierer Vergleiche nicht optimiert.)Inzwischen, wenn der Code nicht optimiert geführt wird, endet der Dolmetscher auf die Behandlung
True
und1
genau das gleiche in allen drei dieser Fälle.bool
ist eine Unterklasse vonint
und erbt die meisten ihrer Methoden vonint
undTrue
hat einen internen ganzzahligen Wert von 1. Egal, ob Sie einenwhile
Test (__bool__
in 3.x,__nonzero__
in 2.x), einen Vergleich (__eq__
) oder eine Arithmetik durchführen (__add__
), Sie rufen dieselbe Methode auf, unabhängig davon, ob SieTrue
oder verwenden1
.quelle