Inhaltsverzeichnis[Anzeigen]

Kontrollfluss

Bedingungen

  • die allgemeine Form der bedingten Auswahlanweisung besitzt folgende Form:
if expression:

statements
elif expression:
statements
elif expression:
statements
...

else:
statements
  • die Angabe der elif beziehungsweise else Anweisung ist optional
  • TIP Python kennt keine case Anweisung, denn sie stellen für objektorientierte Sprachen keinen guten Stildar
    • mittels Dictionaries und anonymen Funktionen sind case Strukturen schnell simuliert:
select={

"+": (lambda x,y: x+y),

"-": (lambda x,y: x-y),
"*": (lambda x,y: x*y),

"/": (lambda x,y: x/y) }


result= select["+"](3,4)
  • REFACTOR übersetze die if Anweisungen in eine Dictionary Abfrage; ALERT! else Anweisung
def choiceIf(choice):    
if choice == 1:
val= "red"

elif choice == 2:
val= "green"
elif choice == 3:

val= "blue"
else:
val="white"
return val
  • da leere Anweisungen syntaktisch falsch sind, muß hier explizit das Schlüsselwort pass verwendet werden
if expression:

pass
else:
statements
  • TIP dies gilt auch für Funktionen und Methoden

Schleifen

  • beide Schleifentypen - while and for - können mit einer optional else Anweisung formuliert werden
  • der else Programmblock wird genau dann ausgeführt, wenn die Schleifeniteration vollständig ausgeführt wurde 

while

  • die while Schleife besitzt folgende Form
while expression:
statements
else:
statements
 
  • ALERT! Python erlaubt keine Zuweisungen an Stellen, in denen Ausdrücke erwartet werden
  • folgender gültige C Ausdruck ist daher nicht zulässig
  • nextLine soll die nächste Zeile liefern
while( line= nextLine() ){ process(line); } 
  • Das entsprechende Python-Idiom lautet:
for line in nextLine(): process(line) 

 

for

  • die for Schleife besitzt folgende Form, wobei i über die Sequenz s iteriert
for i in s:

statements
else:
statements
  • mittels break und continuekann der Schleifendurchlauf manipuliert werden
    • continue beendet die aktuelle Schleife und fährt gegebenfalls mit dem nächsten Schleifendurchlauf weiter
    • break beendet die while bzw. for Schleife
  • Python kennt keine Schleife, bei der am Ende des Schleifendurchlaufs die Bedingung geprüft wird
  • REFACTORIteriere über folgende Sequenzen und gibt sie mittels print aus
    • range(-10,10)
    • ["red","green","blue"]
    • "TestString"
    • [(1,"eins"),(2,"zwei"),(3,"drei"),(4,"vier")]
      • gib die Tupels
      • gib den ersten Wert des Tupels aus
    • ALERT!{1:"eins",2:"zwei",3:"drei",4:"vier"}
      • gib die Items
      • gib jeweils nur die keys und values aus
    • HAND open("/etc/passwd") und
      urllib.urlopen("http://www.python.org")

Ausnahmen - Exceptions

Integraler Bestandteil

  • bei syntaktische Fehlern wirft der Pythoninterpreter eine Ausnahme
  • ein paar verschiedene Ausnahmen
    Sind die Ausnahmemeldungen intuitiv?
>>> 1/0
Traceback (most recent call last):
File "<stdin>", line 1, in ?

ZeroDivisionError: integer division or modulo by zero
>>> d={]
File "<stdin>", line 1

d={]
^
SyntaxError: invalid syntax
>>> d={}
>>> d["gibtsNicht"]

Traceback (most recent call last):
File "<stdin>", line 1, in ?

KeyError: 'gibtsNicht'
>>> arr=[]
>>> arr[1]
Traceback (most recent call last):

File "<stdin>", line 1, in ?
IndexError: list index out of range

>>> import Bibilothek
Traceback (most recent call last):
File "<stdin>", line 1, in ?

ImportError: No module named Bibilothek
>>> 3+"string"
Traceback (most recent call last):

