Ist False == 0 und True == 1 ein Implementierungsdetail oder wird es durch die Sprache garantiert?

244

Ist sichergestellt , dass False == 0und True == 1in Python (unter der Annahme , dass sie nicht vom Benutzer zugewiesen werden)? Ist zum Beispiel in irgendeiner Weise garantiert, dass der folgende Code unabhängig von der Version von Python (sowohl vorhandene als auch wahrscheinlich zukünftige) immer die gleichen Ergebnisse liefert?

0 == False  # True
1 == True   # True
['zero', 'one'][False]  # is 'zero'

Jeder Verweis auf die offizielle Dokumentation wäre sehr dankbar!

Bearbeiten : Wie in vielen Antworten erwähnt, boolerbt von int. Die Frage kann daher wie folgt umformuliert werden: "Sagt die Dokumentation offiziell, dass sich Programmierer auf Boolesche Werte01 verlassen können, die von ganzen Zahlen mit den Werten und erben ?". Diese Frage ist relevant für das Schreiben von robustem Code, der aufgrund von Implementierungsdetails nicht fehlschlägt!

Eric O Lebigot
quelle
63
@ S.Lott: Es gibt viele Gründe, die obige Frage zu stellen. Daher gibt es Fälle, in denen die Verwendung von Booleschen Werten als Ganzzahl Ihren Code einfacher macht: Müssen Sie ihn ändern? Oder Sie können Stellen in einem Code erkennen, der von einer anderen Person geschrieben wurde, die sich darauf verlässt, dass Boolesche Werte Ganzzahlen sind: Unterbrechen Sie das, was Sie im Code ändern, um vorhandenen Code zu "reparieren", oder können Sie sicher sein, dass die aktuelle Codierung korrekt ist ? Es gibt eine Vielzahl anderer Beispiele. Im Allgemeinen ist es gut, die Spielregeln zu kennen, damit Sie es gut spielen und auf solide Weise programmieren können.
Eric O Lebigot
10
@ S.Lott: Der ursprüngliche Beitrag gibt genau Ihren Standpunkt wieder: Die Frage lautet im Wesentlichen "Ist dies ein Implementierungsdetail?", Da ich Ihnen voll und ganz zustimme, dass man sich nicht auf Implementierungsdetails verlassen sollte. Wenn Boolesche Werte offiziell ganze Zahlen bekannter Werte sind, basiert der Code in der Frage nicht auf Implementierungsdetails, was gut ist.
Eric O Lebigot
5
@S. Lot: Wenn Sie wissen, dass False == 0 und True == 1 sind, können Sie leichter zählen, wie viele Bools in einer Sequenz wahr sind: Sie können einfach schreiben sum(bool_list). Sonst müsstest du schreiben sum(1 for x bool_list if x).
dan04
8
@dan: Das ist eine Möglichkeit, Boolesche Werte zu zählen. Ich würde sagen, das bool_list.count(True)ist expliziter; es ist auch ungefähr 3 mal schneller… :)
Eric O Lebigot
2
@akonsu Wie die Antworten zeigen, Python booleans sind tatsächlich (eine bestimmte Unterklasse) ganze Zahlen sind . Darüber hinaus Python offensichtlich hat Typen; Vielleicht haben Sie gemeint, dass es "nicht statisch typisiert" ist? Ich bin mir auch nicht sicher, was Sie unter "Ich würde keine Fehler im Code machen" verstehen. Nun, ich mag es nie, Boolesche Werte mit ganzen Zahlen zu mischen, weil sie konzeptionell unterschiedlich sind, und es würde mir nichts ausmachen, wenn Python-Boolesche Werte keine ganzen Zahlen wären, aber zu wissen, dass sie mit den Werten 0 und 1 vorliegen, ist nützlich.
Eric O Lebigot

Antworten:

183

In Python 2.x ist dies nicht garantiert, da eine Neuzuweisung möglich Trueund möglich ist False. Selbst wenn dies passiert, werden boolean True und boolean False für Vergleiche immer noch ordnungsgemäß zurückgegeben.

In Python 3.x Trueund Falsesind Schlüsselwörter und werden immer gleich 1und sein 0.

Unter normalen Umständen in Python 2 und immer in Python 3:

FalseObjekt ist vom Typ, boolder eine Unterklasse von int:

object
   |
 int
   |
 bool

