.. include:: markup.rst ****************** Kontrollstrukturen ****************** Kontrollstrukturen helfen den :mark:`Ablauf eines Programms zu steuern`. Man unterscheidet: * Fallunterscheidungen (``if``, ``else``) und * Schleifen (``for``, ``while``) Fallunterscheidungen ==================== If, elif, else -------------- Die einfachste Möglichkeit der Fallunterscheidung ist die ``if`` - Anweisung. Diese sieht folgendermaßen aus: :: if Bedingung : # Anweisungskopf Anweisung # | ... # | Anweisungskörper Anweisung # | Diese besteht aus einem * :mark:`Anweisungskopf`, der eine :mark:`Bedingung` enthält und einem * :mark:`Anweisungskörper` (Codeblock) welcher je nach Ergebnis der Bedingung ausgeführt wird. Anders gesagt :mark:`WENN` Bedingung erfüllt, dann mach, was im Anweisungskörper steht. Z.B: :: if x < 1 : print("x kleiner 1") .. note:: * Der Anweisungskopf endet mit einem ``:``. * Der Anweisungskörper ist :mark:`eingerückt`! * Die gleiche Einrückung, wie das ``if`` bedeutet die Anweisung ist :mark:`außerhalb` des Anweisungskörpers! Die Abbildung `if-Anweisung grafisch`_ zeigt diese als Flußdiagramm. .. _`if-Anweisung grafisch`: .. figure:: images/ifAnweisung.jpg :scale: 60 % :align: center if-Anweisung grafisch Möchte man eine :mark:`weitere` Bedingung prüfen (wenn die erste ``False`` war), verwendet man eine ``elif`` - Anweisung. :: if Bedingung1 : # Pruefe Bed 1 Anweisung # | ... # | wenn Bed 1 True Anweisung # | elif Bedingung2 : # Pruefe Bed 2 Anweisung # | ... # | wenn Bed 2 True Anweisung # | Beispiel: :: if x < 1: print("x kleiner 1") elif x == 1: print("x gleich 1") Soll eine Anweisung ausgeführt werden wenn :mark:`keine der beiden Bedingungen` greift, verwendet man eine ``else`` - Anweisung. :: if Bedingung1 : # Pruefe Bed 1 Anweisung # | ... # | wenn Bed 1 True Anweisung # | elif Bedingung2 : # Pruefe Bed 2 Anweisung # | ... # | wenn Bed 2 True Anweisung # | else : # Sonst Anweisung # | ... # | wenn Bed 1 und 2 False Anweisung # | Beispiel: :: if x < 1: print("x kleiner 1") elif x == 1: print("x gleich 1") else: print("x ist groesser 1") Mit dieser Art der Fallunterscheidung lassen sich auch ``switch`` \ ``case`` Kontrollstrukturen (wie in Java oder C++) realisieren. Beispiel (``kontroll_switch.py``): Die Abbildung `if-elif-else-Anweisung grafisch`_ zeigt diese als Flußdiagramm. .. _`if-elif-else-Anweisung grafisch`: .. figure:: images/ifElifElseAnweisung.jpg :scale: 70 % :align: center if-elif-else--Anweisung grafisch .. literalinclude:: src/kontroll_switch.py Die häufigste Verwendung sind ``if``-``else`` Konstrukte (WENN - dann - SONST): :: if Bedingung : # Pruefe Bed Anweisung # | ... # | wenn True Anweisung # | else : # Sonst Anweisung # | ... # | wenn Bed False Anweisung # | .. hint:: Wenn möglich ``if`` Schleifen immer mit ``else`` versehen! Somit erkennt man Programmierfehler leichter. Schleifen ========= For - Schleifen --------------- Eine for-Schleife ist eine :mark:`Zählschleife`. Die Anzahl der Schleifendurchläufe kann mit dem :mark:`Schleifenzähler` angegeben werden: :: for Variable in Objekt : # nimm aus Obj eine Var Anweisung # | ... # | mach was damit Anweisung # | Beispiel (``kontroll_for.py``): .. literalinclude:: src/kontroll_for.py Ausgabe: :: 0 1 2 Die ``range(..)`` Funktion liefert dabei einen Iterator der mit ``list(..)`` in eine Liste umgewandelt werden kann. Z.B. : :: In [1]: range(3) # gibt einen Iterator zurueck Out[1]: range(0, 3) In [2]: list( range(3) ) # wandelt den Iterator in eine Liste um Out[2]: [0, 1, 2] Diese Funktion kann man ganz allgemein verwendet werden: :: In [3]: list( range(1,10,2) ) Out[3]: [1, 3, 5, 7, 9] In [4]: liste=[1,3,5] Listen kann man auf 2 Arten durchlaufen: :: In [5]: for l in liste : ...: print(l) ...: 1 3 5 In [6]: for i in range(len(liste)) : ...: print(i, liste[i]) ...: 0 1 1 3 2 5 je nach dem ob man den Index ``i`` benötigt oder nicht. Dictionaries durchläuft man z.B. mit: :: In [7]: dic = {0:"a", 3:"b", 6:"c" } In [8]: for key in dic: ...: print(key, dic[key]) ...: 0 a 3 b 6 c Die Abbildung `for Schleife grafisch`_ zeigt diese als Flußdiagramm. .. _`for Schleife grafisch`: .. figure:: images/forSchleife.jpg :scale: 70 % :align: center for Schleife grafisch While - Schleifen ----------------- Diese führen Codeblock so lange aus, wie eine bestimmte :mark:`Bedingung erfüllt` ist. :: while Bedingung : # solange Bed True Anweisung # | ... # | mach was damit Anweisung # | Das Flussdiagramm sieht wie bei Abbildung `for Schleife grafisch`_ aus. Beispiel (``kontroll_while.py``): .. literalinclude:: src/kontroll_while.py Ausgabe: :: Raten Sie: 1234 Raten Sie: 1543 Raten Sie: 1337 Sie haben es geschafft! Im :mark:`Vergleich` zur ``for`` Schleife kennt man bei der ``while`` Schleife die Anzahl der Schleifendurchläufe nicht! .. note:: Die ``input`` Anweisung liest dabei Zeichen von der Python Shell ein welche mit ``int(..)`` in Zahlen umgewandelt werden. Mit ``ENTER`` bestätigt man diese Eingabe. .. warning:: While Schleifen sind gefährlich! Schlechte Programmierung kann zu :mark:`Endlosschleifen` führen. Dann hilft manchmal nur mehr ein :mark:`Programmabbruch` ... Vorzeitiger Abbruch eines Schleifendurchlaufs --------------------------------------------- Es gibt Möglichkeiten den Ablauf einer Schleife zu beeinflussen. * ``break`` Anweisung: beendet den :mark:`gesamten` Schleifendurchlauf, verläßt die Schleife. * ``continue`` Anweisung: beendet den :mark:`aktuellen` Schleifendurchlauf, startet den nächsten Durchlauf. Schematisch sieht dies so aus: :: while Bedingung : # <- ... # | if Bedingung1: # | springt nach oben continue # -- ... if Bedingung2: # break # -- ... # | springt nach unten ... # <- Beispiel (``kontroll_while_break_continue.py``): .. literalinclude:: src/kontroll_while_break_continue.py Ausgabe: :: Positive Zahl eingeben : 22 Zahl = 22 Positive Zahl eingeben : -3 Negative Zahlen nicht erlaubt! Positive Zahl eingeben : 6 Zahl = 6 Positive Zahl eingeben : 0 Skript wird beendet! Die pass Anweisung ================== Während der Entwicklung eines Programms kommt es vor, dass * eine Kontrollstruktur vorerst nur :mark:`teilweise implementiert` wird. * Der Anweisungskopf wird erstellt, es :mark:`fehlt` jedoch der :mark:`Anweisungskörper`. * Ein fehlender Anweisungskörper wäre aber ein Syntaxfehler. * :mark:`Abhilfe` schafft dabei die ``pass`` Anweisung. Beispiel: :: if x == 1: pass # wird später implementiert elif x == 2: print("x hat den Wert 2") else : print("Weder 1 noch 2.") .. Iteratoren ---------- Eine weitere Methoden :mark:`Sequenzen durchzulaufen` sind Iteratoren. Ein Beispiel sieht z.B. so aus: :: >>> a = [1,2,3] >>> i = iter(a) >>> i.next() 1 >>> i.next() 2 >>> i.next() 3 Übungsbeispiele ==================