13. Iteration II

Python kann nicht nur über Sequenzen iterieren, sondern auch nach logischen Bedingungen: while. Zu dieser Sorte Schleifen später mehr.

break und continue

Nicht immer ist der normale Kontrollfluss in einer Schleife bequem. Wenn in einer Schleife ein “Notfall” auftritt, wollen wir sie eventuell vorzeitig beenden: break.

>>> sum = 0
>>> for i in range(10):
...   sum = sum+i
...   if sum>20:
...     break
...
>>> sum, i
(21, 6)

Die Schleife ist also nicht ganz durchgelaufen (sonst wäre i gleich dem letzten Element der Sequenz, über die wir iterieren, hier also 9), sie wurde abgebrochen, als sum größer als 20 wurde.

Analog kann es vorkommen, dass ein Teil des Schleifenkörpers unter bestimmten Bedingungen nicht ausgeführt, die Iteration aber fortgesetzt werden soll: continue.

>>> for val in [1, 2, "drei", 4]:
...   if type(val)==type(""):
...     continue
...   print val,
...
1 2 4

Treffen wir bei der Bearbeitung unserer Sequenz also auf einen String, tun wir (hier) nichts und machen einfach beim nächsten Element der Sequenz weiter.

Häufig wird sowas eleganter durch direkte Selektion zu machen sein (“Wenn x ein String ist, dann mache”), es gibt aber durchaus Fälle, in denen ein continue die Intention klarer macht – es sagt so etwas wie “Oh, für diesen Fall bin ich nicht zuständig” oder “Oh, ausnahmsweise soll dieses Element gar nicht behandelt werden”. Aussagen dieser Art sind bei längeren Selektionsausdrücken nicht mehr unbedingt klar.

Die Sprachelemente break und continue können ein Programm leicht zu unverständlichen Monstren machen. Es gibt Stilpäpste, die ihren Einsatz komplett ablehnen (strikt notwendig sind sie offenbar nicht – könnt ihr euch Ersatzkonstrukte überlegen?). Meine Meinung ist, dass es genug Beispiele gibt, in denen speziell break die Abläufe deutlich klarer macht. Trotzdem solltet ihr euch vor einem Einsatz dieser “Ersatz-gotos” immer fragen, ob es nicht anders auch geht.

(Weiterführend:) Die Prüfung, ob etwas ein String ist, sollte man übrigens nicht mehr wie oben gezeigt machen, sondern über isinstance(val, basestring). Allerdings ist der Hintergrund dabei etwas komplexer (für später: wir prüfen auf die gemeinsame Basisklasse von Bytestrings und Unicode-Strings), so dass ich es hier beim Rezept bewenden lassen will.

else an Schleifen

Schleifen, die irgendetwas suchen und, wenn sie Erfolg haben, mit break oder return verlassen werden, können ein sinnvolles “Default-Verhalten” bekommen, indem man einen else-Zweig anfügt. Eine Funktion, die das erste Wort mit “en” am Ende ausgibt und wenigstens irgendwas sagt, wenn es nichts dergleichen gibt (stellt euch vor, ihr wolltet einen ganz schlechten und dummen Infinitivfinder schreiben):

def printFirstInfinitive(wordSeq):
  for word in wordSeq:
    if word.endswith("en"):
      print word
      break
  else:
    print "Keine Infinitive"

Das sieht dann so aus:

>>> printFirstInfinitive(
  ["Gehen", "laufen", "springen"])
Gehen
>>> printFirstInfinitive(
  ["rechts", "links", "mitte"])
Keine Infinitive

Generell sollte man sich bei jeder Schleife dieser Art fragen, was passiert, wenn die Selektionsbedingung nie wahr wird. Wenn es dabei zu einem Fehler kommen kann, ist eine else-Klausel vermutlich empfehlenswert, um für irgendeine Sorte von Notfallverhalten zu sorgen. In diesem Beispiel sollte das allerdings eher eine ordentliche Fehlermeldung oder – vermutlich besser – das Auslösen einer Exception sein. Wie sowas geht, werden wir noch sehen.

Übungen zu diesem Abschnitt

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

(1)

Schreibt die Funktion printFirstInfinitive so um, dass sie den eventuell gefundenen Infinitiv nicht druckt, sondern zurückgibt. Wird kein Infinitiv gefunden, soll der spezielle Wert None zurückgegeben werden.


Markus Demleitner

Copyright Notice