Dies ist der einzige Grund, warum in Ihrem Beispiel ['zero', 'one'][False]funktioniert. Es würde nicht mit einem Objekt funktionieren, das keine Unterklasse von Ganzzahlen ist, da die Listenindizierung nur mit Ganzzahlen oder Objekten funktioniert, die eine __index__Methode definieren (danke mark-dickinson ).

Bearbeiten:

Dies gilt sowohl für die aktuelle Python-Version als auch für Python 3. In den Dokumenten für Python 2.6 und den Dokumenten für Python 3 heißt es beide:

Es gibt zwei Arten von Ganzzahlen: [...] Ganzzahlen (int) [...] Boolesche Werte (bool)

und im booleschen Unterabschnitt:

Boolesche Werte: Diese stellen die Wahrheitswerte False und True dar. [...] Boolesche Werte verhalten sich in fast allen Kontexten wie die Werte 0 bzw. 1, mit der Ausnahme, dass die Zeichenfolgen bei der Konvertierung in eine Zeichenfolge "False" oder "True" sind "werden jeweils zurückgegeben.

Es gibt auch für Python 2 :

In numerischen Kontexten (z. B. wenn sie als Argument für einen arithmetischen Operator verwendet werden) verhalten sie sich [False und True] wie die Ganzzahlen 0 bzw. 1.

Daher werden Boolesche Werte in Python 2.6 und 3 explizit als Ganzzahlen betrachtet.

Sie sind also sicher, bis Python 4 verfügbar ist. ;-);

Olivier Verdier
quelle
2
0 == 0.0 gibt True zurück, während ['Null', 'Eins'] [0.0] fehlschlägt. ['Null', 'Eins'] [Falsch] funktioniert, weil bool eine Unterklasse von int ist. (int .__ Unterklassen __ () gibt [<type 'bool'>] zurück)
luc
20
Nitpick: Jedes Objekt, das eine __index__Methode bereitstellt , kann als Listenindex verwendet werden. nicht nur Unterklassen von intoder long.
Mark Dickinson
Ah ja, es ist auch da. Es ist jedoch besser, keinen Link zur Python 3.0-Dokumentation zu erstellen: 3.0 ist tot. :)
Mark Dickinson
4
Betreff: "In Python 2.x ist dies nicht garantiert, da True und False möglicherweise neu zugewiesen werden können." IMHO, während dies wahr ist, verdient jeder, der Wahr oder Falsch neu zuweist, die seltsamen Konsequenzen, die er bekommt. Insbesondere würde das Speichern von True vor der Neuzuweisung und das anschließende Vergleichen des Ergebnisses mit True nach der Neuzuweisung unterbrochen. a = True; True = 'i am an idiot'; a == True=> Falsch. Abgesehen von einer solchen Neuzuweisung sind die Standardwerte als 0 und 1 standardisiert, und ich glaube, es ist gängige Praxis, davon abzuhängen. zB um in ein Array mit zwei Elementen zu indizieren, wobei [0] den falschen Fall enthält, [1] wahr.
ToolmakerSteve
Ich habe gerade eine weitere offizielle Bestätigung der Tatsache bemerkt, dass True in der Praxis als 1 und False 0 betrachtet werden kann: docs.python.org/2/library/stdtypes.html#boolean-values . Ich füge dies dieser Antwort hinzu.
Eric O Lebigot
77

Link zum PEP, in dem der neue Bool-Typ in Python 2.3 erläutert wird: http://www.python.org/dev/peps/pep-0285/ .

Beim Konvertieren eines Bools in ein Int ist der ganzzahlige Wert immer 0 oder 1, aber beim Konvertieren eines int in ein Bool ist der boolesche Wert für alle Ganzzahlen außer 0 True.

>>> int(False)
0
>>> int(True)
1
>>> bool(5)
True
>>> bool(-5)
True
>>> bool(0)
False
Erik Cederstrand
quelle
22

In Python 2.x ist dies überhaupt nicht garantiert:

>>> False = 5
>>> 0 == False
False

Es könnte sich also ändern. In Python 3.x sind True, False und None reservierte Wörter , sodass der obige Code nicht funktioniert.

Im Allgemeinen sollten Sie bei Booleschen Werten davon ausgehen, dass False zwar immer einen ganzzahligen Wert von 0 hat (solange Sie ihn nicht wie oben ändern), True jedoch einen anderen Wert haben kann. Ich würde mich nicht unbedingt auf eine Garantie verlassen True==1, aber auf Python 3.x wird dies immer der Fall sein, egal was passiert.

