Kontrollstrukturen und Ausnahmebehandlung


Operatoren

Bei der Auswertung mathematischer Ausdrücke gilt wie üblich die Reihenfolge „Punkt vor Strich“. Die Reihenfolge kann durch den Einsatz von runden Klammern beeinflusst werden (Gruppierung). Für die in Python üblichen Operatoren ist eine allgemein gültige „Rangfolge“ für die Auswertung festgelegt. In der folgenden Tabelle stehen die Operatoren mit der höchsten Priorität oben, gleichberechtigte Operatoren (die von links nach rechts ausgewertet werden) stehen in der gleichen Zeile.

Operator Bedeutung
() Gruppierung
x[], x.attribute Listenzugriff (siehe Listen ), Objekteigenschaft
** Potenz
+ und - Positives beziehungsweise negatives Vorzeichen einer Zahl
*, /, //, % Multiplikation, Division, Ganzzahl-Division, Rest (Modulo)
==, <=, <, !=, >=, > Wertevergleich (gleich, kleiner als oder gleich, kleiner als, ungleich, größer gleich, größer als)
is, is not, in, not in Identitätsvergleich, Test auf Mengenzugehörigkeit
not Logisches Nicht
and Logisches Und
or Logisches Oder

In Python muss zwischen dem Wertevergleich == und der Identität von Objekten unterschieden werden. So ist liefert 3/2 == 1.5 eine wahre Aussage (True), da die Zahlenwerte übereinstimmen. Dagegen liefert 3/2 is 1.5 eine falsche Aussage (False); ein mathematischer Ausdruck ist logisch nicht dasselbe wie eine Zahl. Eine Ausnahme bildet der Potenz-Operator **; wenn mehrere Potenzen in einem Ausdruck auftreten, werden diese von rechts nach links ausgewertet. Es gilt: 2**2**3 == 2**8 == 256, was mathematisch gesehen eigentlich nicht zulässig wäre. Eine andere Auswertungsreihenfolge ist doch Klammerung (Gruppierung) möglich: (2**2)**3 == 4**3 == 64.

Kombinierte Zuweisungsoperatoren

Neben dem gewöhnlichen Zuweisungsoperator (Gleichheitszeichen) = gibt es bei Programmiersprachen of weitere Operatoren. In Python existieren die folgenden Operatoren, die eine Kombination aus Operation und Zuweisung bestehen; die Variable wird dabei also um den jeweiligen Wert verändert.

OperatorBedeutung
+= Erhöhung der links stehenden Variable um Wert auf der rechten Seite
-= Erniedrigung der links stehenden Variable um Wert auf der rechten Seite
*= Multiplikation der links stehenden Variable mit Wert auf der rechten Seite
/= Division der links stehenden Variable durch Wert auf der rechten Seite
//= Ganzzahlige Division der links stehenden Variable durch Wert auf der rechten Seite
%= Rest bei ganzzahliger Division der links stehenden Variable durch Wert auf der rechten Seite
**= Potenzieren einer Variable mit Wert auf der rechten Seite

So kann die Potenzierung einer Variablen statt x = x**3 durch x**=3 ersetzt werden. Eine einfache Inkrementierung ist durch i += 1 und Dekrementierung durch i -= 1 möglich. Für Zeichenketten existieren nach dem gleichen Prinzip die Operatoren str0 += str1+= (str1 Zeichenkette anhängen) und str0 *= 2 (str0 zweimal anhängen).

i = 1
j = 7
str0 = "String0"
str1 = 'String1'
i += 1
j *= 7
str0 += str1
print(i, j, str0)
print()

i **= 3
j //= i
str0 *= 3
print(i, j, str0)

Kombinierte Vergleichsoperatoren

Eine weitere Besonderheit in Python liegt darin, dass mehrere Vergleichsoperatoren unmittelbar miteinander kombiniert werden können; beispielsweise kann wie in der Mathematik 1 < 2 < 3 geschrieben werden. Die einzelnen Teilausdrücke muss man sich dabei mit dem Operator and verbunden vorstellen; der Ausdruck ist genau dann wahr, wenn gilt 1 < 2 and 2 < 3. Die „Verkettungsregel“ gilt für alle Vergleichsoperatoren, auch wenn das Ergebnis nicht immer mit der eigenen Erwartung übereinstimmen muss. Beispielsweise könnte man im Fall von 1 == 2 < 3 das Ergebnis True erwarten, wenn man sich die gleichwertigen Operato- ren von links nach rechts ausgewertet denkt, denn 1 == 2 ist False (äquivalent zu 0) und daher False < 3, also True. Die Aussage liefert in Python jedoch False als Ergebnis, denn sie wird als 1 == 2 and 2 < 3 interpretiert. Zwei mit and verknüpfte Aussagen ergeben nur dann ein wahres Ergebnis, wenn beide Aussagen wahr sind.

i = 1
j = 2
k = j + 1
Bool0 = i == j < k
Bool1 = (i == j < k) # übersichtlichere Schreibweise
print(Bool0,Bool1)
print((i == j) and (j < k)) 

