next up previous
Next: Module und mehr Up: python Previous: Einführung

Unterabschnitte

Kontrollstrukturen

if, for, while, def

Wie gesagt ist die Syntax in Python sehr einfach. Bei Kontrollstrukturen wie if, for und while wird die Bedingung nicht in Klammern gesetzt, sondern einfach danach hingeschrieben, und der folgende Block wird nach einem Doppelpunkt eingerückt begonnen. In den Bedingungen sind, anders als in C, keine Zuweisungen möglich, der Lesbarkeit wegen.

Für Wenn-Dann-Abfragen braucht man in Python die Vokabeln if, elif und else. Die Syntax ist wie folgt:

        if <Bedingung>:
          #tu was...
        elif <andere Bedingung>:
          #tu was anderes
        else:
          #ansonsten mach was

Da Python interpretiert ist, gibt es keinen Ausdruck für switch-case. Aber stattdessen kann man manchmal ein Dictionary einsetzen, wo man Funktionen oder Lambda-Ausdrücke unter Zahlen oder Strings ablegt und mit apply anwendet. Beispiel:

a = 3
b = 5
c = 7
if a < b < c:
    print a, b, c, "geordnet!"

if (a * b) < c:
    print "Produkt von a und b > c!"
elif (a * b) == c:
    print "c = a * b!"
else:
    print "c < a * b!"


weekdays = {'Monday' : 'Schoene Woche!',
            'Tuesday' : 'Viel Spass bei Robotik!',
            'Wednesday' : 'Lern mal neue Sprachen!',
            'Thursday' : 'Schon einen Roboter gebaut?',
            'Friday' : 'Schoenes Wochenende!'}

day = 'Tuesday'
print weekdays[day]
            
        
    
Ausgabe:
 
        3 5 7 geordnet!
        c < a * b!
        Viel Spass bei Robotik!

Bei Schleifen gibt es die aus anderen Sprachen bekannten Ausdrücke break und continue, um aus einer Schleife auszusteigen bzw. mit dem nächsten Wert weiterzumachen. Auch die leere Anweisung pass, die dem Semikolon in C entspricht, kann man in diesem Zusammenhang erwähnen3. Nach allen Schleifen kann man mit else einen Block beginnen, der am Ende der Schleife ausgeführt wird, falls diese nicht mit break verlassen wurde.

Die Syntax für while-Schleifen ist folgendermaßen:

        while <Bedingung>:
          #Schleife
          #break oder continue?
        else:
          #falls kein break, mach noch was

Beispiel:

file = open('while.py')
while 1:
    line = file.readline()
    if not line:
        break
    print line[:-1]

print '------------------------------'

y = 101
x = y / 2
while x > 1:
    if y % x == 0:
        print y, 'has factor', x
        break
    x = x - 1
else:
    print y, 'is prime'
Ausgabe:
 
        file = open('while.py')
        while 1:
          line = file.readline()
          if not line:
            break
          print line[:-1]

        print '------------------------------'

        y = 101
        x = y / 2
        while x > 1:
          if y % x == 0:
print y, 'has factor', x
            break
          x = x - 1
        else:
          print y, 'is prime'
        ------------------------------
        101 is prime

for-Schleifen iterieren über einer Sequenz, also z. B. einem Tupel, einer Liste oder einem String. Wenn man über einer Liste von Zahlen iterieren möchte, ist die Funktion range() interessant, die bei einem Parameter eine Liste von Null bis zum Parameter, bei 2 Parametern vom ersten bis zum zweiten zurückgibt. Übergibt man 3 Parameter, wird vom ersten zum zweiten Parameter gezählt, das Inkrement wird durch den dritten Parameter bestimmt. range(10) ist also das gleiche wie range(0, 10) oder range(0, 10, 1). xrange() funktioniert genauso, liefert aber ein Tupel zurück.

for-Schleifen haben folgende Syntax:

       for <variable> in <sequenz>:
         #mach was mit <variable> oder auch ohne
       else:
         #falls nix break

Beispiel:

for i in range(10):
    print i, '...'
print 'and liftoff!'

print '2 loops:'
items = ['spam', 3.14, 911, (123, 456), 'Ni!']
test = [1.44, 'Ni!', (123, 456)]
for key in test:
    for item in items:
        if item == key:
            print key, 'was found'
            break
    else:
        print key, 'not found'

print '1 loop'
for key in test:
    if key in items:
        print key, 'was found'
    else:
        print key, 'not found'

    
Ausgabe:
 
        0 ...
        1 ...
        2 ...
        3 ...
        4 ...
        5 ...
        6 ...
        7 ...
        8 ...
        9 ...
        and liftoff!
        2 loops:
        1.44 not found
        Ni! was found
        (123, 456) was found
        1 loop
        1.44 not found
        Ni! was found
        (123, 456) was found

