Python |
|
Diese Seite basiert auf Inhalten aus dem Buch Arnold Willemer: UNIX-Das umfassende Handbuch Verlagsrechte bei galileo computing |
Der Python-Interpreter heißt python und befindet sich im Verzeichnis /usr/bin. Das ist deswegen so wichtig, weil in einem Python-Skript angegeben wird, wie der Interpreter heißt. Dazu schreiben Sie in die erste Zeile eines Python-Skripts:
#!/usr/bin/python
Anschließend wird die Datei mit Hilfe des Befehls chmod ausführbar gemacht. Danach kann das Skript direkt von der Kommandozeile aus aufgerufen werden.
#!/usr/bin/python print "Hallo Mensch!"
Das Programm gibt auf dem Bildschirm einfach die Meldung »Hallo Mensch!« aus.
Wenn Sie aber lieber einen Namen oder eine sonstige Zeichenkette eingeben lassen wollen, sollten Sie Sie die Funktion raw_input() verwenden. Sie nimmt alles, was kommt.
#!/usr/bin/python print "Hallo! Wie heißen Sie?" antwort = raw_input() print "Oh, Guten Tag,",antwort
Variablennamen bestehen aus Buchstaben, Ziffern und dem Unterstrich und dürfen nicht mit einer Ziffer beginnen. Die Groß- und Kleinschreibung ist signifikant. Hallo und hallo sind also zwei unterschiedliche Variablen.
Fehler führen bei Python normalerweise zu einem Programmabbruch. Das wirkt erst einmal ausgesprochen intolerant. Aber es ist relativ einfach, Fehler abzufangen. Dazu wird dort, wo ein Fehler zu erwarten ist, ein Block mit dem Befehl try (engl. versuchen) aufgebaut. Alles, was in dem try-Block steht, darf zu einem Fehler führen. Für den Fall, dass wirklich ein Fehler passiert, baut der Programmierer einen Block mit except. Dieser Block wird nur im Fehlerfall ausgeführt und sollte dafür sorgen, dass das Programm ordentlich weitergeführt werden kann.
Das Beispiel zeigt eine Eingabe mit input(). Diese Funktion erlaubt nur die Eingabe von Zahlen. Wenn aber jemand dennoch einen Buchstaben oder einen Namen eingibt, wird der except-Block aufgerufen.
try:
zahl = input()
except:
print "Falsche Eingabe"
Den Funktionen input() und raw_input() können in ihren Klammern Zeichenketten übergeben werden, die dann direkt vor der Eingabe auf dem Bildschirm erscheinen:
zahl = input("Bitte eine Zahl eingeben: ")
Computer konnten von Anfang an schon prima rechnen, und das ist auch bei Python nicht anders.
Python verwendet die seit Fortran übliche Schreibweise für mathematische Ausdrücke. Links steht meist die Variable, die das Ergebnis aufnimmt. Nach dem Gleichheitszeichen folgen die Werte und Variablen. Zwischen ihnen stehen dann die klassischen Rechenoperatoren.
| Variable = Ausdruck |
Die Tabelle zeigt die unter Python gängigen Operatoren.
| Operator | Wirkung | + | Addition | - | Subtraktion | * | Multiplikation | / | Division | % | Modulo (Rest einer ganzzahligen Division) | ** | Potenzierung |
|---|
Statt den Wert einer Variablen zuzuordnen, können sie auch gleich ausgegeben werden, wie im Beispielprogramm.
#!/usr/bin/python print 17 + 4 # 21 print 3 -6 # -3 print 3.5 * 7 # 24.5 print 24 / 5 # 4 print 23 % 7 # 2 print 2 ** 4 # 16
In den Kommentaren hinter den Berechnungen finden Sie die Ergebnisse. Mit Hilfe eines Taschenrechners werden Sie die Ergebnisse sicher leicht nachvollziehen können. Es könnte sein, dass Sie bei der Division stutzen. Aber denken Sie daran: Der Computer hat immer Recht. In diesem Fall stehen dort zwei ganzzahlige Werte. Also geht Python davon aus, dass auch ein ganzzahliges Ergebnis gewünscht ist. Wenn Sie 24.0 statt 24 verwenden, kommt auch prompt das Ergebnis 4.8 heraus.
Natürlich gilt auch im angloamerikanischen Raum, dass die Punkt- vor der Strichrechnung kommt. Und genauso gibt es Klammern bei Python, mit denen man diese Regel umgehen kann, wenn es erforderlich ist.
#!/usr/bin/python print 17 + 4 * 2 # 25 print (17 + 4) * 2 # 42
Für die Ausgabe von Tabellen ist es wichtig, Zahlen formatiert ausgeben zu können. Für diesen Zweck wird eine Zeichenkette erstellt, die beschreibt, wie formatiert werden soll. Es folgt ein Prozentzeichen und dann die Variablen in Klammern, die ausgegeben werden sollen.
Die Formatzeichenkette enthält an der Stelle ein Prozentzeichen, an der eine Variable dargestellt werden soll. Es folgt ein Zeichen, das die Darstellungsart angibt. Dabei steht beispielsweise f für Fließkommazahlen mit Dezimalpunkt und i für ganzzahlige Darstellung.
| Kürzel | Bedeutung |
|---|---|
| f | Fließkommazahl in Dezimalpunktdarstellung |
| e | Fließkommazahl in Exponentialdarstellung |
| i | ganzzahliger Wert in dezimaler Darstellung |
| o | ganzzahliger Wert in oktaler Darstellung |
| x | ganzzahliger Wert in hexadezimaler Darstellung mit kleinen Buchstaben |
| X | ganzzahliger Wert in hexadezimaler Darstellung mit großen Buchstaben |
| i | ganzzahliger Wert in dezimaler Darstellung |
| s | Zeichenkette |
Zwischen dem Prozentzeichen und dem Buchstaben für den Typ steht die Zahl der Stellen, die der Gesamtausdruck erhält. Bei Fließkommadarstellung in Dezimalpunktdarstellung sind das zwei Zahlen, getrennt durch einen Punkt. Die erste gibt die Gesamtbreite und die zweite Zahl die Anzahl der Nachkommastellen an. Ein Beispiel veranschaulicht dies:
x = 5.149
y = 5
for i in range(1,10):
print "Fliesskomma: %7.2f und nun Hex: %6X" % (x+i,y+i)
Die Ausgabe dieser Reihe ergibt folgende kleine Tabelle:
Fliesskomma: 6.15 und nun Hex: 6 Fliesskomma: 7.15 und nun Hex: 7 Fliesskomma: 8.15 und nun Hex: 8 Fliesskomma: 9.15 und nun Hex: 9 Fliesskomma: 10.15 und nun Hex: A Fliesskomma: 11.15 und nun Hex: B Fliesskomma: 12.15 und nun Hex: C Fliesskomma: 13.15 und nun Hex: D Fliesskomma: 14.15 und nun Hex: E
Die Welt besteht nicht aus lauter Zahlen. Tatsächlich begegnen uns Texte sehr viel häufiger, und eine Skriptsprache dient auch eher der Auswertung von Protokolldateien als der Lösung numerischer Probleme.
Wie in allen gängigen Programmiersprachen wird auch in Python ein Text in Anführungszeichen gesetzt, wenn er im Listing erscheint. Für die Speicherung scheint Python auf den ersten Blick keine Unterschiede zwischen Zahlen und Zeichenketten zu machen.
Das Pluszeichen wird bei Zeichenketten dazu verwendet, Texte aneinanderzuhängen. Einen Namen können Sie in der üblichen Reihenfolge aus Vor- und Nachnamen ausgeben. Dazwischen steht ein Leerzeichen.
Das folgende kleine Programm spielt mit dem Aneinanderhängen von Texten.
#!/usr/bin/python vor = "James" nach = "Bond" print vor + " " + nach print nach + ", " + vor print nach + ", " + vor + " " + nach
Das Auslesen einzelner Zeichen erfolgt durch rechteckige Klammern. Die Zahl gibt an, der wievielte Buchstabe gemeint ist. Sie können also nach[2] mit Hilfe des Befehls print ausgeben. Unter Python ist es aber nicht möglich, ein Zeichen in einer Zeichenkette durch direkte Zuweisung zu ersetzen. nach[2]='r' wird also aus Mr. Bond keinen Mr. Bord machen.
In Python kann mit Hilfe der rechteckigen Klammern auch auf eine Zeichenfolge zugegriffen werden. Dazu wird zunächst die Position des ersten Buchstabens, dann ein Doppelpunkt und schließlich die Position des letzten gewünschten Buchstabens angegeben.
#!/usr/bin/python name = "Poseidon" print name[2:6]
Die Möglichkeit, einzelne Zeichen im String über die rechteckigen Klammern zu verändern, funktioniert in Python nicht. Python wird eine Fehlermeldung ausgeben und den Skript radikal beenden.
from string import *
Nun stehen Ihnen einige hilfreiche Funktionen zur Verfügung. Die wichtigsten sind hier im Überblick aufgeführt.
| Anzahl = count(Originalzeichenkette, Suchbegriff) |
| Position = find(Originalzeichenkette, Suchbegriff) |
| NaechstePosition = find(Originalzeichenkette, Suchbegriff, Position+1) |
| Rueckwaerts = rfind(Originalzeichenkette, Suchbegriff) |
| NeuenString = replace(AlterString, "Saulus", "Paulus") |
| StringArray = split(Originalzeichenkette) |
GanzeZahl = int(Zeichenfolge) GanzeZahl = long(Zeichenfolge) FliesskommaZahl = float(Zeichenfolge)
Zeichenkette = str(Zahl)
Abfragen werden wie bei den meisten Programmiersprachen mit dem Schlüsselwort if eingeleitet. Danach kommt direkt die Bedingung, die durch einen Doppelpunkt abgeschlossen wird.
Alle Befehle, die nur unter der Bedingung ausgeführt werden, werden eingerückt. Gilt die Bedingung nicht, wird Python nach der nächsten Zeile suchen, die mit der Abfrage gleich eingerückt ist.
|
if <Bedingung>: <Befehle> [elif <Bedingung>: <Befehle> ]* [else: <Befehle> ] |
Es können daraufhin ein oder mehrere elif-Anweisungen mit je einer Bedingung und einem Befehlsblock folgen. Die Anweisungen des Befehlsblocks wird ausgeführt, wenn die Bedingung des elif zutrifft und alle vorigen Bedingungen nicht eingetroffen sind.
Schließlich kann optional am Ende eine else-Anweisung folgen. Sie wird ausgeführt, wenn keine der Bedingungen zutraf.
Die Befehle elif und else werden später im Abschnitt noch genauer ausgeführt. Es ist auch wichtig, dass elif und else auf gleicher Höhe mit if stehen. Hier erst einmal ein einfaches Beispiel für eine if-Anweisung.
if x>10: printf "x ist höher als 10!" print "x ist ", x
In jedem Fall wird »x ist ...« ausgegeben. Sollte aber der Inhalt von x größer als 10 sein, wird vorher noch »x ist höher als 10!« ausgegeben.
Nicht selten gibt es Folgen von Bedingungen. Für diese Fälle bietet Python den Befehl elif, der eine Verschmelzung von else und if darstellt. Auf diese Weise wird verhindert, dass die Verschachtelungen die Einrückungen zu weit nach rechts treiben.
if x>2: printf "Diese Zahl ist größer als 2" elif x==2: printf "Zahl ist gleich 2" else: printf "Das ist kleiner als 2"
Die logischen Operatoren gleichen denen in C und den davon abgeleiteten Sprachen wie Java, C++ oder C#. Auch in Perl werden diese Operatoren verwendet.
| Operator} | Bedeutung |
|---|---|
| > | größer |
| < | kleiner |
| <= | kleiner oder gleich |
| >= | größer oder gleich |
| == | gleich |
| != | ungleich |
Diese Operatoren werden als binär bezeichnet, weil sie immer zwei Werte miteinander vergleichen. Es wird also bei Zahl<2 ausgewertet, ob der Inhalt der Variablen Zahl kleiner als 2 ist. Das Ergebnis ist ein boolescher Wert, der wahr oder falsch sein kann.
Als unärer logischer Operator steht not zur Verfügung. Damit lässt sich das Ergebnis negieren.
Bei Zeichenketten gibt es den Operator in, über den festgestellt werden kann, ob eine Zeichenfolge in einer Zeichenkette enthalten ist.
if "murks" in Name:
print "nomen est omen"
else:
print "Greenhorn!"
Schleifen sind Konstrukte, die dazu dienen, Abläufe zu wiederholen. Ein Vorgang wird für mehrere Fälle durchlaufen oder wiederholt, bis ein bestimmtes Ergebnis vorliegt.
Die for-Schleife arbeitet wie im Shellskript, in dem der Variablen nacheinander die Elemente einer Liste zugewiesen werden.
|
for <Variable in Liste: <Kommandos |
Es folgt ein einfaches Beispiel für solch eine Schleife. Aus einer Liste von Zahlen wird die Variable i gefüllt. Innerhalb der Schleife wird sie ausgegeben und dann das Quadrat der Zahl.
for i in 3, 4.5, 8:
print "Zahl: ", i
print " Quadrat: ", i*i
In anderen Sprachen wird for für Zählschleifen verwendet. Dies lässt sich in Python über die Funktion range() erreichen. Die Funktion range() liefert eine Liste der Zahlen, die durch die drei Parameter bestimmt werden.
for i in range(1,11,1):
print "Zahl: ", i
print " Quadrat: ", i*i
Die Schleife berechnet die Quadratzahlen von 1 bis einschließlich 10. Die Funktion range() hat also drei Parameter. Der erste ist der Startwert, mit dem die Schleife beginnt. Der zweite Parameter ist der erste Wert, der nicht mehr von der Schleife bearbeitet wird. Und der dritte Parameter gibt die Schrittweite der Schleife an.
Eine etwas andere Schleife stellt die while-Schleife dar. Sie wird so lange durchlaufen, wie die Bedingung hinter dem Schlüsselwort while zutrifft.
|
while <Bedingung>: <Befehle> |
Hierin liegt allerdings auch ihr Risiko. Es geschieht oft, dass ein Programmierer übersieht, dass die Bedingung nie zutreffen kann. So kommt es zu der gefürchteten Endlosschleife. Der Computer ist beschäftigt, bis der Strom ausfällt. Hier folgt ein Beispiel für eine hoffentlich korrekte Schleife.
i = 0
while i<50:
i = i * i + 1
print "Ergebnis", i
Das Ergebnis ist natürlich 677. Falls Sie es auf die Schnelle nicht im Kopf nachrechnen konnten, lassen Sie einfach das Programm laufen.
Die while-Schleife eignet sich auch dazu, Eingaben so lange zu wiederholen, bis die Eingabe den Erwartungen entspricht.
#!/usr/bin/pythonNoInput = True while NoInput: try: zahl = input() NoInput = False except: print "Falsche Eingabe: Bitte Zahl eingeben!"
print zahl
Die Variable NoInput wird zu Anfang mit True vorbesetzt. Sie wird nach Aufruf der Funktion input() auf False gesetzt. Sobald die Eingabe erfolgreich verlief, wird die Schleife verlassen, weil die Bedingung hinter while nicht mehr zutrifft. Wenn allerdings keine gültige Zahl eingegeben wird, wird input() sofort eine Ausnahmebehandlung auslösen und der nächste Befehl wird nicht mehr erreicht. Die Ausnahmebehandlung macht nicht viel. Sie meldet nur eine falsche Eingabe.
Sie legen zu Anfang Ihres Programms mit dem Befehl def fest, dass Sie eine Funktion definieren. Dieser Code wird dann bei der Ausführung zunächst übersprungen und erst aktiv, wenn Sie ihn aufrufen. Es folgt der Name der Funktion, über den Sie diese aufrufen möchten. Dann folgt eine Klammer, in der Parameter stehen können. Das sind Werte, die der Aufrufer an die Funktion übergibt.
|
def <Funktionsname(Parameter): <Befehle return <Ausdruck |
Die Funktion stern besteht aus einer Schleife, die nur einen Stern nach dem anderen ausgibt, je nachdem, wie groß die Zahl ist, die per Parameter übergeben wird.
def stern(anzahl):
for i in range(0,anzahl,1):
print "*",
print
...
stern(12) # zeigt 12 Sterne an
Funktionen können Werte zurückgeben. Dazu gibt es das Schlüsselwort return, das auch gleich die Funktion verlässt. Der Rückgabewert wird in den meisten Fällen beim Aufruf einer Variablen zugewiesen.
def quadrat(wert): return wert*wert ... Quadratzahl = quadrat(15)
Die Funktion quadrat() gibt das Quadrat des Parameters zurück. Dieser Wert kann beim Aufruf einer Variablen zugewiesen werden.
Programme bilden Abläufe der Realität nach. Sobald die Programme eine Komplexität haben, die auch Objekte der Realität nachbilden, reichen Zahlen und Texte allein nicht mehr aus. Reale Objekte haben eine Vielzahl von Daten die zusammengehören.
Bei einer Sequenz handelt es sich um eine Folge gleicher Typen. Eine Form der Sequenzen wurden schon erwähnt. Zeichenketten sind Sequenzen. Sie müssen in Python nicht speziell deklariert werden. Eine Variable wird durch eine entsprechende Zuweisung zur Sequenz. Wird einer Variablen eine Zeichenkette zugewiesen, ist es automatisch eine Sequenz und Sie können die einzelnen Buchstaben über die rechteckige Klammer auslesen.
Sequenzen werden eigentlich nur für Zeichenketten verwendet. Die Unmöglichkeit, einzelne Elemente einer Sequenz zu verändern, ist für die meisten anderen Fälle hinderlich.
Eine Liste kann ebenfalls mehrere Datenobjekte kombinieren. Allerdings müssen die Datenobjekte nicht vom gleichen Typ sein. Ein weiterer Unterschied zur Sequenz besteht darin, dass ein Element einer Liste direkt verändert werden kann.
Lottozahlen = {[} 5, 12, 17, 22, 31, 43 {]}
Metropolen = {[} "Hamburg", "Norgaardholz", "London" {]}
Auch die Elemente einer Liste können über die rechteckigen Klammern angesprochen werden. Im Unterschied zur Sequenz können Elemente der Liste verändert werden.
Lottozahlen[2]=16
Das folgende Beispiel arbeitet mit einer doppelt verschachtelten Liste. Die innere Liste besteht aus einem Ortsnamen, der Einwohnerzahl und einem Kennzeichen. Aus diesen Elementen wird eine Liste gebildet. Eigentlich ist es sogar eine Sequenz.
Das Datenelement wird einfach über rechteckige Klammern zusammengefasst. Die Ausgabeschleife zeigt, dass mit einer einfachen rechteckigen Klammer auf ein Listenelement zugegriffen wird.
#!/usr/bin/python
MeineListe = [ ["Norgaardholz", 249, "FL"],
["Bad Homburg", 61253, "HG"],
["Husum", 24327, "NF"]
]
for i in range(0,3,1):
print MeineListe[i]
for j in range(0,3):
print MeineListe[i][j]
Auch Elemente einer verschachtelten Liste können nachträglich geändert werden. Der folgende Befehl ändert das Kfz-Kennzeichen von Norgaardholz in SL.
MeineListe[0][2] = "SL"
Elemente der Liste können gelöscht werden. Der Befehl dazu lautet del.
del MeineListe[1]
Sie können mit dem Befehl insert an beliebiger Stelle ein Element in die Liste einfügen. Mit dem Befehl append wird das neue Element immer am Ende angehängt.
MeineListe.insert(1, ["Berlin", 3000000, "B"]) MeineListe.append(["Berlin", 3000000, "B"])
Mit Hilfe der Funktion sort() kann eine Liste sortiert werden.
MeineListe.sort()
Im Falle der verschachtelten Liste des Beispiels wird von der inneren Liste das erste Element als Sortierkriterium verwendet.
Es können auch Elemente aus der Liste entfernt werden.
MeineListe.remove(["Husum", 23322, "NF"])
Das Element muss exakt bezeichnet werden. Dann wird genau dieses Element entfernt. Sobald nur Teile des Elements benannt werden, führt remove() zu einer Ausnahme, die mit try aufgefangen werden muss.
Ein Tupel entspricht einer Liste, allerdings sind deren Elemente nach der Definition nicht mehr änderbar.
Tupelkonstanten unterscheiden sich von den Listenkonstanten dadurch, dass runde statt rechteckige Klammern verwendet werden.
Lottozahlen = ( 5, 12, 17, 22, 31, 43 ) Metropolen = ( "Hamburg", "Norgaardholz", "London" )
»Dictionary« heißt auf Deutsch >>Wörterbuch<<. So funktioniert dieser Datentyp auch. Es gibt einen Suchbegriff und eine Erläuterung. Der Suchbegriff bezeichnet der Informatiker als Schlüssel. Die Erläuterung als den zugehörigen Datenbereich. Über diesen Schlüssel kann schnell ein Eintrag gefunden werden.
kfz = {"sl":"Schleswig", "fl":"Flensburg","hh":"Hamburg"}
kfz{[}"hg"{]} = "Bad Homburg"
kfz{[}"hg"{]} = "Hochtaunuskreis"
key = "hg"
print "Schluessel = ", key, " Wert = ", kfz{[}key{]}
del kfz[hh]
Damit wird der Eintrag mit dem Hamburger Kennzeichen aus dem Dictionary kfz gelöscht.
Mit der Funktion len() kann die Anzahl der Elemente eines Dictionaries bestimmt werden. Die Funktion has_key() kann ermitteln, ob es ein Element mit dem als Parameter angegebenen Schlüssel gibt.
print "Das Dictionary hat ", len(kfz), " Elemente"
if kfz.has_key("bi"):
print kfz["bi"]
else:
print "Bielefeld gibt es nicht."
In der ersten Zeile wird die Anzahl der Elemente im Dictionary ausgegeben. Danach wird geprüft, ob der Schlüssel »bi« im Dictionary vorkommt und eine entsprechende Ausgabe gemacht.
Es klingt etwas überraschend, dass eine Interpretersprache, die keine feste Typbindung für Variablen kennt, objektorientierte Elemente besitzt. Tatsächlich ist es möglich, Klassen zu definieren. Klassen sind Datenstrukturen, die um Funktionen ergänzt werden, die auf die Datenelemente der Klasse einwirken.
Das Datum kann als Klasse dargestellt werden. Es enthält Tag, Monat und Jahr und den Wochentag. Als Funktion bietet sich an, ein paar Tage zum Datum hinzuzählen.
class Datum:
tag = 1
monat = 1
jahr = 1970
def addiere(self, tage):
self.tag += tage
# die weitere Berechnung spare ich mir hier
meintag = Datum()
meintag.addiere(12)
Mit dem Schlüsselwort class beginnt die Klassendefinition. Es folgt der Name der Klasse und ein Doppelpunkt. Wie bei Python gewohnt, wird eingerückt, solange die Definition der Klasse dauert. Es folgen nun alle Mitglieder der Klasse. Hier sind es die Variablen tag, monat und jahr. Sie werden UNIX-typisch mit dem 1.~Januar 1970 vorbesetzt. Dann folgt die Funktion addiere(). Wie jede Definition einer Funktion beginnt auch diese mit dem Schlüsselwort def. Es folgt der Name der Funktion und die Klammer, die die Parameter enthält. Bei Klassenfunktionen gibt es immer mindestens einen Parameter. Dieser ist der Verweis auf die eigene Klasse. Daher wird dieser Parameter gern self genannt. Sie können aber auch einen anderen Namen nehmen.
Die objektorientierten Möglichkeiten von Python reichen erstaunlich weit. So gibt es die Möglichkeit, Konstruktoren und Destruktoren zu definieren. Operatoren können überladen werden und auch die Vererbung ist möglich. Im Rahmen dieses UNIX-Buchs interessiert allerdings bei den Fähigkeiten einer Skriptsprache mehr die schnelle Erstellung von Systemlösungen als die hohen Weihen des Software-Engineerings.
Bei einer Zuweisung wird eine Kopie erstellt. Für Zahlen stimmt das auf jeden Fall. Wenn eine Zeichenkette einer anderen zugewiesen wird, stimmt das auch.
Sobald es sich aber um komplexere Objekte wie Listen, Tupel, Dictionaries oder von Klassen abgeleitete Objekte handelt, erzeugt Python kein zweites Objekt bei einer Zuweisung, sondern eine Referenz. Eine Referenz ist ein Verweis auf das Datenobjekt. Der Vorteil dieser Vorgehensweise ist, dass es schnell geht. Eine Referenz zu erstellen ist viel einfacher, als einen größeren Berg an Daten zu kopieren. Und in vielen Fällen ist ein Duplikat gar nicht notwendig. Eine Referenz reicht.
Der Nachteil ist, dass der Programmierer nicht immer im Kopf hat, dass zwei Variablen den gleichen Datenspeicher referenzieren. Das kann zu netten Verwechslungskomödien führen, die allerdings bei Programmen meist als Tragödien enden.
Das folgende Beispiel zeigt, wie sich eine Referenz auswirken kann:
kfz = {"sl":"Schleswig", "fl":"Flensburg","hh":"Hamburg"}
kfz{[}"hg"{]} = "Bad Homburg"
kfz2 = kfz # Hier wird eine Referenz gebildet!
kfz{[}"hg"{]} = "Hochtaunuskreis"
key = "hg"
print "Schluessel = ", key, " Wert = ", kfz{[}key{]}
print "Schluessel = ", key, " Wert = ", kfz2{[}key{]}
Eigentlich müsste die Änderung, die nach der Zuweisung von kfz an kfz2 durchgeführt wurde nur auf kfz, nicht aber auf kfz2 wirken. Tatsächlich aber kommt in beiden Fällen das Ergebnis »Hochtaunuskreis« heraus.
Soll tatsächlich eine Kopie angefertigt werden, muss eine entsprechende Funktion verwendet werden. Zu diesem Zweck gibt es die Funktionen copy() und deepcopy() aus dem Modul copy.
kfz = {"sl":"Schleswig", "fl":"Flensburg","hh":"Hamburg"}
kfz{[}"hg"{]} = "Bad Homburg"
kfz2 = copy(kfz) # Hier wird ordentlich kopiert!
kfz{[}"hg"{]} = "Hochtaunuskreis"
key = "hg"
print "Schluessel = ", key, " Wert = ", kfz{[}key{]}
print "Schluessel = ", key, " Wert = ", kfz2{[}key{]}
Und tatsächlich: Hier gibt es in der ersten Ausgabezeile »Hochtaunuskreis« und in der zweiten Zeile »Bad Homburg«.
Die Funktion deepcopy() müssen Sie einsetzen, wenn Sie verschachtelte Listen verwenden, damit auch die inneren Elemente kopiert werden.
Sollten Sie in Verwirrung geraten, ob zwei Variablen auf das gleiche Objekt verweisen oder vielleicht doch eine Kopie sind, können Sie beide mit dem Operator is vergleichen. Ist das Ergebnis wahr, sind es Referenzen auf das gleiche Objekt.
Um Daten längerfristig festzuhalten, muss ein Programm sie in einer Datei abspeichern können. Um die geschriebenen Daten wiederzubekommen, wäre es schon ganz gut, wenn das Programm die Datei später auch wieder lesen könnte. Als Skriptsprache zur Unterstützung der Administrationstätigkeit ist das Auslesen von Protokolldateien natürlich von besonderem Interesse.
| Datei = open(Dateiname, [Optionsstring]) |
Die Optionen werden als Buchstaben in einer Zeichenkette übergeben.
| Option} | Bedeutung |
|---|---|
| r | Datei wird nur gelesen |
| w | Datei wird neu geschrieben |
| a | An die Datei wird angehängt |
| r+ | Datei wird gelesen und geschrieben |
| w+ | Datei wird gelesen und geschrieben |
| a+ | Datei wird gelesen und geschrieben |
| b | Datei wird im Binärmodus verwendet |
| <Datei>.close() |
#!/usr/bin/python
try:
Datei = open("testdata", "w")
Datei.write("Wir schreiben in eine Textdatei\n")
Datei.close();
except:
print "oha!"
#!/usr/bin/python
try:
Datei = open("testdata")
TextZeilen = Datei.readlines()
for Zeile in TextZeilen:
print Zeile
Datei.close()
except:
# Ausnahmebehandlung
print "oha! Ein Problem mit der Datei"
| Parameter} | Berechnungsrichtung |
|---|---|
| 0 | Vom Anfang der Datei aus (Standardvorgabe) |
| 1 | Von der aktuellen Dateiposition aus |
| 2 | Vom Ende der Datei aus gesehen. |
Daraus ergeben sich die folgenden Wirkungen von seek()-Aufrufen:
Datei.seek(129) # Positioniert auf das 129. Byte Datei.seek(129,0) # Positioniert auf das 129. Byte Datei.seek(12,1) # Positioniert auf das 141. Byte (129+12) Datei.seek(-2,2) # Positioniert auf das vorletzte Byte
Von Python aus können Sie auf Datenbanken zugreifen. Dadurch steht es Ihnen offen, schnell größere Datenkorrekturen, Kontrollen oder Statistiken durchzuführen. Sie können natürlich auch komplexe Datenbankanwendungen schreiben.
Das folgende Beispiel öffnet eine Datenbank, setzt einen INSERT-Befehl dort ab und schließt die Verbindung wieder.
#!/usr/bin/python # -*- coding: Latin-1 -*- import MySQLdbconn = MySQLdb.connect(db="meinedb",user="ich", passwd="huhu") cursor = conn.cursor() cursor.execute("insert into buch " + \ " (nr, name, auflage) values " + \ "(4711, 'Einstieg in C++', 25000)") conn.close()
Über die Funktion connect() wird eine Verbindung geschaffen. Als Parameter dieser Verbindung sind die üblichen Angaben bei Datenbanken erforderlich. Unter db wird der Datenbankname angegeben. Es folgen der berechtigte Benutzer mit seinem Kennwort.
import pg conn = pg.connect(db="meinedb",user="ich", passwd="huhu")
Die Verbindungsvariable wird benötigt, um einen Cursor zu bekommen. Über diesen Cursor wird dann mit Hilfe der Funktion execute() der Befehl an die Datenbank als einfache Zeichenkette übergeben.
sqlbefehl = "insert into buch (nr, name, auflage) " + \
" values (%i, %s, %i) % (nr, name, aufl)"
cursor.execute(sqlbefehl)
Die Befehle zum Einfügen, Ändern und Löschen sind auf diese Weise zu übermitteln, da sie letztlich nur aus einer einfachen Kommandozeile bestehen, die man vor dem Senden vom Programm her aufbereitet.
Etwas anders ist das Auslesen der Datenbank. In diesem Fall werden eventuell mehrere Zeilen von der Datenbank als Antwort kommen. Der Rahmen für eine Anfrage ist mit den anderen Befehlen gleich.
#!/usr/bin/python # -*- coding: Latin-1 -*- import MySQLdbconn = MySQLdb.connect(db="meinedb",user="ich", passwd="huhu") cursor = conn.cursor() cursor.execute("select from buch") erg = cursor.fetchall() if erg: # Überschrift print " Nr Name Auflage" print "-----------------------------------" for nr, name, auflage in erg: print "%3i %30s %9i" % (nr, name, auflage) conn.close()
Nach dem Aufruf von execute() wird über die Funktion fetchall() die gesamte Ergebnismenge in den Speicher geholt. Das funktioniert natürlich nur dann, wenn diese Menge überschaubar ist.
Python unterstützt Sie mit Bibliotheken im Zugriff auf viele Internetserver. So gibt es die Möglichkeit, Websites zu steuern, Mails zu lesen und zu senden, Newsserver auszulesen oder Daten per FTP zu übertragen.
Das folgende kleine Programm öffnet die Website www.willemer.de Anschließend liest sie die vom Server gelieferte Seite Zeile für Zeile durch und speichert sie in einer lokalen Datei.
import urllib
website = urllib.urlopen("http://www.willemer.de")
Zeilen = website.readlines()
website.close()
try:
Datei = open("willemer.htm", "w")
Datei.writelines(Zeilen)
Datei.close()
except:
print "Konnte Datei nicht schreiben"
Auch der Zugriff auf einen POP3-Server ist aus Python sehr einfach zu realisieren. Das folgende Beispiel liest die ersten 10 Zeilen jeder Mail aus und zeigt sie auf dem Bildschirm an. Damit Sie wirklich Freude an dem Programm haben, sollten Sie Ihre eigenen Daten für den POP3-Server, die Benutzerkennung und das Passwort verwenden.
#!/usr/bin/python
import poplib
MyMail = poplib.POP3('pop.1und1.de')
MyMail.user('pt1234567-aa')
MyMail.pass_('dasgehteuchgarnichtsan')
AnzMails = len(MyMail.list()[1])
for i in range(AnzMails):
for j in MyMail.top(i+1, 10)[1]:
print j
Es sind die POP3-Kommandos user pass, list und top als Memberfunktionen im Listing zu sehen. Mit den weiteren Kommandos retr und dele können alle von der RFC 1725 festgelegten Vorgänge durchgeführt werden.
Bei Fehlern bricht dieses Programm einfach ab. Durch die Ergänzung mit try und except können Sie die Fehler einfangen und eine ansprechende Fehlermeldung komponieren.
Tk ist eine Bibliothek, die in Zusammenhang mit der Skriptsprache Tcl entstand. Tcl hat sich nicht auf breiter Basis durchsetzen können. Aber Tk ist eine beliebte Möglichkeit, auf einfache Art ein grafisches Programm zu erstellen.
Das folgende Beispielprogramm erzeugt ein Fenster mit einem Text und einem Button. Sobald der Button angeklickt wird, ist das Programm beendet.
#!/usr/bin/python
from Tkinter import *
# Callback-Funktion für den Button
def ende():
sys.exit(0)
Fenster = Tk()
meinLabel = Label(Fenster, text = "Huhu")
meinButton = Button(Fenster, text = "Schluss", command = ende)
meinLabel.pack()
meinButton.pack()
Fenster.mainloop()
In der Abbildung sehen Sie das Miniprogramm, wie es auf dem Bildschirm erscheint.
lErgebnis.grid(row=2, column=1)
Der Aufbau des Fensters ist darüber hinaus geprägt von den Konstruktionsaufrufen der Widgets. Die Ressourcen werden belegt und die Fensterelemente in das passende Grid gelegt. In der folgenden Tabelle sehen Sie noch einmal das Grid, das dem Programm zu Grunde liegt.
| row=0, column=0 | row=0, column=1 |
| row=1, column=0 | row=1, column=1 |
| row=2, column=0 | row=2, column=1 |
Die Variablen für die Widgets werden nur benötigt, wenn später Interaktionen mit ihnen stattfinden. Das ist für die Entry-Elemente und das Ergebnis-Label wichtig. Für die Beschriftungen habe ich darum die Variable meinLabel wiederverwendet. Wenn die Beschriftung und Positionierung in einer Anweisung ausgeführt werden, könnte man die Variable komplett sparen. Auch die Button-Variable wird eigentlich nicht mehr gebraucht. Den Callback hat der Button bei seiner Erzeugung mitbekommen. Die Ressourcen des Buttons werden später nicht mehr geändert.
In der Callback-Funktion sehen Sie, wie mit der Memberfunktion get() die Werte aus den Entry-Feldern geholt werden. Sie sehen auch, dass das Programm keinerlei Fehler abfängt. In einem Programm, das ernsthaft unter die Leute kommt, würde man das natürlich ändern. Allerdings bringen diese Sicherheitsabfragen nichts Neues, darum ist es hier nicht dabei. Das Programm ist auch ohne diese schon reichlich lang.
Fenster["menu"] = menubar
lErgebnis["text"] = "---" lErgebnis.configure(text="---")
#!/usr/bin/python
# -*- coding: Latin-1 -*-
from Tkinter import *
# Callback-Funktion für den Button. Berechnet das Ergebnis
def Calc():
Udiff = float(eUges.get())-Uled.get()
Imax = float(eImax.get())
if Imax>0:
lErgebnis["text"] = str((Udiff/Imax)*1000)
else:
lErgebnis["text"] = "---"
# Callback für den Quit-Menüeintrag
def Ende():
sys.exit(0)
Fenster = Tk() # Fenster erzeugen
# Uges - Label und Eingabefeld
meinLabel = Label(Fenster, text = "Uges:")
meinLabel.grid(row=0)
eUges = Entry(Fenster)
eUges.grid(row=0, column=1)
# Imax - Label und Eingabefeld
meinLabel = Label(Fenster, text = "Imax:")
meinLabel.grid(row=1)
eImax = Entry(Fenster)
eImax.grid(row=1, column=1)
# Ergebniszeile - Label und Ergebnislabel
Label(Fenster, text = "Ohm").grid(row=2)
lErgebnis = Label(Fenster, text = "")
lErgebnis.grid(row=2, column=1)
# Berechnungs-Button
meinButton = Button(Fenster, text="Berechne", command=Calc)
meinButton.grid(row=3, column=1)
# Menü wird erstellt
menubar = Menu(Fenster)
mdatei = Menu(menubar, tearoff=0)
mdatei.add_command(label="Quit", command=Ende)
menubar.add_cascade(label="Datei", menu=mdatei)
mfarbe = Menu(menubar, tearoff=0)
# Die Radiobuttons füllen die Variable Uled
Uled = DoubleVar()
mfarbe.add_radiobutton(label="rot", variable=Uled,value=1.6, \
background="red")
mfarbe.add_radiobutton(label="grün", variable=Uled,value=2.1, \
background="green")
mfarbe.add_radiobutton(label="gelb", variable=Uled,value=2.2,\
background="yellow")
mfarbe.add_radiobutton(label="blau", variable=Uled,value=2.9,\
background="blue")
mfarbe.add_radiobutton(label="weiß", variable=Uled,value=4.0,\
background="white")
menubar.add_cascade(label="Farbe", menu=mfarbe)
# Das Menü wird eingehängt
Fenster["menu"] = menubar
# Nun kann das Programm laufen
Fenster.mainloop()
Das Programmfenster ist nicht groß, aber sieht mit dem farbigen Menü natürlich originell aus.
|
Diese Seite basiert auf Inhalten aus dem Buch Arnold Willemer: UNIX-Das umfassende Handbuch Verlagsrechte bei galileo computing |
| Homepage | (C) Copyright 2009 Arnold Willemer |