HOWTO zu den Booleschen Wahrheitswerten in Python (C) 2016-2025 T.Birnthaler/H.Gottschalk OSTC Open Source Training and Consulting GmbH http://www.ostc.de Dieses Dokument beschreibt die Boolesche Logik der Werte in Python, insbesondere die Booleschen Werte True und False sowie den Wert None. ________________________________________________________________________________ INHALTSVERZEICHNIS 1) Boolesche Werte 1b) Boolescher Kontext 1c) Darstellung per print/str/repr 1d) Formatierte Ausgabe 1e) Zusammenhang mit Zahlen-Datentypen int/float/complex 2) Logische Operatoren and, or, not und ihr Vorrang 2a) Vorrang 2b) Inhaltliches Ergebnis 2c) Tatsächliches Ergebnis 2d) Short Cut/Circuit Evaluation 2e) Rechenausdrücke mit logischen Werten (Expression) 2f) Bitweise Operatoren 2g) Logische Operator xor 3) Vergleiche 3a) True == 1/1.0 und False == 0/0.0 3b) Test auf leeren/gefüllten Container 4) Undefinierter Wert None 4a) 3-wertige Logik 4b) 3-wertige SQL-Logik ________________________________________________________________________________ 1) Boolesche Werte ------------------ Doku --> http://docs.python.org/3/library/stdtypes.html#truth --> http://docs.python.org/3/library/stdtypes.html#boolean-type-bool --> http://docs.python.org/3/library/stdtypes.html#boolean-values --> http://docs.python.org/3/library/stdtypes.html#truth-value-testing --> http://docs.python.org/3/library/stdtypes.html#boolean-operations-and-or-not --> http://docs.python.org/3/library/stdtypes.html#comparisons Python kennt den BOOLESCHEN Datentyp "bool" mit den Werten "True" und "False", aber interpretiert auch JEDEN anderen Wert JEDES Datentyps als LOGISCHEN Wert. Dabei ist EXAKT DEFINIERT, welche Werte als logisch "falsch" und welche als logisch "wahr" interpretiert werden. Logisch "falsch" sind GENAU die folgenden Werte (alle anderen WERTE sind logisch "wahr"): * Konstante "None" (steht für Wert "undefiniert/ungültig/unbekannt") * Konstante "False" (falsch) * Wert "0" numerischer Datentypen (int, float, complex, Decimal, Fraction) * Leere Sequenzen (str, list, tuple) * Leere Collections (dict, set) * Leere Generatoren (range) Vollständige Liste: +------------------+-------------------------------------------------------+ | Wert | Beschreibung | +------------------+-------------------------------------------------------+ | None | Undefinierter/ungültiger/unbekannter Wert | | False | Logisch falscher Wert | +------------------+-------------------------------------------------------+ | 0 -0 | Ganzzahl Null | | 0.0 -0.0 0e0 | Fließkommazahl Null | | 0l 0L | Ganzzahl Null (Datentpy "long", NUR in Python2!) | PY2 | 0j 0J -0j -0J | Imaginäre Zahl Null (Imaginärteil komplexe Zahl) | | Decimal(0) | Dezimalzahl 0 (interessant für Finanzbuchhaltung) | | Fraction(0,1) | Bruch 0/1 | +------------------+-------------------------------------------------------+ | "" | Leere Zeichenkette (auch '' r"" r'' """""" ...) | | () | Leerer Tupel | | [] | Leere Liste | | {} | Leeres Dictionary | | set() | Leere Menge | | range(0) | Leerer Wertebereich | +------------------+-------------------------------------------------------+ | bytes() | Leere Byte-Folge | | bytearray() | Leere Byte-Folge | | frozenset() | Leere Menge (im-mutable) | | ... | ... | +------------------+-------------------------------------------------------+ ALLE ANDEREN Werte werden als logisch "wahr" interpretiert, z.B. folgende (Auswahl): +----------------+-------------------------------------------+ | Wert | Bedeutung | +----------------+-------------------------------------------+ | True | Logisch wahrer Wert | | 1 | Zahl 1 | | -1 | Negative Zahl -1 | | 0.1 | Fließkommazahl 0.1 | | Decimal("0.1") | Dezimalzahl 0.1 | | Fraction(1,2) | Bruch 1/2 | +----------------+-------------------------------------------+ | " " | Zeichenkette 1 Leerzeichen | | " " | Zeichenkette 5 Leerzeichen | | "\n" | Zeichenkette 1 Newline | | "\r" | Zeichenkette 1 Carriage Return | | "\t" | Zeichenkette 1 Tabulator | | "None" | Zeichenkette Text "None" | | "False" | Zeichenkette Text "False" | | "0" | Zeichenkette 1 Zeichen "0" | | "00" | Zeichenkette 2 Zeichen "00" | | "+0" | Zeichenkette 2 Zeichen "+0" | | "-0" | Zeichenkette 2 Zeichen "-0" | | "0.0" | Zeichenkette 3 Zeichen "0.0" | | "abc" | Beliebige Zeichenkette ab 1 Zeichen Länge | +----------------+-------------------------------------------+ | (0,) | Tupel mit mind. 1 Wert | | [0] | Liste mit mind. 1 Wert | | {0:0} | Dictionary mit mind. 1 Wert | | {0} | Set mit mind. 1 Wert | | range(1) | Wertebereich mit mind. 1 Wert | +----------------+-------------------------------------------+ HINWEIS: In JEDER Programmiersprache gibt es eine EXAKTE DEFINITION, welche Werte als logisch "Falsch" und welche als logisch "Wahr" interpretiert werden. Üblich ist auch, dass JEDER Wert IMPLIZIT als Boolescher Wert interpretiert wird (z.B. als Bedingung in einer if-Verzweigung oder while-Schleife). EXPLIZIT erfolgt die Konvertierung in einen Booleschen Wert durch: bool(WERT) # Konvertierung (Python) not not WERT # 2-malige Negation (Python, SQL, ...) !!WERT # 2-malige Negation (C, C++, Java, ..., NICHT in Python!) 1b) Boolescher Kontext in if/while ---------------------------------- Die Anweisungen "if" und "while" erzwingen einen "Booleschen Kontext", in dem der Wert des steuernden Ausdrucks EXPR (Expression/Bedingung) als Boolescher Wert interpretiert wird: if EXPR: ... # Entspricht if bool(EXPR): ... while EXPR: ... # Entspricht while bool(EXPR): ... 1c) Darstellung per print/str/repr ---------------------------------- Die Booleschen Werte True und False sowie der "undefinierte" Wert None werden bei Ausgabe per print(...) bzw. bei Konvertierung per str(...) oder repr(...) als Text "True", "False" und "None" dargestellt: print(None) # --> None print(True) # --> True print(False) # --> False str(None) # --> 'None' str(True) # --> 'True' str(False) # --> 'False' repr(None) # --> 'None' repr(True) # --> 'True' repr(False) # --> 'False' 1d) Formatierte Ausgabe ----------------------- Die Booleschen Werte True und False werden im Rahmen der FORMATIERTEN AUSGABE folgendermaßen als Ganzzahl (d=decimal), Fließkommazahl (f=float, 6 Nkst.) und String (s=str) dargestellt: print("%d" % True) # --> 1 print("%f" % True) # --> 1.000000 print("%s" % True) # --> True print("{:d}".format(True)) # --> 1 print("{:f}".format(True)) # --> 1.000000 print("{:}".format(True)) # --> True print("{}".format(True)) # --> True print(F"{True:d}") # --> 1 print(F"{True:f}") # --> 1.000000 print(F"{True:}") # --> True print(F"{True}") # --> True print("%d" % False) # --> 0 print("%f" % False) # --> 0.000000 print("%s" % False) # --> False print("{:d}".format(False)) # --> 0 print("{:f}".format(False)) # --> 0.000000 print("{:}".format(False)) # --> False print("{}".format(False)) # --> False print(F"{False:d}") # --> 0 print(F"{False:f}") # --> 0.000000 print(F"{False:}") # --> False print(F"{False}") # --> False Mit Format "s" (str) ergeben "True" und "False" einen Fehler (seltsamerweise): print("{:s}".format(True)) # --> ValueError: Unknown format code 's' for object of type 'bool' print("{:s}".format(False)) # --> ValueError: Unknown format code 's' for object of type 'bool' print(F"{True:s}") # --> ValueError: Unknown format code 's' for object of type 'bool' print(F"{False:s}") # --> ValueError: Unknown format code 's' for object of type 'bool' Der Wert "None" kann formatiert nur ohne Formatangabe dargestellt werden: print("%s" % None) # --> None print("{}".format(None)) # --> None print(F"{None:}") # --> None print(F"{None}") # --> None Mit Format "d" (int) und "f" (float) und "s" (str) ergibt "None" einen Fehler: print("%d" % None) # --> TypeError: %d format: a real number is required, not NoneType print("%f" % None) # --> TypeError: must be real number, not NoneType print("{:d}".format(None)) # --> TypeError: unsupported format string passed to NoneType.__format__ print("{:f}".format(None)) # --> TypeError: unsupported format string passed to NoneType.__format__ print("{:s}".format(None)) # --> TypeError: unsupported format string passed to NoneType.__format__ print(F"{None:d}") # --> TypeError: unsupported format string passed to NoneType.__format__ print(F"{None:f}") # --> TypeError: unsupported format string passed to NoneType.__format__ print(F"{None:s}") # --> TypeError: unsupported format string passed to NoneType.__format__ 1e) Zusammenhang mit Zahlen-Datentypen int/float/complex -------------------------------------------------------- Der Datentyp "bool" ist eine SPEZIALISIERUNG des Datentyps "int", d.h. die Booleschen Werte "True/False" werden in Rechenausdrücken als Ganzzahl 1/0 interpretiert: True + 100 # --> 101 False + 100 # --> 100 True * 100 # --> 100 False * 100 # --> 0 True + False + 1 + 1.0 + (1+1j) # --> (4+1j) True * False * 1 * 1.0 * (1+1j) # --> 0j In Listen/Tupeln werden "True/False" als Index 1/0 interpretiert: lst = ["hallo", "welt", "hier", "bin", "ich"] print(lst[False]) # --> hallo print(lst[True]) # --> welt Ebenso werden "True/False" in Dictionaries/Sets mit den Keys 1/0 (int), 1.0/0.0 (float) und 1.0+0.0j/0.0+0.0j (complex) IDENTIFIZIERT (d.h. jeder der folgenden Keys kann nur 1x in einem Dictionary oder Set vorkommen). True 1 1.0 1.0+0.0j 1+0j False 0 0.0 0.0+0.0j 0+0j Vor PY3.7 wurde bei gleichzeitiger Verwendung der obigen Keys ein ZUFÄLLIGER Key + sein Wert ausgewählt, seit PY3.7 wird der ERSTE im Dictionary vorkommende Key mit dem LETZTEN diesem Key zugeordneten Wert ausgewählt: dct = {True: "bool", 1: "int", 1.0: "float", 1+0j: "complex"} print(dct) # --> {True: 'complex'} dct = {} # dct[True] = "bool" # dct[1] = "int" # dct[1.0] = "float" # dct[1+0j] = "complex" # print(dct) # --> {True: 'complex'} dct = {False: "bool", 0: "int", 0.0: "float", 0j: "complex"} print(dct) # --> {False: 'complex'} dct = {} # dct[False] = "bool" # dct[0] = "int" # dct[0.0] = "float" # dct[0j] = "complex" # print(dct) # --> {False: 'complex'} 2) Logische Operatoren and, or, not ----------------------------------- Die Booleschen Operatoren AND, OR und NOT zur logischen Verknüpfung von Werten werden durch die Schlüsselworte and, or und not dargestellt. Die aus den Programmiersprachen C/C++/... bekannten Syntaxformen && || ! für die Booleschen Operatoren gibt es in Python nicht! Den Booleschen Operator XOR gibt es nicht als Schlüsselwort, er lässt sich aber durch den Operator ^ darstellen (Bitweises-XOR) falls zwei Boolesche Werte verknüpft werden. 2a) Vorrang ----------- Bei KOMBINATION der logischen Operatoren "and", "or" und "not" in einem Ausdruck gilt folgender VORRANG (wie in allen anderen Programmiersprachen auch): +-----+-------------+ | not | höchster | | and | mittlerer | | or | niedrigster | +-----+-------------+ 2b) Inhaltliches Ergebnis ------------------------- Die logischen Operatoren "and", "or" und "not" liefern angewendet auf Wahrheitswerte (oder beliebige andere Werte, die dann gemäß obiger Tabelle als Wahrheitswerte interpretiert werden) folgende Resultate: +------------+-----------------------------------------------------------+ | Operator | Bedeutung | +------------+-----------------------------------------------------------+ | A and B | UND: Resultat "True" wenn beide Operanden A und B True | | | Resultat "False" sonst | | A or B | ODER: Resultat "False" wenn beide Operanden A und B False | | | Resultat "True" sonst | | not A | NICHT: Resultat "True" wenn Operand A False | | | Resultat "False" wenn Operand A True | +------------+-----------------------------------------------------------+ 2c) Tatsächliches Ergebnis -------------------------- Der logische Operator "not" liefert IMMER True oder False zurück: not True # --> False not False # --> True not "abc" # --> False not "" # --> True not 0 # --> True not 1 # --> False not [] # --> True Die logischen Operatoren "and" und "or" liefern IMMER den LETZTEN für das Ergebnis ausgewerteten Wert (interpretierbar als Wahrheitswert) zurück: 5 or "abc" # --> 5 = True 1 or ["abc"] # --> 1 = True 0 or "abc" # --> 'abc' = True 0 or "" # --> '' = False (leerer String) 1 and 234 # --> 234 = True 1 and ["abc"] # --> ['abc'] = True 9 and None # --> None = False 0 and [] # --> 0 = False 2d) Short Cut/Circuit Evaluation -------------------------------- Die logische Operatoren and und or werden VON LINKS NACH RECHTS ausgewertet (unter Berücksichtigung ihres Vorrangs). Ergibt sich dabei ein Zwischenergebnis, bei dem auch das ENDERGEBNIS des gesamten logischen Ausdrucks feststeht, wird die Auswertung an dieser Stelle abgebrochen und der Rest des logischen Ausdrucks nicht mehr ausgewertet ("Short Cut/Circuit Evaluation", verkürzte Auswertung). Dieses Verhalten ist KEINE Besonderheit von Python, sondern ist in vielen Programmiersprachen (z.B. C, C++, Java, JavaScript, Perl, PHP, Ruby, Awk) genauso üblich. * Folge von UND-Verknüpfungen (and) bricht mit Gesamtergebnis False ab, sobald 1x False als Zwischenergebnis vorkommt. * Folge von ODER-Verknüpfungen (or) bricht mit Gesamtergebnis True ab, sobald 1x True als Zwischenergebnis vorkommt. Beispiel: 0 and "KEINE Ausgabe" # --> 0 = False 1 and "Ausgabe" # --> 'Ausgabe' = True 1 or "KEINE Ausgabe" # --> 1 = True 0 or "Ausgabe" # --> 'Ausgabe' = True 5 or "abc" or 7.5 # --> 5 = True 0 or "abc" or 7.5 # --> 'abc' = True 0 or "" or 7.5 # --> 7.5 = True 1 and "" and 3.14 # --> '' = False (leerer String) 1 and 234 and 74 # --> 74 = True 9 and None and 8 # --> None = False 0 or [] or {} # --> {} = False (leeres dict) 2e) Rechenausdrücke mit logischen Werten (Expression) ----------------------------------------------------- In Rechenausdrücken (Expression) zählt True als Zahl 1 und False als Zahl 0. D.h. Berechnungen mit Booleschen Werten sind erlaubt: 123 - True # --> 122 False + 123 # --> 123 True * True # --> 1 True * False # --> 0 5 * True - 3 * False # --> 5 if monat == 2: max_tag = monat_laenge(monat) + schaltjahr(jahr) # schaltjahr --> True/False else: max_tag = monat_laenge(monat) 2f) Bitweise Operatoren ----------------------- Die Operatoren & (Bit-and), | (Bit-or), ^ (Bit-xor), ~ (Bit-invert, Zweier-Komplement), << (Bit-shift-left) und >> (Bit-shift-right) für die BITWEISEN Operationen lieferen eine bitweise Verknüpfung von 2 Zahlen (analog C/C++/...). 0b1010 & 0b1100 # Bit-and: 10 & 12 --> 8 = 0b1000 0b1010 | 0b1100 # Bit-or: 10 | 12 --> 14 = 0b1110 0b1010 ^ 0b1100 # Bit-xor: 10 ^ 12 --> 6 = 0b0110 ~ 0b1010 # Bit-invert: ~ 10 --> -11 = -0b1011 = -10 - 1 0b1010 << 1 # Bit-shift-left: 10 << 1 --> 20 = 0b10100 0b1010 >> 1 # Bit-shift-right: 10 >> 1 --> 5 = 0b0101 2g) Logischer Operator xor -------------------------- Der Bitweise XOR-Operator ^ liefert normalerweise eine ganze Zahl zurück. Beim Verknüpfen von zwei Booleschen Werten liefert er allerdings wieder einen Booleschen Wert zurück, kann also als Ersatz für (den fehlenden) logischen Operator "xor" verwendet werden: True ^ True # --> False True ^ False # --> True False ^ True # --> True False ^ False # --> False HINWEIS: Die Operatoren & und | verhalten sich ebenfalls so, dass sie bei Verknüpfung zweier Booleschen Werten wieder einen Booleschen Wert zurückliefern und somit als Ersatz für "and" und "or" verwendet werden können. True & True # --> True False & True # --> False True & False # --> False False & False # --> False True | True # --> True False | True # --> True True | False # --> True False | False # --> False HINWEIS: Der Operator ~ (Bitweise-Invertieren) lässt sich nicht als Ersatz für "not" verwenden! ~ True # --> -2 ~ False # --> -1 Die Vorrangtabelle ist dann insgesamt allerdings etwas unübersichtlich: +-----+-------------+ | & | and-Ersatz | | ^ | XOR-Ersatz | | | | or-Ersatz | +-----+-------------+ | not | höchster | | and | mittlerer | | or | niedrigster | +-----+-------------+ Um den "nächsten Programmierer" nicht zu verwirren, sollten bei LOGISCHEN VERKNÜPFUNGEN die Bit-Operatoren NICHT als Ersatz für die logischen Operatoren verwendet werden. 3) Vergleiche ------------- Folgende Vergleiche prüfen, ob eine Variable den Wert True bzw. False hat: if VAR: # VAR True? (GUT) if not VAR: # VAR False? (GUT) if VAR == True: # --> False außer VAR hat Wert True/1/1.0 (SCHLECHT) if VAR == False: # --> False außer VAR hat Wert False/0/0.0 (SCHLECHT) if VAR != True: # --> True außer VAR hat Wert True (SCHLECHT) if VAR != False: # --> True außer VAR hat Wert False (SCHLECHT) if VAR is True: # --> False außer VAR hat Wert True (SCHLECHT) if VAR is False: # --> False außer VAR hat Wert False (SCHLECHT) if VAR is not True: # --> True außer VAR hat Wert True (SCHLECHT) if VAR is not False: # --> True außer VAR hat Wert False (SCHLECHT) ACHTUNG: Nur die beiden ersten Tests sind allgemein gültig, die anderen Tests prüfen nur EINEN Wert/EINIGE Werte, aber nicht alle Werte gemäß Tabelle --> 1) Boolesche Werte. 3a) True == 1/1.0 und False == 0/0.0 ------------------------------------ Aus historischen Gründen (der Datentyp "bool" wurde erst später als Subtyp von "int" hinzugefügt) liefern folgende Vergleiche alle den Wert True (obwohl die Datentypen der verglichenen Werte unterschiedlich sind): True == 1 # --> True True == 1.0 # --> True True == 1+0j # --> True 1 == 1.0 # --> True 1 == 1+0j # --> True 1.0 == 1+0j # --> True False == 0 # --> True False == 0.0 # --> True False == 0j # --> True 0 == 0.0 # --> True 0 == 0j # --> True 0.0 == 0j # --> True 3b) Test auf leeren/gefüllten Container --------------------------------------- Da JEDES Objekt im Booleschen Kontext einen Wahrheitswert ergibt, kann ein Test auf leeren/gefüllten CONTAINER (str, tuple, list, dict, set, ...) folgendermaßen durchgeführt werden: if CONT: # CONTAINER enthält mind. 1 Element --> True/False (GUT) if not CONT: # CONTAINER leer --> True/False (GUT) if len(CONT) != 0: # CONTAINER enthält mind. 1 Element --> True/False (SCHLECHT) if len(CONT) > 0: # CONTAINER enthält mind. 1 Element --> True/False (SCHLECHT) if len(CONT) >= 1: # CONTAINER enthält mind. 1 Element --> True/False (SCHLECHT) if len(CONT) == 0: # CONTAINER leer --> True/False (SCHLECHT) if TUPEL != (): # Tupel enthält mind. 1 Element --> True/False (SCHLECHT) if TUPEL == (): # Tupel leer --> True/False (SCHLECHT) if LISTE != []: # Liste enthält mind. 1 Element --> True/False (SCHLECHT) if LISTE == []: # Liste leer --> True/False (SCHLECHT) if DICT != {}: # Dictionary enthält mind. 1 Eintrag --> True/False (SCHLECHT) if DICT == {}: # Dictionary leer --> True/False (SCHLECHT) if STR != "": # String enthält mind. 1 Zeichen --> True/False (SCHLECHT) if STR == "": # String leer --> True/False (SCHLECHT) HINWEIS: Die beiden ersten Varianten sind vom Standpunkt der Allgemeinheit, der Performance und des Speicherverbrauchs aus die Geschicktesten! 4) Undefinierter Wert None -------------------------- Ein undefinierter (unbekannter/ungültiger) Wert kann in Python durch "None" dargestellt werden (hat den Datentyp "NoneType" bzw. ab PY3.7 type(None)). Variablen mit diesem Wert sind UNDEFINIERT (analog SQL-Wert "NULL"), ALLE anderen Werte sind DEFINIERT. Der Datentyp "NoneType" und sein einziger Wert "None" können eigentlich miteinander IDENTIFIZIERT werden (SINGLETON). Ab PY3.7 gibt es daher den Bezeichner "NoneType" für den Datentyp nicht mehr direkt, sondern nur indirekt per type(None): NoneType = type(None) # ab PY3.7 Folgende Tests prüfen, ob der Wert einer Variablen "var" DEFINIERT bzw. UNDEFINIERT ist: if var is None: ... # var UNDEFINIERT? (EMPFOHLEN!) if var == None: ... # var UNDEFINIERT? (NICHT empfohlen) if type(var) == NoneType: ... # var UNDEFINIERT? (NICHT empfohlen) if type(var) == type(None): ... # var UNDEFINIERT? (NICHT empfohlen, ab PY3.7) if isinstance(var, NoneType): ... # var UNDEFINIERT? (NICHT empfohlen) if isinstance(var, type(None): ... # var UNDEFINIERT? (NICHT empfohlen, ab PY3.7) if var is not None: ... # var DEFINIERT? (EMPFOHLEN!) if not var is None: ... # var DEFINIERT? (NICHT empfohlen) if var != None: ... # var DEFINIERT? (NICHT empfohlen) if not var == None: ... # var DEFINIERT? (NICHT empfohlen) if type(var) != NoneType: ... # var DEFINIERT? (NICHT empfohlen) if type(var) != type(None): ... # var DEFINIERT? (NICHT empfohlen, ab PY3.7) if not isinstance(var, NoneType): ... # var DEFINIERT? (NICHT empfohlen) if not isinstance(var, type(None): ... # var DEFINIERT? (NICHT empfohlen, ab PY3.7) Numerische Berechnungen mit "None" generieren IMMER einen "TypeError": None + 3 # --> TypeError! None - 3 # --> TypeError! None * 3 # --> TypeError! None / 3 # --> TypeError! None % 3 # --> TypeError! None // 3 # --> TypeError! None ** 3 # --> TypeError! Vergleiche mit dem Wert "None" sind nur für is, is not, == und != möglich: None is None # --> True None is True # --> False None is not None # --> False None is not True # --> True None == None # --> True None == True # --> False None != None # --> False None != 123 # --> True Alle anderen Vergleiche mit "None" generieren IMMER einen "TypeError": None < "" # --> TypeError! None > 3.14 # --> TypeError! None <= [] # --> TypeError! None >= 3+3j # --> TypeError! 4a) 3-wertige Logik ------------------- Die Werte "True", "False" und "None" bilden bgzl. der Operatoren "and", "or" und "not" eine 3-wertige Logik, wobei "None" bei der Auswertung als "False zählt und daher als linker Wert von "and" und als rechter Wert von "or" erhalten bleibt bzw. bei "not" zu True wird (d.h. "and", "or", "not" verhalten sich UN-SYMMETRISCH, bzw. "and", "or" verhalten sich NICHT KOMMUTATIV). * and: True links --> rechter Wert False/None links --> linker Wert * or: True links --> True False/None links --> rechter Wert * not: True --> False False/None --> True +-------+-------++-------+-------+-------+-------+ | a | b || and | or | not | ^ | +-------+-------++-------+-------+-------+-------+ | True | True || True | True | | False | | True | False || False | True | False | True | | True | None || None | True | | ERROR*| +-------+-------++-------+-------+-------+-------+ | False | True || False | True | | True | | False | False || False | False | True | False | | False | None || False | None | | ERROR*| +-------+-------++-------+-------+-------+-------+ | None | True || None | True | | ERROR*| | None | False || None* | False*| True* | ERROR*| | None | None || None | None | | ERROR*| +-------+-------++-------+-------+-------+-------+ ERROR = TypeError ausgelöst * = Abweichung zu SQL-Logik 4b) 3-wertige SQL-Logik ----------------------- Die 3-wertige SQL-Logik mit den SQL-Werten TRUE, FALSE und NULL verhält sich etwas anders (NULL zählt nicht als FALSE, sondern als "undefiniert/ungültig/ unbekannt") und ist somit Ergebnis, falls kein anderweitiges eindeutiges Ergebnis möglich ist (and, or, not, xor verhalten sich SYMMETRISCH bzw. and, or, xor verhalten sich KOMMUTATIV). * AND: TRUE links --> rechter Wert FALSE links/rechts --> FALSE Sonst --> NULL * OR: FALSE links --> rechter Wert TRUE links/rechts --> TRUE Sonst --> NULL * NOT: TRUE --> FALSE FALSE --> TRUE NULL --> NULL * XOR: Ein NULL --> NULL Zwei TRUE/FALSE --> FALSE Sonst --> TRUE +-------+-------++-------+-------+-------+-------+ | a | b || and | or | not | xor | +-------+-------++-------+-------+-------+-------+ | TRUE | TRUE || TRUE | TRUE | | FALSE | | TRUE | FALSE || FALSE | TRUE | FALSE | TRUE | | TRUE | NULL || NULL | TRUE | | NULL* | +-------+-------++-------+-------+-------+-------+ | FALSE | TRUE || FALSE | TRUE | | TRUE | | FALSE | FALSE || FALSE | FALSE | TRUE | FALSE | | FALSE | NULL || FALSE | NULL | | NULL* | +-------+-------++-------+-------+-------+-------+ | NULL | TRUE || NULL | TRUE | | NULL* | | NULL | FALSE || FALSE*| NULL* | NULL* | NULL* | | NULL | NULL || NULL | NULL | | NULL* | +-------+-------++-------+-------+-------+-------+ | a | b || and | or | not | xor | +-------+-------++-------+-------+-------+-------+ * = Abweichung zu Python-Logik