Funktionen definiert man mit dem Schlüsselwort def. Wenn man einen Wert zurückgeben möchte, tut man das mit return, man muß aber nicht - dann ist der Rückgabewert None. Man kann auch mehrere in ein Tupel verpackte Werte zurückgeben - dann wird, wenn man die Rückgabewerte an Variablen zuweist, Tuple unpacking betrieben.

Die Syntax für Funktionen:

        def <funktionsname>(<parameter>):
          #tu was
          return <was>

In Funktionen lokale Variablen sind nach außen nicht sichtbar, außer man sagt dies explizit mit dem Schlüsselwort global. Wie aus anderen Sprachen bekannt, verdecken lokale Variablen in Blöcken Variablen außerhalb. Wenn aber der Interpreter eine Variable nicht lokal im aktuellen Block oder auf globaler Ebene findet, schaut er bei builtin-Funktionen nach.

Parameter können bei der Funktionsdefinition auch auf Default-Werte gesetzt werden - wenn dann weniger Parameter angegeben werden, sind die anderen mit diesen Defaults belegt. Außerdem kann man beim Aufruf einer Funktion, wenn man die Reihenfolge der Parameter nicht weiß, aber ihre Namen, diese explizit mit angeben - dann ist die Reihenfolge egal, solange die Schlüsselwort-Argumente am Schluß stehen. Wenn man an übergebene Parameter innerhalb der Funktion zuweist, ist das nach außen egal (call by value), aber wenn man veränderliche Datentypen innerhalb einer Funktion verändert, wirkt sich das auf sie auch außerhalb der Funktion aus.

Beispiel:

def intersect(seq1, seq2):
    res = []
    for x in seq1:
        if x in seq2:
            res.append(x)
    return res

def return_tuple(arg1, arg2, arg3):
    return (arg1, arg2, arg3)

def times(x, y=1):
    return x * y

print 'intersections:'
print intersect('spam', 'scam')
print intersect([1, 2, 3, 4,], (4, 2, 5))
print 'tuple stuff:'
return_tuple(3, 17, 'a')
spam = return_tuple(1, 2, 3)
print spam
eggs, ham, spam = return_tuple(1, 2, 3)
print eggs, spam, ham
print 'keywords:'
print times(4, 'Ni!')
print times('Ni!')
print times(x=4, y='Ni!')
print times(y=4, x='Ni!')
print times(4, y='Ni!')




Ausgabe:
 
        intersections:
        ['s', 'a', 'm']
        [2, 4]
        tuple stuff:
        (1, 2, 3)
        1 3 2
        keywords:
        Ni!Ni!Ni!Ni!
        Ni!
        Ni!Ni!Ni!Ni!
        Ni!Ni!Ni!Ni!
        Ni!Ni!Ni!Ni!

Exceptions

Mit Exceptions hat Python ein Fehlerkonzept, wie man es aus Java kennt. Das Werfen bzw. Auffangen von fehlerspezifischen Exceptions verkürzt den Code enorm. Die Vokabeln hierfür sind try und except und else bzw. finally um Blöcke, die Exceptions werfen könnten, zum Auffangen von Exceptions bzw. zur Ausführung egal was passiert (anders als in Java), sowie raise zum Verursachen von Exceptions. Dabei schließen sich except und finally aus. Mit except kann man Variablen, Klassen von Exceptions oder in einem Tupel zusammengefaßte Exceptions auffangen. Nach der Exception kann man auch eine Variable angeben, um mehr Details zu erfahren (diese gibt man nach der Exception bei raise an) - per Default ist dies None.

Die Syntax von Exceptions sieht folgendermaßen aus:

        try:
          #mach was
        except <name>:
          #fang auf
        except (<name1>, <name2>):
          #mehrere auf einmal abarbeiten
        except <name>, <data>:
          #extra infos
        except:
          #default Fehler
        else:
          #nix exception

        try:
          #mach was
        finally:
          #mach dies, egal was passiert ist
Beispiel:

def excep1(a=[]):
  try:
    for i in range(3):
      5 / a[i]
  except (ZeroDivisionError, IndexError), data:
    print data
  else:
    print 'Liste ok!'

def excep2(error='error'):
  try:
    raise error, 'oh-oh!'
  finally:
    print 'vorbei!'

excep1([1, 2, 0])
excep1()
excep1([3, 4, 6, 'a'])
mess = 'Fehler'
try:
  excep2(mess)
except mess, data:
  print mess, data

Ausgabe:
 
        integer division or modulo
        list index out of range
        Liste ok!
        vorbei!
        Fehler oh-oh!

Lambda-Expressions

Mit lambda kann man Funktionen generieren, aber weil es ein Ausdruck ist, kann es auch in einer Liste etc. stehen. Allerdings kann man nur eine Zeile ohne Kontrollstrukturen in einen Lambda-Ausdruck stecken, so daß die Komplexität begrenzt ist. Da man auch kein return benutzen kann, sondern nur den Ausdruck aufzuschreiben braucht, der zurückgegeben werden soll, kann man Lambda-Expressions eher mit Makros als mit Funktionen vergleichen.

Die Syntax von lambda:

        lambda <args..., auch mit defaults>: <Ausdruck>