Im Zweifelsfall können die einzelnen Teilaussagen jederzeit mit Hilfe von runden Klammern gruppiert werden, um eine ungewollte Auswertungsreihenfolge zu vermeiden.

Bedingte Wertzuweisung

In einigen Programmiersprachen, wie beispielsweise C, gibt es „ternäre“ Operatoren, die drei Argumente erwarten. In Python gilt die Syntax x = a if condition else b. Zunächst die Bedingung condition geprüft. Ist diese eine wahre Aussage, also True, so wird der Variablen x der Wert a zugewiesen, andernfalls der Wert b. Die bedingten Wertzuweisungen haben die niedrigste Priorität bei der Abarbeitung einer Zuweisung.

import math# für sqrt
a = 17
b = 71
x = a if math.sqrt(b) < 8 else b
print(x)
x = ( a if math.sqrt(b) < 9 else b )
print(x)

X = [1.5, 2.3, 4.4, 5.4, 'Johnny', 1.5, 5.1, 'Mauser']     # Original list
# Alle Nicht-Strings in eine neue Liste
X_non_str = [i for i in X if not isinstance(i, str)]
# Alle Strings in eine neue Liste
X_only_str = [i for i in X if isinstance(i, str)]   

print("Liste ohne Strings:",X_non_str)
print("Liste nur Strings: ",X_only_str)

# Ersetze alle Strings in X durch "Franz"
X_str_changed = ["Franz" if isinstance(i, str) else i for i in X]  
print("Liste mit geänderten Strings:",X_str_changed)

if–Fallunterscheidungen

Mit Hilfe von if-Abfragen ist es möglich, Code-Teile nur unter bestimmten Bedingun- gen ablaufen zu lassen. Ist die if-Bedingung wahr, so wird der anschließende, mit einer Einrückung hervorgehobene Code ausgeführt.

# Hinweis
if bedingung:
    ... Anweisung ...
    ... Anweisung ...
    ...   ...     ...

Optional können nach einem if-Block mittels elif eine oder mehrere zusätzliche Be- dingungen formuliert werden, die jedoch nur dann untersucht werden, wenn die erste if-Bedingung falsch ist. Schließlich kann auch eine else-Bedingung angegeben werden, die genau dann ausgeführt wird, wenn die vorherige Bedingung (beziehungsweise alle vor- herigen Bedingungen bei Verwendung eines elif-Blocks) nicht zutreffen. Insgesamt kann eine Fallunterscheidung beispielsweise folgenden Aufbau haben:

# Hinweis
if bedingung_1:
    ... Anweisung(en)
    
elif bedingung_2:
    ... Anweisung(en)

elif bedingung_n:
    ... Anweisung(en)

else:
    ... Anweisung(en)

import datetime
print(datetime.datetime.now())
f = str(datetime.datetime.now()).split()
print(f)
f = f[0].split("-")
print(f)
today = datetime.date(day=int(f[2]), month=int(f[1]), year=int(f[0])).weekday()
print(today)
if today == 0:
  wTag = "Montag"
elif today == 1:
  wTag = "Dienstag"
elif today == 2:
  wTag = "Mittwoch" 
elif today == 3:
  wTag = "Donnerstag" 
elif today == 4:
  wTag = "Freitag" 
elif today == 5:
  wTag = "Sonnabend" 
else:
  wTag = "Sonntag"
print("Heute ist",wTag) 

# Einfachere Variante
wTage = ['Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Sonnabend','Sonntag']
print("Heute ist",wTage[today])

if-elif-else in Python

a = float(input('First: '))
b = float(input('Second: '))
op = input('Operation (sum/sub/mul/div): ')

if op == 'sum':
    print(f'a + b = {a+b}')
elif op == 'sub':
    print(f'a - b = {a-b}')
elif op == 'mul':
    print(f'a * b = {a*b}')
elif op == 'div':
    print(f'a / b = {a/b}')
else:
    print('Invalid Operation!')

Ab Python 3.10 existiert der sogenannte match-case, welcher äquivalent zum switch-case ist:

a = float(input('First: '))
b = float(input('Second: '))
op = input('Operation (sum/sub/mul/div): ')

match op:
    case 'sum':
        print(f'a + b = {a+b}')
    case 'sub':
        print(f'a - b = {a-b}')
    case 'mul':
        print(f'a * b = {a*b}')
    case 'div':
        print(f'a / b = {a/b}')
    case _:
        print('Invalid Operation!')

Im Gegensatz zu anderen Prpgrammiersprachen unterstützt Python zum einen die Abfrage auf die Existenz eines Elements innerhalb einer Menge und zum anderen die Abfrage auf größer und kleiner ohne eine and-Bedingung nutzen zu müssen:

grade = 90
print("grade=",grade)
if 0 <= grade <= 100:
  print("0 ≤ grade ≤ 100 ist wahr")
else:
  print("0 ≤ grade ≤ 100 ist falsch")
if grade in range(0,101):
  print("grade in [0;100] ist wahr")
