11. Logik und Selektion

Logische Ausdrücke

Die Operatoren logischer Ausdrücken verknüpfen ihre Operanden so, dass sich entweder wahr oder falsch ergibt; Vergleiche verhalten sich so:

>>> s = "bla"        >>> 5 <= 4
>>> "bla" == s       0
1                    >>> s != 5
>>> "aba" > s        1
0

Logisch falsch sind in Python die 0 (und der leere String "" sowie der spezielle Wert None und etliche andere “leere” Datenstrukturen) , alles andere zählt als wahr.

Ab Python 2.3 gibt es extra für Logik einen neuen Typ: bool. Das Beispiel oben sieht dann so aus:

>>> s = "bla"         >>> 5 <= 4
>>> "bla" == s        False
True                  >>> s != 5
>>> "aba" > s         True
False

Die Details sind etwas jenseits unseres gegenwärtigen Horizonts, wie auch die Frage, warum das wohl gemacht wurde. So oder so, abgesehen von einigen interaktiven Antworten ändert sich dadurch am hier dargestellten so gut wie nichts, zumal die neu vordefinierten Namen True und False für praktische alle Zwecke 1 und 0 sind. Das erlaubt auch Perversionen wie

>>> 7+True
8

– aber sowas will man natürlich wirklich nicht machen.

Weitere Operatoren erlauben die Verknüpfung logischer Werte:

>>> 5==s or "bla"==s
1
>>> 5==s and "bla"==s
0
>>> not 5==s
1

Selektion

Oft muss ein Programm in Abhängigkeit von Bedingungen verschiedene Dinge tun. In Python gibt es dafür if:

>>> n = 5                    >>> s = raw_input("Name? ")
>>> if n>7:                  Name? ich
...   print n, "> 7"         >>> if s=="ich":
... else:                    ...   print "Sehr witzig"
...   print n, "< 8"         ...
...                          Sehr witzig
5 < 8

Wieder kommt nach der if- oder der else-Zeile ein Doppelpunkt, die Zeilen, die in Abhängigkeit von der Bedingung ausgeführt werden sollen sind eingerückt.

Wir haben es hier also wieder – wie schon bei den Funktionskörpern – mit einem compound statement zu tun. Die Grundidee ist, dass der Rechner wissen muss, bis wohin eine Funktion oder ein Zweig einer Selektion geht (im Nebensatzbild also: Was alles zum Nebensatz gehört). Offensichtlich ist das wichtig, wenn wir eine Sequenz in einem Selektionszweig haben, wie folgendes Beispiel illustrieren mag:

“Wenn es sonnig ist, hole die Strandmatte und lege dich auf die Neckarwiese”

In der Natursprache wird die Entscheidung, ob die zweite Aufforderung der ersten beigeordnet (in Sequenz mit “holen”) ist oder unabhängig steht (in Sequenz mit “Wenn”), der Semantik oder der Pragmatik überlassen. Computer können das in der Regel nicht, und so brauchen Computersprachen syntaktische Merkmale, um zwischen den beiden Alternativen

Wenn es sonnig ist

hole die Strandmatte
lege dich auf die Neckarwiese

und

Wenn es sonnig ist

hole die Strandmatte

lege dich auf die Neckarwiese

zu entscheiden – und eben das tut die Syntax der compound statements. Dass diese in Python durch Einrückung markiert werden, ist eher ungewöhnlich. Viele Sprachen, vor allem die von C abgeleiteten, verwenden lieber geschweifte Klammern, in Pascal gibt es die Schlüsselwörter begin und end, übliche Unix-Shells machen das eher ad hoc und schließen ein if-statement mit fi, ein case-statement mit esac und haben für Funktionskörper geschweifte Klammern.

Will man, dass Programme für Menschen lesbar sind, wird man aber auch in diesen Sprachen einrücken, weil es für Menschen einfacher ist, einer Einrückung zu folgen als Klammern zu zählen. Guido van Rossum, Pythons Spiritus Rector, dachte sich, dass der Rechner auch nicht (viel) schlechter als Menschen darin ist, Einrückungen zu erkennen und beschloss, dann auf eine separate Kennzeichnung der Struktur extra für den Rechner gleich zu verzichten. Wie gut diese Idee war, werden wir in Programmieren II sehen, wenn es um das “dangling else problem” geht.

Vor allem an C angelehnte Sprachen haben ein weiteres Konstrukt zur Selektion, das nicht-bool’sche Entscheidungen (also solche, in denen die Bedingung nicht nur zwei Werte annehmen kann) behandelt. Das wären etwa Dinge wie “Wenn die Taste a gedrückt wurde, öffne die Tür, wenn die Taste b gedrückt wurde, schließe sie, und wenn q gedrückt wurde, verlasse das Programm” oder so. Solche Konstrukte werden gern mit Schlüsselwörtern wie switch oder case gemacht.

Python hat kein switch-Statement, das eine mehrfache Selektion erlaubt (“Wenn A, dann x, wenn B, dann y, wenn C, dann z usf.”, wobei A, B, C,ausschließend sind – andere Sprachen haben dafür eigene Syntax). Ersatz durch elif-Ketten:

>>> def printRelation(x, y):      >>> printRelation(4, 3)
...   if x<y:                     4 > 3
...     print x, "<", y           >>> printRelation(5, 5)
...   elif x>y:                   5 == 5
...     print x, ">", y
...   else:
...     print x, "==", y
...

(Weiterführend): Häufig wird man Konstruktionen dieser Art auch durch andere, meist elegantere, Sprachmittel realisieren – so können beispielsweise die uns bald begegnenden Dictionaries auch Funktionen als Werte haben und auf diese Weise bestimmte Anwendungen abdecken. Wer aber an einem switch-ähnlichen Konstrukt für Python hängt, kann sich dieses Rezept ansehen – was dort passiert, könnt ihr allerdings erst später verstehen.

Übungen zu diesem Abschnitt

Ihr solltet euch wenigstens an den rötlich unterlegten Aufgaben versuchen

(1)

Überlegt euch, wie ein Satz wie “Wenn die Sonne scheint, hole ich meine Strandmatte, und wenn auf der Neckarwiese Platz ist, lege ich mich dorthin, sonst fahre ich nach Ilvesheim” interpretiert werden kann und schreibt die zugehörigen “Programme” nach dem Vorbild im Skript.

(2)

Definiert analog zur Funktion printRelation eine, die je nach Vorzeichen einer Zahl Auskunft gibt, ob sie positiv, negativ oder Null ist. Definiert diese Funktion auch mal so, dass sie die Auskunft nicht direkt ausgibt, sondern in einem String an die aufrufende Funktion zurückgibt.

(3)

Lasst euch “Wahrheitstafeln” der logischen Operatoren and, or und not ausgeben, etwa per

print 0, 0, 0 and 0
print 1, 0, 1 and 0

und so fort. Wie man solch lästigen Kram wie die dauernde Tipperei dem Rechner überlässt, sehen wir auf der nächsten Folie.


Markus Demleitner

Copyright Notice