Lambda-Ausdrücke werden oft in Verbindung mit apply und map benutzt, die eingebaute Funktionen sind. apply bekommt 2 Argumente: ein Funktionsobjekt (auch einen Lambda-Ausdruck) sowie ein Argumenttupel. Es ruft die angegebene Funktion mit dem Tupel als Parametern auf - der Vorteil hierbei ist, daß man sowohl Funktion als auch Argumente aus Variablen lesen kann. Wenn man allerdings Keywords nutzen möchte oder zuviele Argumente angibt, klappt dies nicht.

map bekommt auch als erstes Argument ein Funktionsobjekt, der Rest sind Sequenzen. Dann wendet es die Funktion nacheinander auf die Elemente der Sequenzen an. Übergibt man mehr als eine Sequenz, wird nacheinander je ein Element pro Sequenz zusammen an die Funktion übergeben. map liefert die Ergebnisse als Liste zurück. Es gibt noch weitere Funktionen, die Funktionen nach bestimmten Gesichtspunkten auf Listen anwenden, wie z. B. reduce oder filter. In diesem Zusammenhang kann man auch noch eval erwähnen, das einen übergebenen Python-Ausdruck auswertet.

Beispiel:

        >>> times = lambda x, y: x * y
        >>> times
        <function <lambda> at 807f228>
        >>> times(4, 2)
        8
        >>> times(4, 'Ni!')
        'Ni!Ni!Ni!Ni!'
        >>> apply(times, (times(4, 2), 'Ni!'))
        'Ni!Ni!Ni!Ni!Ni!Ni!Ni!Ni!'
        >>> map(times, ['a', 4, 3.14], [2, 'Ni!', 17])
        ['aa', 'Ni!Ni!Ni!Ni!', 53.38]

Objektorientierung

Die Objektorientierung in Python ist ganz einfach.

Syntax:

        class <name>(<Superklassen>):
          def __init__(self, <args>):
            self.<slot> = <wert>
            #Konstruktor
          def <funktion>(self, <args>):
            #andere Funktionen

Objektvariablen werden wie gezeigt mit self.<varname> = <wert> zugewiesen, danach kann man sie mit self.<varname> ansprechen. Instanzen erzeugt man sich durch <instanz> = <Klasse>(<Konstruktor-Argumente>), auf deren Slots kann man dann mit <instanz>.<varname> zugreifen. Objektmethoden ruft man mit <instanz>.<methode>(<args>) auf. Intern wird das als <methode>(<instanz>, <args>) gemappt, weshalb auch die Definition als ersten Parameter self hat, das der Verweis auf das aktuelle Objekt ist. Man muß diesen Parameter nicht self nennen, dies ist aber so üblich. Schlüsselwörter wie private oder protected gibt es nicht - will man Zugriff auf eine Methode bzw. einen Slot vermeiden, setzt man Unterstriche davor und dahinter.

In Python gibt es auch Mehrfachvererbung - die Reihenfolge der Vererbung ist hier top-down von links nach rechts. Will man die Methoden einer Superklasse aufrufen, benutzt man die Syntax <Superklasse>.<methode>(self, <params). Das Schlüsselwort super existiert in Python auch nicht - mit dieser Methode weiß man aber genau, welche Superklasse denn nun die angesprochen wird.

Außer besonderen Methoden wie __init__(), den Konstruktor, gibt es noch andere: __del__(), den Destruktor, und __repr__(), das die Repräsentation als String (bei Verwendung von ``) zurückgibt. Man kann z. B. mit __add__() oder __mul()__ die Additions- bzw. Multiplikationsoperatoren überladen oder auch Index- bzw. Sliceoperationen.

Anders als in Java kann man Methoden nicht überladen, z. B. mit verschiedenen Typen - zum einen verhindert das die schwache Typisierung der Skriptsprache, zum anderen muß alles in der Symboltabelle einzigartig sein4.

Beispiel:

class Basket:

    def __init__(self,contents=None):
        self.contents = contents or []

    def add(self,element):
        self.contents.append(element)

    def __str__(self):
        result = ""
        for element in self.contents:
            result = result + " " + `element`
        return "Contains:"+result

class SpamBasket(Basket):
    def __init__(self, contents):
        Basket.__init__(self, contents)
        self.add('spam')

    def add(self, element):
        Basket.add(self, element)
        Basket.add(self, 'spam')
        
        
b = Basket(['apple','orange'])
b.add("lemon")
print b
sb = SpamBasket(b.contents)
sb.add('eggs')
print sb
Ausgabe:
 
        Contains: 'apple' 'orange' 'lemon'
        Contains: 'apple' 'orange' 'lemon' 'spam' 'spam' 'eggs' 'spam'



Fußnoten

... erwähnen3
Sei es nur, um eine Endlosschleife zu schreiben: while 1: pass
... sein4
so überschreibt eine Variable a auch die Funktion a und umgekehrt

next up previous
Next: Module und mehr Up: python Previous: Einführung
Britta Koch