Daniel G.
quelle
3
Zu "True könnte jeden anderen Wert haben. Ich würde mich nicht unbedingt auf eine Garantie verlassen, dass True == 1". Tatsächlich können Sie sich auf True == 1 gemäß python.org/dev/peps/pep-0285 und spec docs.python.org/2/reference/… verlassen. "Boolesche Werte verhalten sich wie die Werte 0 bzw. 1 , in fast allen Kontexten ... "Ich sage nicht, dass es unmöglich ist, dies in Py 2 durch Neuzuweisung von Richtig oder Falsch zu überschreiben, aber ich sage, dass, wenn kein Programmierer in Ihrem Projekt ein Idiot ist und eine solche Neuzuweisung vornimmt, die Verhalten ist garantiert.
ToolmakerSteve
-2

Sehr einfach. Da sich Bool auf die Auswertung einer Ganzzahl als Bool bezieht, gibt NUR Null eine falsche Antwort. ALLE Nicht-Null-Werte, Gleitkommazahlen, Ganzzahlen, einschließlich negativer Zahlen oder was Sie haben, geben true zurück.

Ein gutes Beispiel dafür, warum dies nützlich ist, ist die Bestimmung des Stromversorgungsstatus eines Geräts. Ein ist ein Wert ungleich Null, Aus ist Null. Elektronisch gesehen macht dies Sinn.

Um relativ zwischen den Werten wahr oder falsch zu bestimmen, müssen Sie etwas haben, mit dem Sie es vergleichen können. Dies gilt für Strings und Zahlenwerte, mit ==oder !=oder <, > >=,<= usw.

Sie können einer Variablen eine Ganzzahl zuweisen und dann basierend auf diesem Variablenwert true oder false erhalten.

Kathy
quelle
1
Die Frage ist, ob True == 1 von Python garantiert wird, nicht der boolesche Wert von ganzen Zahlen.
Eric O Lebigot
-3

Schreiben int(False)Sie einfach und Sie erhalten 0, wenn Sie eingeben int(True), wird es ausgegeben1

Harte Rathee
quelle
4
Dies bedeutet nur, dass False und True gültige Eingaben int()mit einer einfachen numerischen Bedeutung sind, nicht dass sie genau mit 0 und 1 identisch sind.
Eric O Lebigot
-5

Falsch ist ein Trottel. Es hat einen anderen Typ. Es ist ein anderes Objekt als 0, das eine Ganzzahl ist.

0 == FalseGibt True zurück, da False in eine Ganzzahl umgewandelt wird. int (False) gibt 0 zurück

In der Python-Dokumentation des Operators == heißt es (help ('==')):

Die Betreiber <, >, ==, >=, <=, und !=die Werte der zwei Objekte vergleichen. Die Objekte müssen nicht denselben Typ haben. Wenn beide Zahlen sind, werden sie in einen gemeinsamen Typ konvertiert.

Infolgedessen wird False für den Vergleich in eine Ganzzahl konvertiert. Aber es ist anders als 0.

>>> 0 is False
False
luc
quelle
26
Das ist nicht ganz richtig: boolist eine Unterklasse von int, so in einem sehr realen Sinne ein Bool ist eine ganze Zahl. Gibt beispielsweise isinstance(True, int)True zurück. Und die Gleichheitsprüfung konvertiert den Bool nicht in ein int, da keine Konvertierung erforderlich ist: Sie ruft einfach int.__cmp__direkt auf. Beachten Sie, dass bool.__cmp__ is int.__cmp__auch ausgewertet wird True.
Mark Dickinson
3
-1 für diese Antwort. Falsche Beschreibung der Beziehung zwischen bool und int (in Python 2). isinstance(True, int)=> Richtig. Das heißt, True IS ist eine Ganzzahl und erfordert keine Konvertierung.
ToolmakerSteve
Ich hatte ein Skript, das False oder ein Int ... mit while response is Falsefunktioniert zurückgab , und while response == Falsetat es nicht. Danke!
curly_brackets
5
Das 0 is Falseist falsch, sagt dir nichts. Geben Sie in Ihrem interaktiven Interpreter x = -10dann y = -10, dann x is yund das ein auch falsch. Nur weil es Optimierungen an Ort und Stelle , wo die Python - Interpreter wieder verwendet die gleichen ganzzahligen Objekte unter bestimmten Umständen (Ganzzahlliterale als Konstanten zu speichern, kleine ganze Zahlen Internierung) bedeutet nicht , dass isverwendet werden soll , wenn Sie testen wollen für Integer - Wert Gleichheit.
Martijn Pieters