else:
  print("grade in [0;100] ist falsch")

Es folgt ein etwas längeres Beispiel mit mehreren if-Abfragen, welches nicht Online ausgeführt werden kann, da es interaktive Aktionen erfordert. Kopieren Sie es und lassen es in Ihrem Editor laufen. Sie können es aber auch momentan übergehen; es soll hier lediglich einen Überblick geben.

# Hinweis
"""
grade_statistics - Grade statistics
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Prompt user for grades (0-100 with input validation) and compute the sum, average,
  minimum, and print the horizontal histogram.
An example to illustrate basic Python syntaxes and constructs, such as block indentation,
  conditional, for-loop, while-loop, input/output, list and function.
"""

# Define all the functions before using them
def my_sum(lst):
    """Return the sum of the given list."""
    sum = 0
    for item in lst: sum += item
    return sum
 
def my_average(lst):
    """Return the average of the given list."""
    return my_sum(lst)/len(lst)   # float
 
def my_min(lst):
    """Return the minimum of the given lst."""
    min = lst[0]
    for item in lst:
        if item < min:   # Parentheses () not needed for test
            min = item
    return min
 
def print_histogram(lst):
    """Print the horizontal histogram."""
    # Create a list of 10 bins to hold grades of 0-9, 10-19, ..., 90-100.
    # bins[0] to bins[8] has 10 items, but bins[9] has 11 items.
    bins = [0]*10   # Use repetition operator (*) to create a list of 10 zeros
 
    # Populate the histogram bins from the grades in the given lst.
    for grade in lst:
        if grade == 100:  # Special case
            bins[9] += 1
        else:
            bins[grade//10] += 1  # Use // for integer divide to get a truncated int
 
    # Print histogram
    # 2D pattern: rows are bins, columns are value of that particular bin in stars
    for row in range(len(bins)):  # [0, 1, 2, ..., len(bins)-1]
        # Print row header
        if row == 9:  # Special case
            print('{:3d}-{:<3d}: '.format(90, 100), end='')  # Formatted output (new style), no newline
        else:
            print('{:3d}-{:<3d}: '.format(row*10, row*10+9), end='')  # Formatted output, no newline
 
        # Print one star per count
        for col in range(bins[row]): print('*', end='')  # no newline
        print()  # newline
        # Alternatively, use str's repetition operator (*) to create the output string
        #print('*'*bins[row])

# Create an initial empty list for grades to receive from input
grade_list = []
# Read grades with input validation
grade = int(input('Enter a grade between 0 and 100 (or -1 to end): '))
while grade != -1:
    if 0 <= grade <= 100:  # Python support this comparison syntax
        grade_list.append(grade)
    else:
        print('invalid grade, try again...')
    grade = int(input('Enter a grade between 0 and 100 (or -1 to end): '))

# Call functions and print results
print('---------------')
print('The list is:', grade_list)
print('The minimum is:', my_min(grade_list))
print('The minimum using built-in function is:', min(grade_list))  # Using built-in function min()
print('The sum is:', my_sum(grade_list))
print('The sum using built-in function is:', sum(grade_list))   # Using built-in function sum()
print('The average is: %.2f' % my_average(grade_list))          # Formatted output (old style)
print('The average is: {:.2f}'.format(my_average(grade_list)))  # Formatted output (new style)
print('---------------')
print_histogram(grade_list)

Bei der Untersuchung der einzelnen Bedingungen gelten die üblichen Regeln für Boolsche Werte:

  • Werden zwei Bedingungen mit and verknüpft, so ist das Ergebnis genau dann wahr, wenn beide Bedingungen erfüllt sind.
  • Werden zwei Bedingungen mit or verknüpft, so ist das Ergebnis dann wahr, wenn mindestens eine der beiden Bedingungen (oder beide zugleich) erfüllt sind.
  • Der Operator not kehrt den Wahrheitswert einer Bedingung um, eine wahre Bedin- gung liefert also False als Ergebnis, eine falsche Bedingung True.

    Da die logischen Operatoren eine geringe Priorität haben als die Vergleichsoperatoren, können mehrere Vergleiche auch ohne Klammern mittels and beziehungsweise or verbunden werden. Insbesondere Anfängern wird aber geraten mit Klammern zu arbeiten, um den Vergleich auch optisch eindeutig erscheinen zu lassen.

    var_1 = (578 + 94) / 12
    var_2 = (1728) / 144
    
    if var_1 > var_2:
        print("var_1 is larger als var_2.")
    elif var_1 < var_2:
        print("var_1 is smaller als var_2.")
    else:
        print("var_1 is equal var_2.")

    Beinhaltet eine Variable einen Listentyp, beispielsweise ein Tupel, einen String, ein Dictionary oder einen Set, so ergibt if var den Wert False, falls die Länge der Liste gleich Null ist und True, falls die jeweilige Liste mindestens ein Element beinhaltet.

    Ausnahmebehandlung

    Die Beispiele gibt es hier.


    Nächste Kurseinheit: 03 Schleifen