File "<stdin>", line 1, in ?
TypeError: unsupported operand type(s) for +: 'int' and 'str'
  • Python besitzt eine differenzierte built-in Ausnahmenhierachie:

    Ausnahmenhierachie
  • fängt man die Ausnahme durch einen Ausnahmebehandlung nicht ab, so passiert folgendes:
    1. die Ausnahme wird bis zum Mainprogramm weiterpropagiert
    2. im Mainprogramm wird der default exception handler aufgerufen
    3. der default exception handler schreibt eine Fehlermeldung, die den Typ der Ausnahme und den stack trace (die Liste der aktiven Zeilen und Funktionen, als die Ausnahme geworfen wurde) enthält
    4. der default exception handler beendet (terminates) das Programm
  • MOVED TO... Exceptions brechen aus dem normalen Kontrollfluß aus

Aspekte der Ausnahmebehandlung

fangen mit try/except/else

Beispiele
  • eine Ausnahme zu fangen in seiner einfachsten Form:
>>> try:
... 7/0
... except:

... print "Kein Fehler!"
...
Kein Fehler!
  • es geht auch spezieller:
>>> try:
... 7/0
... except ZeroDivisionError:

... print "Kein Fehler"
...
Kein Fehler
  • mit kleinen Überraschungen
>>> try:
... 7/0
... except StandardError:

... print "Zu allgemein"
... except ZeroDivisionError:
... print "Toter Code"

...
Zu allgemein
  • die except Handler werden sukzessive abgearbeitet
  • TIP der erste exception handler, der zutrifft wird benützt
    • MOVED TO... first match for best match
    • MOVED TO... die exception handler sollten vom speziellen zum allgemeinen definiert werden
  • optional kann noch ein abschließendes else angegeben werden, das genau dann prozessiert wird, wenn keine Ausnahme auftrat
>>> try:
... 7/1
... except:

... pass
... else:
... print "keine Ausnahme"
...

7
keine Ausnahme
  • falls die Ausnahme nicht gefangen werden konnte, führt dies in der Regel zum Programmabruch
>>> try:

... 7/0
... except IndexError:
... pass

...
Traceback (most recent call last):
File "<stdin>", line 2, in ?

ZeroDivisionError: integer division or modulo by zero
  • HAND mittels reguläre expressions kann geprüft werden, ob ein String einer gültigen Zahl entspricht
def is_a_number(x):
import re
num_re = re.compile(r'^[-+]?([0-9]+\.?[0-9]*|\.[0-9]+)([eE][-+]?[0-9]+)?$')

matchObject = num_re.match(str(x))

if matchObject:
return True
else:
return False
  • dies geht deutlich einfacher mit Exceptions
    MOVED TO... schreibe eine Funktion mit der gleichen Funktionalität
Syntax
  • die Ausnahmebehandlung kann leicht komplex werden
try:
<Anweisungen> # wird zuerst ausgeführt
except <name1>:
<Anweisungen> # wird ausgeführt, falls eine Ausnahme vom Type name1 geworfen wurde

except <name2>,<Daten>:
<Anweisungen> # wird ausgeführt, falls Ausnahme name2 geworfen wurde, erhalte dabei zusätzlich Daten
except (name3,name4):

<Anweisungen> # wird ausgeführt, falls eine Ausnahme vom Typ name3 oder name3 geworfen wurde
except:
<Anweisungen> # fange die restlichen Ausnahmen auf, und führe die Anweisungen aus
else:
<Anweisungen> # wird ausgeführt, falls der try Block keine Ausnahme warf
 
  • HANDAnnahme:
    • in try werden jeweils Ausnahmen vom Typ name1, name2, eine nicht aufgezählt Ausnahme und keine Ausnahme geworfen
    • dann kommt es zu folgendem Kontrollfluß nach dem try Block:
      • name1:
        • try MOVED TO... except <name1>
      • name2:
        • try MOVED TO... except <name1> MOVED TO... except <name2>, <Daten>
      • nicht aufgezähler Typ:
        • try MOVED TO... except <name1> MOVED TO... except <name2>, <Daten> MOVED TO... except (name3,name4) MOVED TO... except
      • keine Exception:
        • try MOVED TO... else
  • Exceptions verhalten sich Sprunganweisungen (goto) deutlich ähnlicher als Funktionsaufrufen,
