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!
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 istBeispiel:
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, dataAusgabe:
integer division or modulo list index out of range Liste ok! vorbei! Fehler oh-oh!
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]
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 sbAusgabe:
Contains: 'apple' 'orange' 'lemon' Contains: 'apple' 'orange' 'lemon' 'spam' 'spam' 'eggs' 'spam'