Beim Betrachten von Queue.py in Python 2.6 fand ich dieses Konstrukt, das ich etwas seltsam fand:
def full(self):
"""Return True if the queue is full, False otherwise
(not reliable!)."""
self.mutex.acquire()
n = 0 < self.maxsize == self._qsize()
self.mutex.release()
return n
Wenn maxsize
0 ist, ist die Warteschlange nie voll.
Meine Frage ist, wie es in diesem Fall funktioniert? Wie 0 < 0 == 0
wird als falsch angesehen?
>>> 0 < 0 == 0
False
>>> (0) < (0 == 0)
True
>>> (0 < 0) == 0
True
>>> 0 < (0 == 0)
True
>>> (0) < (0 == 0)
, dass dies eindeutig nicht der Fall ist.n = 0 < self.maxsize == self._qsize()
in irgendeiner Sprache schreiben sollten . Wenn Ihre Augen mehrmals über die Linie hin und her huschen müssen, um herauszufinden, was los ist, ist dies keine gut geschriebene Linie. Teilen Sie es einfach in mehrere Zeilen auf.Antworten:
Ich glaube, Python hat eine spezielle Fallbehandlung für Sequenzen von Vergleichsoperatoren, um Bereichsvergleiche einfach auszudrücken. Es ist viel schöner sagen zu können
0 < x <= 5
als zu sagen(0 < x) and (x <= 5)
.Diese werden als verkettete Vergleiche bezeichnet . Und das ist ein Link zur Dokumentation für sie.
In den anderen Fällen, über die Sie sprechen, wird in Klammern ein Vergleichsoperator vor dem anderen angewendet, sodass es sich nicht mehr um verkettete Vergleiche handelt. Und da
True
undFalse
Werte als Ganzzahlen haben, erhalten Sie die Antworten, die Sie tun, aus den in Klammern gesetzten Versionen.quelle
weil
ist
False
. Sie können Vergleichsoperatoren verketten und sie werden automatisch zu paarweisen Vergleichen erweitert.EDIT - Klarstellung über Richtig und Falsch in Python
In Python
True
undFalse
sind nur Instanzen vonbool
, was eine Unterklasse von istint
. Mit anderen Worten, istTrue
wirklich nur 1.Der Punkt dabei ist, dass Sie das Ergebnis eines booleschen Vergleichs genau wie eine Ganzzahl verwenden können. Dies führt zu verwirrenden Dingen wie
Dies geschieht jedoch nur, wenn Sie die Vergleiche in Klammern setzen, damit sie zuerst ausgewertet werden. Andernfalls erweitert Python die Vergleichsoperatoren.
quelle
'success' if result_code == 0 else 'failure'
kann wie folgt umgeschrieben werden('error', 'success')[result_code == 0]
: Ich hatte noch nie einen Booleschen Wert gesehen, mit dem ein Element in einer Liste / einem Tupel ausgewählt wurde.Das seltsame Verhalten, das Sie erleben, beruht auf der Fähigkeit von Python, Bedingungen zu verketten. Da festgestellt wird, dass 0 nicht kleiner als 0 ist, entscheidet es, dass der gesamte Ausdruck als falsch ausgewertet wird. Sobald Sie dies in separate Bedingungen zerlegen, ändern Sie die Funktionalität. Es testet zunächst im Wesentlichen das
a < b && b == c
für Ihre ursprüngliche Aussage vona < b == c
.Ein anderes Beispiel:
quelle
a < b && b == c
ist das gleiche wiea < b == c
OODies ist ein verketteter Vergleich. Es gibt true zurück, wenn jeder paarweise Vergleich der Reihe nach true ist. Es ist das Äquivalent zu
(0 < 0) and (0 == 0)
Dies entspricht
0 < True
der Auswertung von True.Dies entspricht
False == 0
der Auswertung von True.Entspricht
0 < True
dem, wie oben, True.quelle
Mit Blick auf die Demontage (die Bytes - Codes) ist es offensichtlich, warum
0 < 0 == 0
istFalse
.Hier ist eine Analyse dieses Ausdrucks:
Hinweiszeilen 0-8: Diese Zeilen prüfen, ob
0 < 0
diese offensichtlichFalse
auf den Python-Stapel zurückkehren.Beachten Sie nun Zeile 11:
JUMP_IF_FALSE_OR_POP 23
Dies bedeutet, dass Sie bei0 < 0
RückgabeFalse
einen Sprung zu Zeile 23 ausführen.Jetzt
0 < 0
wirdFalse
der Sprung ausgeführt, der den Stapel mit einemFalse
Rückgabewert für den gesamten Ausdruck verlässt0 < 0 == 0
, obwohl der== 0
Teil nicht einmal überprüft ist.Abschließend ist die Antwort wie in anderen Antworten auf diese Frage angegeben.
0 < 0 == 0
hat eine besondere Bedeutung. Der Compiler wertet dies mit zwei Begriffen aus:0 < 0
und0 == 0
. Wie bei allen komplexen booleschen Ausdrückenand
zwischen ihnen wird der zweite nicht einmal überprüft, wenn der erste fehlschlägt.Ich hoffe, dass dies die Dinge ein wenig aufklärt, und ich hoffe wirklich, dass die Methode, mit der ich dieses unerwartete Verhalten analysiert habe, andere dazu ermutigen wird, dies in Zukunft auch zu versuchen.
quelle
Wie bereits erwähnt,
x comparison_operator y comparison_operator z
handelt es sich um syntaktischen Zucker(x comparison_operator y) and (y comparison_operator z)
mit dem Bonus, dass y nur einmal bewertet wird.Ihr Ausdruck
0 < 0 == 0
ist also wirklich(0 < 0) and (0 == 0)
, was zuFalse and True
welchem gerecht wirdFalse
.quelle
Vielleicht kann dieser Auszug aus den Dokumenten helfen:
Dies waren Vergleiche, aber da Sie Vergleiche verketten , sollten Sie Folgendes wissen:
quelle
Hier ist es in seiner ganzen Pracht.
quelle
Ich denke, Python macht es komisch zwischen Magie. Gleich wie
1 < 2 < 3
Mittel 2 zwischen 1 und 3 liegt.In diesem Fall denke ich, dass [mittlere 0] größer als [links 0] und gleich [rechts 0] ist. Die mittlere 0 ist nicht größer als die linke 0, daher wird sie als falsch ausgewertet.
quelle