>>> try:
... 7/0
... print "Ignoriere die Zeile"

... except:
... print "Ignoriere den Fehler"
...
Ignoriere den Fehler

denn ein Funktionsaufruf würde nach gefangener Exception

print "Ignoriere die Zeile" 


prozessieren

aufräumen mit try/finally

  • häufig kommt es vor, daß im try Block eine Ressource (Datei,Socket,Lock,...) gebunden wird, die natürlich wieder freigegeben werden sollte
    MOVED TO... daß hätte aber zu Folge, daß in jedem exception handler und im abschließenden else Block die Ressource wieder freigeben werden müsste ( vgl.Syntaxbeispiel )- ein mühsames und fehlerträchtiges Unterfangen
  • aus diesem Grund bietet Python ein weiteres Konzept an, um mit Ausnahmebehandlungen umzugehen:
try:
lockARessource()
finally:
releaseTheRessource()
  • unabhängig davon, ob eine Exception auftrat, wird der finally Block abgearbeitet
  • durch die try Anweisung wird der Kontrollfluß immer zum finally Block gelenkt
  • ALERT! die beiden Konzepte try/except/else und try/finally können einschließlich Python 2.4 nur exclusive verwendet werden
  • falls eine Ausnahme auftrat, wird diese nach dem Prozessieren des finally Block wieder geworfen
>>> def lockARessource(): raise IndexError

...
>>> try:
... try:
... lockARessource()
... finally:

... print "Räume auf"
... except IndexError:
... print "Error"

...
Räume auf
Error

werfen mit raise/assert

  • bisher war wir nur in der passiven Situation: eine Exception trat auf und wir reagierten mit except/else oder finally darauf
  • mittels raise ist es möglich, eine Exception explizit zu werfen
  • folgende Variationen stehen zur Verfügung
raise <name>         # wirf explizt eine Exception
raise <name>,<data> # übergibt zusätzlich Daten

raise # wirf die aktuelle Exception weiter

Beispiele

  • wirf eine Exception
>>> def raiseError(): raise IndexError

>>> try:
... raiseError()
... except IndexError:
... print "Mein Index Error"

...
Mein Index Error
  • Datenübergabe und Exceptions weiterwerfen ( rethrow )
def raiseError() : raise IndexError,"Ich werde wieder geworfen"
>>> try:

... raiseError()
... except IndexError,data:
... print data

... raise
...
Ich werde wieder geworfen
Traceback (most recent call last):
File "<stdin>", line 2, in ?

File "<stdin>", line 1, in raiseError

IndexError: Ich werde wieder geworfen
assert
  • eine Sonderform unter den Exceptions nimmt die assertAnweisung in doppelter Hinsicht ein
    1. ihr werfen ist an eine Bedingung geküpft
    2. sie wird explizit durch das Aufrufen des Python Interpreters mit Optimierung -O" unterbunden
  • die Syntax des Aufrufes ist
assert <test>,<data> 

wobei dies äquivalent zu folgendem Ausdruck ist

if __debug__:
if not <test>:

raise AssertionError, <data>
  • TIP durch das explizite Ausschalten der Exceptions eignen sich die Assertion für die Entwicklung des Codes, während die restlichen Exceptions die Fehler im Produktivcode fokusieren

Anhänge:
Diese Datei herunterladen (kontrollfluss.py)kontrollfluss.py[ ]0.3 KB

Mentoring

Stay Informed about my Mentoring

 

Rezensionen

Tutorial

Besucher

Heute 1854

Gestern 3725

Woche 7655

Monat 34972

Insgesamt 3887686

Aktuell sind 600 Gäste und keine Mitglieder online

Kubik-Rubik Joomla! Extensions

Abonniere den Newsletter (+ pdf Päckchen)

Beiträge-Archiv

Sourcecode

Neuste Kommentare