0% fanden dieses Dokument nützlich (0 Abstimmungen)
6 Ansichten463 Seiten

Python Kurs

Das Dokument ist eine Einführung in die Programmiersprache Python, verfasst von Martin Schimmels und unterliegt der Creative Commons Lizenz BY-NC-SA. Es behandelt grundlegende Konzepte der Programmierung, die Entwicklungsumgebung IDLE und die Verwendung von Variablen sowie mathematische Operationen in Python. Zudem wird betont, dass das Skript nicht für kommerzielle Zwecke genutzt werden darf und die Verbreitung von Wissen gefördert wird.

Hochgeladen von

bvb.reha2023
Copyright
© All Rights Reserved
Wir nehmen die Rechte an Inhalten ernst. Wenn Sie vermuten, dass dies Ihr Inhalt ist, beanspruchen Sie ihn hier.
Verfügbare Formate
Als PDF, TXT herunterladen oder online auf Scribd lesen
0% fanden dieses Dokument nützlich (0 Abstimmungen)
6 Ansichten463 Seiten

Python Kurs

Das Dokument ist eine Einführung in die Programmiersprache Python, verfasst von Martin Schimmels und unterliegt der Creative Commons Lizenz BY-NC-SA. Es behandelt grundlegende Konzepte der Programmierung, die Entwicklungsumgebung IDLE und die Verwendung von Variablen sowie mathematische Operationen in Python. Zudem wird betont, dass das Skript nicht für kommerzielle Zwecke genutzt werden darf und die Verbreitung von Wissen gefördert wird.

Hochgeladen von

bvb.reha2023
Copyright
© All Rights Reserved
Wir nehmen die Rechte an Inhalten ernst. Wenn Sie vermuten, dass dies Ihr Inhalt ist, beanspruchen Sie ihn hier.
Verfügbare Formate
Als PDF, TXT herunterladen oder online auf Scribd lesen

Einführung in Python

Martin Schimmels

28. Juni 2020


Copyright c 2009, 2018 Martin Schimmels
Rechtlicher Hinweis

W ICHTIG
Druck dieses Buch nicht aus!!!
Im Online-Dokument kann man suchen, springen, es wird (hoffentlich)
ständig verändert und verbessert. Und es benötigt nicht eine wichtige
natürliche Ressource: Papier.

Dieses Skript steht unter der Creative Commons Lizenz BY-NC-SA, auf Deutsch, Creative Commons

Namensnennung-Keine kommerzielle Nutzung-Weitergabe unter gleichen Bedingungen.“

Diese Lizenz erlaubt es, das Skript zu benutzen, zu ergänzen, zu verändern, Inhalte umzustellen. Diese
Lizenz erlaubt es nicht, das Skript für kommerzielle Zwecke zu nutzen. Der Link zu dieser Lizenz ist
<[Link]
Nachfolgend steht die Zusammenfassung der wichtigsten Teile der Lizenz:
• Das Skript darf vervielfältigt, weitergegeben und öffentlich zugänglich gemacht werden.
• Das Skript darf verändert werden.
• Ich als Autor muss in Kopien genannt werden.
• Das Skript darf nicht kommerziell verwendet werden.
• Veränderte oder bearbeitete Versionen dieses Skriptes müssen unter der selben Lizenz stehen.
Das heißt auch, dass solche Versionen genau wie dieses Skript einen Link zur Lizenz enthalten
müssen.

Fehler, Verbesserungen, Ergänzungen etc. an martin@[Link]


Mit Arbeitsblättern von Frank Krafft und Jens Stephan
Danke an Jürgen Adam für Korrekturen, Ergänzungen, Tips.
Die Wort-Wolke auf der Titelseite wurde mit R und dem Paket wordcloud erstellt.
Widmung
• Allen, die sich für freie Software einsetzen und freie Software schreiben.
• Allen, die ihr Wissen nicht für sich behalten wollen, sondern es mit anderen teilen wollen. Wissen
ist ein Gut, das sich vermehrt, wenn man es teilt.
Wenn Informationen allgemein nützlich sind, wird die Menschheit durch ihre Verbreitung rei-

cher, ganz egal, wer sie weitergibt und wer sie erhält.“ 1
• Allen, die verstanden haben, dass freie Software nicht ein Hirngespinst ist, sondern wirtschaftli-
ches und politisches Denken beeinflusst: der Gedanke, der dahinter steckt, kann Politik und Wirt-
schaft menschlicher machen.
• Kris Kristofferson (Freedom is just another word for nothing left to lose)
• Benjamin Franklin: That as we enjoy great Advantages from the Inventions of Others, we should

be glad of an Opportunity to serve others by any Invention of ours, and this we should do freely
and generously.“ 2

1 Richard Stallman, Datum und Ort unbekannt


2 Benjamin Franklin, Autobiographie [Part III, p. 98], zitiert nach [Link] Franklin

3
Inhaltsverzeichnis

I. Grundlagen 25
1. Was ist Python? 27
1.1. Der Name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
1.2. Was für eine Sprache? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
1.3. Warum Python und nicht eine andere Sprache? . . . . . . . . . . . . . . . . . . . . . . . . . 28
1.4. Ausführung von Python-Programmen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

2. Programmieren 33
2.1. Was heißt Programmieren“? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

2.1.1. Warum soll man überhaupt programmieren lernen? . . . . . . . . . . . . . . . . . . 34
2.1.2. Sprache lernen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
2.1.3. Übersetzung ... in welche Sprache denn? . . . . . . . . . . . . . . . . . . . . . . . . 35
2.2. Was ist also ein Programm? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
2.3. Geschichte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
2.4. Was braucht man, um mit Python zu arbeiten? . . . . . . . . . . . . . . . . . . . . . . . . . 36
2.5. Hilfsprogramme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
2.6. Voraussetzungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
2.6.1. Das Dateisystem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
2.6.2. Regeln für Dateinamen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
2.6.3. Datei-Operationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
2.7. Was heißt Programmieren“? Fortsetzung! . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

2.7.1. Strukturierte Programmierung: Ein Überblick . . . . . . . . . . . . . . . . . . . . . 40
2.8. Objektorientierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
2.9. Programmierstil und Konventionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
2.10. Reservierte Wörter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
2.11. Fehler (zum ersten) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
2.12. ... und das fehlt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
2.13. Fehler finden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
2.14. Aufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

II. IDE 49
3. Die Entwicklungsumgebung IDLE: Zahlen und Variable 51
3.1. . . . und bevor es losgeht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.2. Rechnen in der Entwicklungsumgebung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.2.1. Aufgaben zu Zahlen und elementaren Berechnungen . . . . . . . . . . . . . . . . . 58
3.3. Ein Speicherplatz mit einem Namen: Variable . . . . . . . . . . . . . . . . . . . . . . . . . . 58
3.3.1. Variable in Mathematik und in der Programmierung . . . . . . . . . . . . . . . . . 58
3.3.2. Variablennamen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
3.3.3. Wertzuweisung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
3.3.4. Aufgaben zu Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
3.3.5. Zuweisungsmuster . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
3.4. Bruchrechnen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
3.5. Rechnen und vergleichen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
3.5.1. Zahlen, Zahlen, Zahlen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
3.5.2. Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
[Link]. Vergleichsoperatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
[Link]. Verschiebeoperatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
3.5.3. Komplexe Zahlen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
3.5.4. Andere Zahlsysteme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
3.5.5. Zufall . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
[Link]. Zufällige ganze Zahlen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
[Link]. Zufällig ausgewählte Buchstaben aus einer Textzeile . . . . . . . . . . . . 73

5
Inhaltsverzeichnis Inhaltsverzeichnis

3.6. Shortcut-Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73

4. Richtig programmieren 75
4.1. Entwicklungsumgebungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
4.1.1. Die Entwicklungsumgebung Eric . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
4.1.2. IDE unter Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
4.1.3. So sieht’s aus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
4.1.4. Der Programm-Rahmen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
4.2. Das absolute Muss: Hallo Ihr alle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
4.3. Die ersten einfachen Programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

III. Texte und andere Daten 79


5. Texte 81
5.1. Grundlegendes zu Texten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
5.2. Operationen auf Texten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
5.2.1. Methoden von Zeichenketten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
5.2.2. Wie und wo gespeichert wird . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
5.3. Kodierungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
5.3.1. Unicode in Python 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
5.4. Formatierung von Zeichenketten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
5.4.1. Die C-ähnliche Formatierung mit dem %-Operator . . . . . . . . . . . . . . . . . . . 90
5.4.2. Die Formatierung mit Hilfe der format-Methode . . . . . . . . . . . . . . . . . . . 92
5.5. Reguläre Ausdrücke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
5.5.1. Allgemeines zu regulären Ausdrücken . . . . . . . . . . . . . . . . . . . . . . . . . 97
5.5.2. Wortteile aus einem Text herausfiltern . . . . . . . . . . . . . . . . . . . . . . . . . . 98
5.5.3. gpx-Datei eines Fitness-Trackers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
5.5.4. Beispiel für Zahlen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
5.5.5. Ein komplizierterer Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
5.5.6. Eine etwas sinnvollere Anwendung: Wörter mit Doppelbuchstaben finden . . . . 102
5.6. Aufgaben zu Texten (Strings) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

6. Strukturierte Daten 105


6.1. Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
6.2. Listen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
6.2.1. Definition von Listen und Listenelemente . . . . . . . . . . . . . . . . . . . . . . . . 105
6.2.2. Erzeugung von Listen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
[Link]. Durch Angabe der Elemente . . . . . . . . . . . . . . . . . . . . . . . . . . 106
[Link]. Als Objekt der Klasse list . . . . . . . . . . . . . . . . . . . . . . . . . . 106
[Link]. Mittels range . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
[Link]. Mit Hilfe der list comprehension . . . . . . . . . . . . . . . . . . . . 107
[Link]. Mittels input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
6.2.3. Beispiele von Listen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
6.2.4. Operationen auf Listen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
[Link]. Wie funktioniert das Enthaltensein“? . . . . . . . . . . . . . . . . . . . . 109

[Link]. Erzeugung einer Liste durch eine Filterfunktion . . . . . . . . . . . . . . . 109
6.2.5. Veränderung von Listen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
[Link]. Ein Element anhängen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
[Link]. Ein gern gemachter Fehler . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
[Link]. Mehrere Elemente anhängen . . . . . . . . . . . . . . . . . . . . . . . . . . 111
[Link]. Ein Element einfügen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
[Link]. Ein bestimmtes Element entfernen (nicht so schön) . . . . . . . . . . . . . 113
[Link]. Ein bestimmtes Element bearbeiten und entfernen . . . . . . . . . . . . . 113
[Link]. Eine Teilmenge der Liste bearbeiten . . . . . . . . . . . . . . . . . . . . . . 114
[Link]. Eine Liste sortieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
6.2.6. Tricks mit ListenMehrere Listen auf einmal bearbeiten . . . . . . . . . . . . . . . . 116
[Link]. Matrizen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116

6
Inhaltsverzeichnis Inhaltsverzeichnis

[Link]. Listenelemente mit Namen ansprechen . . . . . . . . . . . . . . . . . . . . 118


[Link]. Richtige Datentypen aus einer Zeichenkette . . . . . . . . . . . . . . . . . 119
6.2.7. Kopie einer Liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
6.2.8. Nicht mehr ganz so wilde Listen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
6.3. Dictionaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
6.3.1. Zugriff auf Dictionary-Elemente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
[Link]. Dictionary lesen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
[Link]. Dictionary schreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
6.3.2. Dictionaries sortiert ausgeben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
6.3.3. Was ist denn das irgendwas“, das in einer Liste oder einem Dictionary stehen kann?128

6.3.4. Tricks mit Dictionaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
[Link]. Verschlüsselung durch Erzeugung eines Dictionaries mit zip . . . . . . . 128
[Link]. Dictionary Comprehension . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
6.4. Tupel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
6.4.1. Allgemeines zu Tupeln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
6.4.2. Benannte Tupel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
6.5. Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
6.6. Mengen (sets) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
6.6.1. Mengenoperationen mit Rechenzeichen . . . . . . . . . . . . . . . . . . . . . . . . . 131
6.6.2. Mengenoperationen als Methoden der Klasse Menge . . . . . . . . . . . . . . . . . 133
6.7. Aufgaben zu Listen, Dictionaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
6.8. Veränderbarkeit von Daten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134

IV. Strukturen 137


7. Programmstrukturen 139
7.1. Gute Programme, schlechte Programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
7.1.1. Kontrollfluß . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
7.2. Eins nach dem anderen: Die Sequenz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
7.2.1. Aufgaben zu Sequenz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
7.3. Wenn . . . dann: Die Alternative . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
7.3.1. Wahrheit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
[Link]. Sprachliche Ungenauigkeiten und Fallen . . . . . . . . . . . . . . . . . . . 145
7.3.2. Wahrheit angewandt: die Alternative . . . . . . . . . . . . . . . . . . . . . . . . . . 146
7.3.3. Blöcke und Einrückungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
7.3.4. Beispiele zu Bedingungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
[Link]. Kurzschlüsse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
7.3.5. Beispiel für eine Mehrfach-Entscheidung . . . . . . . . . . . . . . . . . . . . . . . . 151
7.3.6. So sehen Mehrfachentscheidungen schöner aus! . . . . . . . . . . . . . . . . . . . . 152
7.3.7. Ein Trick für verschachtelte Entscheidungen . . . . . . . . . . . . . . . . . . . . . . 153
7.3.8. Aufgaben zu Auswahl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
7.3.9. Verknüpfte Logik-Operatoren und Reihenfolge . . . . . . . . . . . . . . . . . . . . 155
7.4. Schleifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
7.4.1. Zähl-Schleifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
[Link]. Mitzählen in einer Zählschleife . . . . . . . . . . . . . . . . . . . . . . . . 165
7.4.2. While-Schleifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
7.4.3. Verschiedene Probleme und ihre Lösung mittels Schleifen . . . . . . . . . . . . . . 167
[Link]. Listen oder Dictionaries durch eine Art Liste erzeugen (list comprehen-
sions) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
[Link]. Die Anzahl der Elemente einer Liste bestimmen . . . . . . . . . . . . . . . 170
[Link]. Anzahl der Elemente einer Liste mit einer bestimmten Eigenschaft . . . . 171
[Link]. . . . wie eben, aber mit Ergebnisliste . . . . . . . . . . . . . . . . . . . . . . 171
[Link]. Das größte Element einer Menge finden . . . . . . . . . . . . . . . . . . . 172
[Link]. An welcher Stelle steht das größte Element einer Menge? . . . . . . . . . 172
7.4.4. Ein bißchen Klassik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
7.4.5. Eigentlich keine Schleife . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
7.4.6. Eingriffe in das Durchlaufen von Schleifen . . . . . . . . . . . . . . . . . . . . . . . 176

7
Inhaltsverzeichnis Inhaltsverzeichnis

7.4.7. Was schief gehen kann . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176


7.4.8. Aufgaben zu Schleifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
7.5. Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
7.5.1. Allgemeines zu Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
7.5.2. Eingebaute Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
7.5.3. Funktionen selbstgebaut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
[Link]. Definition und Aufruf von Funktionen . . . . . . . . . . . . . . . . . . . . 181
[Link]. Rückgabewerte und Parameterlisten . . . . . . . . . . . . . . . . . . . . . 182
[Link]. Verkettung von Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . 185
[Link]. Gültigkeitsbereiche und Namensräume . . . . . . . . . . . . . . . . . . . 186
7.5.4. Funktionen wiederverwenden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
7.5.5. Ein Trick, um Funktionen zu testen . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
7.5.6. Globale Variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
7.5.7. Rekursive Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
7.5.8. Funktionen als Parameter von Funktionen . . . . . . . . . . . . . . . . . . . . . . . 193
[Link]. Seiteneffekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
7.5.9. Aufgaben zu Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
7.5.10. lambda-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195

V. Programmentwicklung und Modularisierung 199


8. Programmentwicklung mit Test 201
8.1. Der Doctest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
8.1.1. Aufgaben zu doctest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203

9. Module und Pakete 205


9.1. Mehr Mathematik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
9.2. Eigene Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
9.3. Pakete . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210

VI. Objektorientierte Programmierung 211


10. Klassen 213
10.1. Ist schon klasse, so eine Klasse! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
10.2. Objekte, Objekte, Objekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
10.3. Kapselung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
10.4. Setter und Getter? Oder doch lieber nicht? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
10.5. Statische Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
10.6. Vererbung (ohne Erbschaftssteuer) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
10.6.1. Klassen neuen Stils . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
10.6.2. Weiter mit der Klasse Mensch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232
10.7. Methoden überschreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
10.7.1. Selbstgeschriebene Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
10.7.2. Magische“ Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234

10.8. Gute Programme ... wann schreibt man objektorientiert? . . . . . . . . . . . . . . . . . . . 236

11. Ein etwas längeres Programm 239


11.1. Objektorientierter Entwurf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
11.2. Objektorientierte Programmierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
11.2.1. Die Klasse Konto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
11.2.2. Das aufrufende Programm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
11.2.3. Realisierung der Methoden Einzahlen“ und Auszahlen“ . . . . . . . . . . . . . . 241
” ”
11.2.4. Die Verzinsung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242
11.2.5. Die ersten Verbesserungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
11.2.6. Aufgaben zu Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244

8
Inhaltsverzeichnis Inhaltsverzeichnis

11.3. Ein klassisches Beispiel: Stack und Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245


11.3.1. Die Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246
11.3.2. Der Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247

VII. Fehler und Ausnahmen 249


12. Fehler. . . 251
12.1. .. macht jeder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
12.2. Fehler werden abgefangen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
12.3. Spezielle Fehler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255
12.3.1. Ein Menu-Schnipsel mit Fehlerbehandlung . . . . . . . . . . . . . . . . . . . . . . . 257

[Link] Speicherung 259


13. Dateizugriff 261
13.1. Dateien allgemein . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
13.1.1. print funktioniert auch! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264
13.1.2. Textanalyse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264
13.2. Fortführung des Konten-Programms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
13.3. In die Datei damit!!! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
13.3.1. Der Modul pickle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
13.3.2. Der Modul shelve . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
13.4. Aufgaben zu Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270

14. Datenbanken 271


14.1. MySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271
14.2. .. mit Python-Bordmitteln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274

IX. Noch ein paar Beispiele zur OOP 275


15. Ein weiteres Projekt: ein Getränkeautomat 277
15.1. Objektorientierter Entwurf und Realisierung der Klasse . . . . . . . . . . . . . . . . . . . . 277
15.2. Die Waren kommen in den Automaten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280
15.3. Geld regiert die Welt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280
15.4. Jetzt kann gekauft werden! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
15.5. To Do!! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282

16. Noch ein Beispiel: Zimmerbuchung in einem Hotel 283


16.1. Vorstellung des Projekts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
16.2. Der erste Entwurf: Eine Klasse für Hotelzimmer . . . . . . . . . . . . . . . . . . . . . . . . 283
16.3. Der zweite Entwurf: ein aufrufendes Programm . . . . . . . . . . . . . . . . . . . . . . . . 285
16.4. Der dritte Entwurf: das Hotel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286
16.5. Der vierte Entwurf: Methoden werden ergänzt . . . . . . . . . . . . . . . . . . . . . . . . . 288

17. Und noch ein Beispiel: ein Adressbuch 291


17.1. Vorstellung des Projekts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
17.2. Der erste Entwurf: eine Liste von Listen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
17.3. Der zweite Entwurf: ein fauler Trick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
17.4. Der dritte Entwurf: eine Liste von Dictionaries . . . . . . . . . . . . . . . . . . . . . . . . . 293
17.5. Der vierte Entwurf: Aktionen (aber nur angedeutet)!! . . . . . . . . . . . . . . . . . . . . . 294
17.6. Der fünfte Entwurf: Aktionen (jetzt tut sich wirklich etwas)!! . . . . . . . . . . . . . . . . . 296
17.7. Der sechste Entwurf: persistente Speicherung . . . . . . . . . . . . . . . . . . . . . . . . . . 298
17.8. Jetzt wird es objektorientiert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
17.8.1. Der Klassenentwurf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
17.8.2. Zur Klasse Adresse kommt die Klasse Adressbuch hinzu . . . . . . . . . . . . . 301
17.8.3. Dauerhafte Speicherung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304

9
Inhaltsverzeichnis Inhaltsverzeichnis

18. Immer noch das Adressbuch — nur schöner 307


18.1. Das Adressbuch kommt in die Datenbank . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307

19. Eine Ampel 313


19.1. Der Entwurf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313
19.2. Die Realisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314
19.3. Persistente Speicherung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314
19.4. Eine Kreuzung hat 4 Ampeln! Der Entwurf. . . . . . . . . . . . . . . . . . . . . . . . . . . . 315
19.5. Die Realisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317

X. Grafik! Internet! 319


20. CGI-Programme 321
20.1. HTML und Kollegen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
20.2. Allgemeines zu HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
20.2.1. Was ist HTML? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
20.2.2. Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
20.2.3. Obligatorische HTML-Befehle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
20.2.4. Struktur eines HTML-Dokuments . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322
20.2.5. Absätze und Leerzeichen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322
20.2.6. Hervorhebungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322
20.2.7. Listen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
20.2.8. Links . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
20.2.9. Formulare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
20.3. CGI (Das Common Gateway Interface) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
20.4. Die Pflicht: hallo, ihr alle da draußen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
20.5. Hello world als dynamische Web-Seite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
20.6. Ein eigener Mini-Webserver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
20.7. Dynamik durch Schleifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
20.7.1. Vorwärtszählen .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
20.7.2. .. und rückwärtszählen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
20.7.3. Das kleine 1 x 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328
20.8. Formular-Eingabe und Auswertung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331
20.9. Eine Rechnung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334
[Link] aber wirkliche Dynamik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341

21. Eine Kreuzung auf meiner Web-Seite 345


21.1. Die Ampel kommt ins Netz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
21.2. Die Kreuzung im Netz ist auch nicht schwerer . . . . . . . . . . . . . . . . . . . . . . . . . 348

22. Programme mit grafischer Oberfläche 355


22.1. Tkinter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355
22.2. Problem: Temperaturen umrechnen (zuerst ohne grafische Oberfläche) . . . . . . . . . . . . 355
22.3. . . . und jetzt mit grafischer Oberfläche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357

XI. Python für Verwaltungsaufgaben 361


23. Python als Sprache für den eigenen Rechner 363
23.1. Das Betriebssystem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363
23.2. Verzeichnisse und Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
23.2.1. Die Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
23.2.2. Das Modul os . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366
23.3. Aufruf von Programmen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
23.4. Weiter mit Verzeichnissen: das Modul glob . . . . . . . . . . . . . . . . . . . . . . . . . . . 369
23.5. Das Modul subprocess . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370
23.6. Das Modul shutil . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370
23.7. Das Modul [Link] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371

10
Inhaltsverzeichnis Inhaltsverzeichnis

XII. Texte für Fortgeschrittene 373


24. Texte bearbeiten für Fortgeschrittene 375
24.1. Natural Language Toolkit (NLTK) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375

[Link] (Forts.) 377


25. Mathematik (Forts.) 379
25.1. Das Paket numpy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379
25.1.1. Matrizen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379
[Link]. Erzeugung von Matrizen . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380
[Link]. Matrizen umformen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385
[Link]. Elementare Zeilenumformungen . . . . . . . . . . . . . . . . . . . . . . . 387
[Link]. Rechnen mit Matrizen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389
[Link]. Matrizengleichungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393
25.2. Symbolische Mathematik (und andere schöne Dinge) . . . . . . . . . . . . . . . . . . . . . 393
25.3. Pandas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
25.3.1. Series . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
25.3.2. Dateien, die Pandas lesen kann . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405
25.3.3. Data Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
25.3.4. Indizierung und andere Möglichkeiten der Auswahl . . . . . . . . . . . . . . . . . 407
[Link]. Series . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407

[Link] 411
Glossar 416

A. Arbeitsblätter zu Klassen (Danke, Jens!) 417


A.0.1. UML-Diagramme und Python-Code . . . . . . . . . . . . . . . . . . . . . . . . . . . 417
A.0.2. Vererbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418
A.0.3. Objektvariable vs. Klassenvariable . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419
A.0.4. Polymorphie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420
A.0.5. Übungsaufgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421
A.0.6. Assoziationen Teil 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422
A.0.7. Klassenarbeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423
A.0.8. Assoziationen Teil 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424
A.0.9. Liste von Objekten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425

B. Arbeitsblätter zu Python (Danke, Frank!) 427

C. Lösungen zu Aufgaben 449


C.1. aus Kapitel 7: Programmstrukturen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449
C.2. aus Kapitel 8: Schleifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449
C.3. aus Kapitel 10: Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455

D. Literatur zu Python 457

E. Index 459

11
Abbildungsverzeichnis
0.1. 6 einfache quadratische Spiralen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
0.2. 6 verdrehte quadratische Spiralen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
0.3. 3 sechseckige Spiralen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

1. Was ist Python?


1.1. Monty Python (CC by 2.0) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
1.2. Interpreter und Compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.3. Compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.4. Interpreter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

3. Die Entwicklungsumgebung IDLE: Zahlen und Variable


3.1. Eric Idle (CC BY 2.0) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
3.2. Die IDE Idle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
3.3. Erste Berechnung in der IDE Idle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
3.4. Rechnungen in Idle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
3.5. Ein Variablen-Karton mit Inhalt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

4. Richtig programmieren
4.1. Die IDE Eric . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
4.2. Die IDE PyScripter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

5. Texte
5.1. Texte in der IDE Idle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
5.2. Multiplikation von Texten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

6. Strukturierte Daten
6.1. Struktogramm binäre Suche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109

10. Klassen
10.1. Klassendiagramm Mensch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
10.2. Klassendiagramm Schueler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229

15. Ein weiteres Projekt: ein Getränkeautomat


15.1. Klassendiagramm Automat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277
15.2. Klassendiagramm Ware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280

16. Noch ein Beispiel: Zimmerbuchung in einem Hotel


16.1. Klassendigramm Hotelzimmer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
16.2. Klassendiagramm Hotel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286

17. Und noch ein Beispiel: ein Adressbuch


17.1. Klassendiagramm Adresse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299

19. Eine Ampel


19.1. Klassendiagramm Ampel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313
19.2. Eine Kreuzung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316
19.3. Kreuzung: Freie Fahrt von Nord nach Süd . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316
19.4. Kreuzung: Alle warten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316
19.5. Kreuzung: Freie Fahrt von West nach Ost . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317
19.6. Kreuzung: Wieder warten alle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317

13
Abbildungsverzeichnis Abbildungsverzeichnis

20. CGI-Programme
20.1. Eingabe-Formular in HTML(Namen) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332
20.2. Eingabe-Formular für eine Rechnung in HTML . . . . . . . . . . . . . . . . . . . . . . . . . 334
20.3. Ausgabe einer Rechnung in HTML (aber wirklich nicht schön) . . . . . . . . . . . . . . . . 338
20.4. Ausgabe einer Rechnung in HTML (so kann man das akzeptieren) . . . . . . . . . . . . . 341

22. Programme mit grafischer Oberfläche


22.1. Klassendiagramm Temperatur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355
22.2. Klassendefinition: GUI für die Temperatur . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
22.3. Temperaturprogramm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
22.4. Beendigung des Temperaturprogramms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360

14
Tabellenverzeichnis

2. Programmieren
2.1. Betriebssystem-Befehle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

3. Die Entwicklungsumgebung IDLE: Zahlen und Variable


3.1. Division in Python 3.x bzw. Python 2.x . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
3.2. Arithmetische Operatoren in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
3.3. Variablennamen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
3.4. Vergleichsoperatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
3.5. Verschiebeoperatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
3.6. Verschiedene Zahlsysteme und Umrechnung . . . . . . . . . . . . . . . . . . . . . . . . . . 70
3.7. Shortcut-Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

5. Texte
5.1. Steuerzeichen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
5.2. Zeichenkette als Feld betrachtet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
5.3. Format-Codes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
5.4. Format-Option-Codes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
5.5. Parameter für die format-Methode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
5.6. Reguläre Ausdrücke: Zeichen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
5.7. Reguläre Ausdrücke: Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98

6. Strukturierte Daten
6.1. Liste mit Hausnummern und Einträgen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
6.2. Überblick Strukturierte Daten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131

7. Programmstrukturen
7.1. UND-Verknüpfung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
7.2. ODER-Verknüpfung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
7.3. NICHT-Verknüpfung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
7.4. Übung zu Wahrheitswerten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
7.5. Pseudocode und Python-Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
7.6. Notendurchschnitt: Pseudocode und Python-Code . . . . . . . . . . . . . . . . . . . . . . . 164
7.7. Pseudocode und Python-Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
7.8. Schlüsselwort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
7.9. Verschlüsselung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179

10. Klassen
10.1. Sichtbarkeit und Kapselung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222

12. Fehler. . .
12.1. Fehler-Konstanten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258

19. Eine Ampel


19.1. Die Ampel-Phasen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317

25. Mathematik (Forts.)


25.1. Skatturnier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392

15
Vorwort
Typographische Konventionen

Abbildung 0.1. 6 einfache quadratische Spiralen

Bei manchen Kapiteln stehen solche Bilder voran. Sie sind mit Python und der Bibliothek turtle“ ge-

malt. Wer sich über die Schildkröte informieren möchte, sollte einfach im Internet suchen. Vorschläge
für Suchbegriffe: turtle, logo, Seymour Papert
Jetzt fängt das Buch aber richtig an. Zuerst muss hier aber einmal geklärt werden, was die verschie-
denen Schriftarten in diesem Buch bedeuten:
• Schreibmaschinenschrift wird für Code(-Fragmente) benutzt. Ebenso werden Variablennamen
in Schreibmaschinenschrift gesetzt.
• Befehlsnamen werden fett gesetzt.
• Dateinamen werden in Schreibmaschinenschrift gesetzt.
• Ein- und Ausgaben in IDLE werden wie folgt gesetzt. Eingaben sind an den >>> zu erkennen.

>>> print(’Hallo’)
Hallo

T IPP
Randnotizen stehen im Online-Dokument in einem blauen Kasten.
Randnotizen stehen im gedruckten Text in einem Rahmen mit einem ein-
gekreisten großen i“ am Rand.

W ICHTIG
Wenn etwas besonders wichtig ist, steht das im Online-Dokument in einem
orange-roten Kasten.
Wenn etwas besonders wichtig ist, steht im gedruckten Text am Rand ein
Ausrufezeichen in einem Kreis.

A NMERKUNG
Eine Anmerkung steht im Online-Dokument in einem grünen Kasten.
Auf eine Anmerkung wird im gedruckten Text durch den ausgestreckten
Zeigefinger hingewiesen.
Anmerkungen werden insbesondere auch benutzt, um auf Änderungen in
Python 3.x im Verhältnis zu Python 2.x hinzuweisen.

17
VORWORT

A CHTUNG
Das Achtung-Zeichen weist auf eine Situation hin, bei der leicht ein Fehler
gemacht werden kann. Wenn etwas besonders wichtig ist, steht im ge-
druckten Text am Rand ein Ausrufezeichen in einer Raute.
Das wird im Online-Dokument durch einen violetten Kasten hervorgeho-
ben.

Freiheit

Abbildung 0.2. 6 verdrehte quadratische Spiralen

Dieser gesamte Text ist frei im Sinne der Freien Software“. Er steht unter der CC BY-NC-SA“, die unter
” ”
dem Link <[Link] nachzulesen ist.
Das bedeutet, dass dieser Text beliebig kopiert und verbreitet werden darf. Er darf auch modifiziert
werden.
Das Urheberrecht dieses Textes bleibt bei mir. Die wichtigste Bestimmung ist, dass dieser Text immer
unter der CC BY-NC-SA bleibt, auch wenn er von Dir verändert wird, und dass die CC BY-NC-SA
immer Teil dieses Textes sein muss.
Du darfst beliebig viele Kopien dieses Textes auf beliebigen Medien machen. Auf jeder Kopie muss
aber ein urheberrechtlicher Vermerk aufgeführt sein und die CC BY-NC-SA muss Teil der Kopie sein.
Den eigentlichen Text darfst Du nach Deinen Vorstellungen bearbeiten, Teile hinzufügen, Verbesse-
rungen anbringen, Teile weglassen, sofern Du einige Regeln einhältst

1. Der veränderte Text muß deutlich sichtbare Vermerke enthalten, die die Veränderung, den Autor
der Veränderung und das Datum der Veränderung angeben.
2. Der veränderte Text verbleibt unter der CC BY-NC-SA und enthält die CC BY-NC-SA.
3. Der Text darf nicht in ein proprietäres Format umgewandelt werden.
4. Eine Kopie des veränderten Textes wird mir zugesandt.

Dieser Text ist in DocBook-XML geschrieben. Dabei habe ich mich an die Spezifikationen gehalten,
wie sie in dem Buch von [DocBook-XML] beschrieben wird. Sollte jemand diesen Text im Docbook-
XML-Format weiterverarbeiten, soll er sich per Mail an mich wenden.
Da ich selber es absolut unerträglich finde, wenn Fachbücher der Informatik in schlechtem Deutsch
geschrieben sind,3 4 bitte ich auch alle Leser, dass sie mir eventuelle sprachliche Fehler mitteilen, gerade
auch wenn es nur Leichtsinnsfehler oder kleinere Ungenauigkeiten sind. 5
3 Es ist leider betrüblich zu sehen, wie viele Autoren geraden von Fachbüchern im Bereich der Datenverarbeitung ihre Mutter-
sprache nicht mehr beherrschen. Zeichensetzung und Rechtschreibung folgen da oft Regeln, die niemand zuvor gehört hat —
und der Autor kurz danach wieder vergessen hat. Manchmal fragt man sich da, ob der Autor schon jemals ein Programm in
welcher Programmiersprache auch immer geschrieben hat, wenn man weiß, mit welcher Genauigkeit man dabei sprachliche
Regeln einzuhalten hat.
Besonders peinlich sollte das für das Lektorat eines Verlages sein, aber auch da hat man manchmal das Gefühl, dass dort
Analphabeten eingestellt worden sind. Die typische Reaktion, wenn man einen solchen Lektor auf einen Fehler hinweist, ist
dann ein Haben Sie etwa noch nie einen Fehler gemacht?“

4 Von Frau A.F. habe ich gelernt, dass Schüler inzwischen in Bezug auf die Zeichensetzung nur noch die 5-cm-Regel kennen:
Setze alle 5 Zentimeter ein Komma.
5 Ich bitte wirklich ausdrücklich darum, mir Dinge NICHT durchgehen zu lassen, die heutzutage an Schulen viel zu vielen

Schülern nachgesehen werden.

18
VORWORT

Gleichberechtigung
In diesem ganzen Text wird immer für einen generischen Begriff nur das in der deutschen Sprache
übliche grammatikalische Geschlecht benutzt. Eine Fachkraft oder sogar eine Koryphäe auf dem Gebiet
der Python-Programmierung kann also durchaus auch mal ein Mann sein und ein Python-Programmierer
auch eine Frau. Vor allem bei der Bezeichnung von mehreren Personen, vulgo Plural genannt, vermei-
de ich so unschöne Formulierungen wie Python-Programmiererinnen und Python-Programmierer“.

Sollte jemand daran Anstoß nehmen, so steht jedem Leser es frei, den Quelltext mit einem (zum Bei-
spiel in Python selbstgeschriebenen) Programm und mit den in diesem Text erworbenen Kenntnissen
und einigem Zusatzwissen in XML (hierzu bietet sich das Buch von Drake [Python and XML] an) so
abzuändern, dass solche generischen Begriffe in eine nach seinen Vorstellungen politisch korrekte Form
umwandelt werden. 6

Wer? Wo? Wie?

Abbildung 0.3. 3 sechseckige Spiralen

Dieses Buch kann man natürlich überall lesen, am Schreibtisch, auf dem Balkon, vor dem Fernsehgerät,7
am Strand . . . . Bei vielen Kapiteln ist es aber ganz sinnvoll, dass man dieses Buch am Arbeitsplatz vor
sich nimmt, Computer eingeschaltet und alles so vorbereitet, dass man sofort den einen oder anderen
Python-Befehl eingeben kann oder eine kleine Übung machen kann, ein Programm schreibt, weil durch
das Lesen die Idee zu einem Programm kommt . . .

Eine Begründung
Ich höre und vergesse.
Ich sehe und erinnere mich.
Ich tue und ich verstehe.

(Konfuzius 8 )
Aber warum sollen wir eigentlich programmieren lernen? Computer sind inzwischen zu einem Werk-
zeug geworden, von dem man wie etwa von dem Werkzeug Staubsauger“ nicht mehr wissen muss,

wie es funktioniert, um es zu bedienen. So jedenfalls wird das uns in der Werbung immer wieder gesagt.
Ist das wirklich so?
Nun, zu welcher Gruppe von Menschen willst Du gehören? Der Gruppe derjenigen, die bedienen
können, ohne zu verstehen? Oder zu der Gruppe derjenigen, die verstehen und die Maschine beherr-
schen? Man muss sich klar machen: Computer machen genau das, was man ihnen sagt“, und das

machen sie richtig gut, ohne Widerspruch, skrupellos. Vielleicht will ich doch lieber zu der Gruppe
gehören, die dem Computer sagen kann, was er tun soll.
Einfache Aufgaben sollten einfach gelöst werden. Einfach ist schön, einfach ist elegant. Auf dem Ge-
biet der Programmierung heißt das: das Zusammenklicken eines Programms ist vor allem für Anfänger
abzulehnen, weil dadurch das Programm, das man schreiben will, undurchschaubar wird. Durch diese
Methode der Software-Produktion werden Bibliotheken, Module, Klassen eingebunden, die die Logik
6 Wenn es sein muss, sogar mit dem grossen Binnen-I. horribile dictu.
7 Ja, es soll wirklich Fernsehsendungen geben, bei denen man nichts versäumt, wenn man wegschaut — und manchmal ist es
trotzdem besser, man bleibt vor der Glotze hängen.
8 sinngemäß unter: <[Link]

19
VORWORT

des Problems verschleiern, die Platz kosten, die das Programm langsam machen, die ein Programm
unleserlich machen. Die Folge davon ist: eine komplizierte Lösung erfordert komplexe Resourcen.

Andere Sprachen
Deswegen soll an einem alltäglichen Beispiel demonstriert werden, wie das alltägliche Problem in ver-
schiedenen Sprachen gelöst wird. Vor allem wird das oben genannte Vorgehen realisiert, also auf allen
Schnickschnack verzichtet, der heutzutage zu einem richtigen“ Programm gehört: eine grafische Ober-

fläche fehlt, Eingabemasken fehlen. Das Programm benutzt nur die Shell (die bei anderen Betriebssys-
temen Eingabeaufforderung“ heißt.)

Ein Programm soll einen Text von der Standard-Eingabe entgegennehmen. Der Begriff Standard-

Eingabe“ bedeutet, dass in der Umgebung, in der das Programm ausgeführt wird, über die Tastatur
etwas eingegeben wird. Dies bedeutet insbesondere weiter, dass nicht etwa eine grafische Oberfläche
geschaffen wird, in der sich vielleicht ein Fenster öffnet, in das man etwas eingeben kann. Damit man
auch sieht, was man eingegeben hat, wird die Eingabe danach auch noch ausgedruckt. Das macht das
Programm natürlich viel länger !!! Dazu folgen hier 3 Lösungen in 3 Programmiersprachen:

1. In perl gibt es die ganz kurze Version:

$s = <> ;
print $s;

oder die fast schon geschwätzige Version:

$s = <STDIN> ;
print $s;

Was fragt der typische Schüler, wenn er dieses Stück Programmcode sieht?
• Warum steht da ein Dollar-Zeichen?
• Was heißt STDIN“?

• Warum steht das STDIN“ in größer-kleiner-Zeichen?

• Muss da ein Strichpunkt stehen?
2. In Python geht das fast noch kürzer:

print(input(’Text eingeben: ’))

Das funktioniert, aber das ist nicht besonders schön, deswegen schreibt man in Python oft we-
sentlich mehr. In beiden Fällen erhält aber man auch wesentlich mehr Komfort, nämlich eine aus-
drückliche Aufforderung, etwas einzugeben:

s = input(’Text eingeben: ’)
print(s)

Was fragt der typische Schüler, wenn er dieses Stück Programmcode sieht?
• Was heißt input“?

• Warum steht der Text in Anführungszeichen?
3. In Java sieht das Programm-Fragment so aus:

import [Link].*;
public class stdLesen {
public static void main(String[] args)
throws IOException{
BufferedReader eingabe =

20
VORWORT

new BufferedReader(new InputStreamReader([Link]));


String s;
while ((s = [Link]()) != null & & [Link]() != 0)
[Link](s);
}
}

Was fragt der typische Schüler, wenn er dieses Stück Programmcode sieht?
• Was bedeutet [Link].*“?

• Was bedeutet importieren?
• Was bedeutet public“?

• Was heißt class“?

• Was bedeutet static void main“?

• Was bedeutet String[] args“?

• Was heißt throws“?

• Was ist eine IOException“?

• Was sollen die vielen geschweiften Klammern?
• usw.
Ich bin sicher, dass jeder Lehrer zustimmt, wenn ich sage, dass für fast jedes Wort und fast jedes
Zeichen hier eine Frage nach dem Sinn auftauchen wird.
4. Und zum Schluß kommt das entsprechende C++-Programm.

#include<iostream>
#include<string>
using namespace std;

int main()
{
string t1;
cin >> t1;
cout << t1 << endl;
return 0;
}

Kein Kommentar! Aber falls jemand Lust verspürt: einfach mal ein paar Kommentare sammeln
von absoluten Programmieranfängern.

Entscheidungskriterien
Man kann die Entscheidung für eine Programmiersprache nach vielen Kriterien treffen. Ein Unter-
nehmen wird die Wirtschaftlichkeit einer Sprache weit oben ansiedeln. Eine interessante (wenn auch
schon etwas ältere) Gegenüberstellung findet man bei Steve Ferg unter <[Link]
org/wiki/Compiler>. Aber Wirtschaftlichkeit sollte nicht nur unter dem Kostenaspekt gesehen wer-
den. Auch in der Bildung ist Wirtschaftlichkeit ein Kriterium, nämlich wenn man der Frage nachgeht,
wieviele Fehlermöglichkeiten eine Sprache bei verschiedenen Konstrukten enthält. Hier ist eine knappe
Sprache wie Python deutlich im Vorteil. Auch hierzu gibt es in oben genanntem Artikel von Ferg einige
Beispiele.
Für den Unterricht, sei es in der Schule oder sei es an der Hochschule, stellen sich die Fragen nach der
Lernkurve (steil oder flach), nach der Modellhaftigkeit der Sprache und der Mächtigkeit der Sprache.
Die Mächtigkeit der Sprache ist allerdings in der Schule von untergeordneter Bedeutung. Jede Program-
miersprache ermöglicht es, alle Probleme, die etwa in einem 2- oder 4-stündigen Kurs auftreten, zu
lösen.

21
VORWORT

Entscheidung
Hier sollte sich jeder Lehrende kurz überlegen, wie er vorgehen würde, wenn er seinen Schülern er-
klären sollte, was die Befehle bedeuten. Würde er sagen: #include<iostream>, #include<string>, using
namespace std;, cin usw. ignorieren wir einfach mal, das kommt später? Oder würde er wirklich die
einzelnen Sprachelemente erklären? Wie lange bräuchte er wohl dazu? (Eine kleine Entscheidungs-
hilfe, aber leider nur für die Sprache Java: In einem der Standardbücher zu [Java] steht ein ähnliches
Programm-Fragment, das dieses Problem löst, auf Seite 612.) Wenn er die erste Methode wählt: wie-
viele Zuhörer würden Programmierung als etwas sehen, das in der Nähe von obskuren Voodoo-Kulten
anzusiedeln ist, aber für Normalsterbliche völlig unverständlich ist. Und wenn er die zweite Metho-
de wählt: wieviele Programmieranfänger würden diesen Erklärungen gerne folgen, sie verstehen und
sagen: mehr davon!
Man könnte das Beispiel vereinfachen und das Standard-Programm, das jedem Anfänger in fast je-
der Programmiersprache vorgeschlagen wird, seit Kernighan/Ritchie ihr Werk über die Sprache C“

geschrieben haben, das Programm, das nichts tut außer den Text Hallo, world!“ ausgeben, in verschie-

denen Programmiersprachen untersuchen (dann müssen natürlich C“ und C++“ auch dabei sein!).
” ”
Vor allem die Schüler sind es, die mit Recht eine Abkehr von den bisher benutzten Unter-
richtssprachen verlangen, weil die damit fabrizierten Produkte in der Regel keinen Wieder-
erkennungswert mehr besitzen im Vergleich zu den sonst vorherrschenden Programmen.
Es besteht allerdings die Gefahr - insbesondere beim Einsatz moderner Entwicklungsober-
flächen und Interface-Buildern“, wie sie z.B. bei Delphi üblicherweise eingesetzt werden -

dass nun schöne bunte Programme entstehen, die Vermittlung wichtiger Informatik-Konzepte
aber zu kurz kommt. 9

Schön einfach? Einfach ist schön


Deswegen hat dieser Text ein Motto: Keep it simple. Je einfacher, desto besser für die Lernenden. Da-
mit will ich verhindern, dass Tools eingesetzt werden, die für die professionelle Arbeit konzipiert sind,
aber für den Unterricht im Programmieren überdimensioniert sind. Die Software, die wir einsetzen,
soll das können, was man braucht, um Probleme des Kurses zu lösen, und sie soll es dem Lernenden
ermöglichen, das möglichst einfach zu tun. Sie soll nicht ungezählte Fähigkeiten beherrschen, die man
braucht, um ein großes Programmpaket in einem großen oder mittleren Unternehmen zu erstellen, die
man aber nicht braucht, um programmieren zu lernen.
Was wir hier einsetzen, orientiert sich also nicht an dem, was Industrie und Wirtschaft produktiv
benutzen. Für Lernende viel sinnvoller ist es, Software zu benutzen, die das Exemplarische hervorhebt
und damit dem Lernenden ermöglicht, Gelerntes auf andere Umgebungen zu übertragen.

Die Programmierung graphischer Oberflächen erfolgt heute im kommerziellen Bereich in


der Regel mit Hilfe sogenannter Interface-Builder“. Auch wenn es Sinn machen kann, sol-

che Werkzeuge Schülern im Informatikunterricht an die Hand zu geben (Java-Workshop,
Python-Glade, PythonWin), so sollte dies nicht gleich im Anfängerunterricht geschehen. Ein
wichtiges Ziel des Unterrichts besteht darin, grundsätzliche Konzepte und Arbeitsweisen
zu verstehen. Komfortable Oberflächen verstellen oft den Blick für das Wesentliche, machen
u.U. oberflächlich. Die Oberfläche ist nicht das System!10

Lernen durch Nachmachen? Lernen durch Selbertun?


Man kann eine Sprache erst dann, wenn man in ihr kommunizieren kann.

Man kann eine Programmiersprache erst dann, wenn man selbständig in ihr Programme
schreiben kann.

Weil learning by doing“ in der Programmierung nicht nur ein netter Spruch ist, sondern wirklich das

einzig erfolgversprechende Rezept, sollte jeder Lernende möglichst viele Übungsaufgaben machen. Ein
paar Aufgaben sind bereits am Ende mancher Kapitel aufgeführt. Im Sinne des oben Gesagten sollte
jeder sich ermutigt fühlen, Aufgaben hinzuzufügen.
9 aus: <[Link]
10 aus: <[Link]

22
VORWORT

Wer Programmieren lernt, der wird Probleme als solche erkennen lernen. Fortschritte dabei bedeuten,
dass man immer mehr Lösungsstrategien sich erarbeitet und verstehen kann. Nach einer Weile hat man
dann einen ganzen Stapel Vorgehensmuster, unter denen man dann bei einem neuen Problem einige
auswählen kann, die Effizienz beurteilen kann und das Problem löst, indem man aus seinem Erfah-
rungsschatz das Richtige auswählt.

Bereits beim Zusammenspiel zwischen Variablen und Schleifen zeigen sich die Probleme
vieler SchülerInnen11 im Umgang mit Steuerstrukturen. (Einfaches Beispiel: Wie bestimmt
man das Maximum aus fünf eingegebenen Zahlen?) 12 Ein grundsätzliches Dilemma des
Unterrichts besteht nun darin, dass häufig eine große Lücke zwischen dem passiven Beherr-
schen (also dem Nachvollziehen eines von der Lehrperson erstellten Programms) und dem
aktiven Beherrschen (also dem selbständigen Erkennen, wann und wie die jeweilige Steu-
erstruktur zur Problemlösung einzusetzen ist) klafft und dass diese Lücke nur sehr schwer
durch Erklärungen durch die Lehrperson zu überbrücken ist. 13

Und im Sinne dieses Zitates sollten sich Dozenten davor hüten, Lösungen zu Aufgaben an die Ler-
nenden auszugeben. Jeder Programmieranfänger sollte das schöne Gefühl kennenlernen, ein Problem
selbst gelöst zu haben. Und nur beim Durchdenken einer eigenen Lösung kann ein Neuling das Für und
Wider eines Lösungsansatzes bewerten.

11 Ganz ehrlich: ich war das nicht! Das große I“ ist im Originaltext, und bei dem Zitat muss ich das übernehmen.
12 ”
Übrigens in Python ein triviales Problem. Da in Python dynamische Parameterlisten für Funktionen zum Sprachumfang
gehören, liefert print(max(3,4,12,67,34,8)) das korrekte Ergebnis. Es ist Python völlig egal, wieviele Parameter
übergeben werden.
13 aus: <[Link]
BCr_den_Einsatz_im_Unterricht#Einleitung>

23
Teil I.

Grundlagen

25
1. Was ist Python?
Always look on the bright side of life
(Eric Idle 1 )

1.1. Der Name


Python? Ein Tier? Eine Schlange? Nein, eine Sprache!! Eine Programmiersprache!!
Und der Name dieser Sprache hat in erster Linie nichts mit der Schlange zu tun, sondern mit Monty
Python’s Flying Circus. Die Ritter der Kokosnuss“ oder Das Leben des Brian“ kennt wahrscheinlich
” ”
wirklich jeder, genauso wie wohl die meisten die bekanntesten Schauspieler dieser so britischen Komi-
kertruppe kennen: John Cleese, Michael Palin, Eric Idle. 2

Abbildung 1.1. Monty Python (CC by 2.0)

Wie Mark Lutz in seinem Buch Programming python“ 3 schreibt: You don’t have to run out and rent
” ”
The Meaning of Life or The Holy Grail to do useful work in Python, but it can’t hurt.“
Aus diesem Grund sollte sich niemand wundern, wenn typische Mustertexte in Python-Beispielen
Always look on the bright side of life“ oder And now for something completely different“ lauten. Es
” ”
fällt auf, dass Programmierer oft einen eigenen Sinn für Humor haben — besonders wenn sie Engländer
sind und Monty Python im Kopf haben.
1 Life of Brian
2 Bild lizensiert unter
3 [Programming Python], Seite 15

27
KAPITEL 1. WAS IST PYTHON? 1.2. WAS FÜR EINE SPRACHE?

1.2. Was für eine Sprache?


Aber was für eine (Programmier-)Sprache ist denn Python? Python ist
• keine Skriptsprache, aber man kann damit Skripte schreiben4
• eine objektorientierte Sprache, aber man muss keine Objekte (explizit) benutzen
• keine Sprache, mit der man Programme mit grafischen Oberflächen schreibt; aber man kann das
trotzdem sehr gut, weil es viele grafische Bibliotheken gibt
• eine der drei großen P-Sprachen: perl, php und eben Python. Python ist wirklich eine Sprache,
mit der man dynamische Web-Seiten erstellen kann. Und viele machen das. Es existiert sogar ein
Web-Applikations-Server, der in Python geschrieben ist und Python deswegen als interne Sprache
benutzt: Zope.
• eine der am häufigsten benutzten Sprachen im WWW. Wenn man sich fragt, in welcher Sprache
die Programme geschrieben sind, die weltweit am häufigsten benutzt werden, dann kommt man
auf Python. Glaubst Du nicht? Nur zwei Unternehmen, die Python wesentlich benutzen:
– Google
– You Tube
Überzeugt?
Dazu schreibt Mark Lutz: Mancher stellt da die Frage Wer benutzt überhaupt Python?“ Aber die

richtige Frage ist Wer benutzt denn Python nicht?“ 5

1.3. Warum Python und nicht eine andere Sprache?


Kann man denn wirklich mit einer Sprache, bei der der Erfinder an etwas wie Always look on the

bright side of life“ gedacht hat, etwas Sinnvolles machen, oder kommt da nur Blödsinn raus? Ach nein:
Der Sinn des Lebens“ .

Was sind also die Vorteile von Python als Programmiersprache?
1. Python-Code ist gut lesbar, oder wie Peter Walerowski sein Buch6 beginnt: Python-Programme

kann man lesen!“ Damit sind Python-Programme gut nachvollziehbar, damit gut zu verändern
und zu verbessern (Wartbarkeit).
Für den Programmieranfänger ist das nicht einzusehen, dass das tatsächlich ein wichtiges Krite-
rium ist. Wer länger programmiert, weiß es: ein Programm wird einmal geschrieben, hundertmal
getestet, tausendmal verbessert und verändert. Die Zeitersparnis, die sich ergibt, wenn ein Pro-
gramm gut lesbar ist und damit beim ersten Durchlesen (oder auch beim zweiten) verständlich
ist, ist enorm, und Zeit ist Geld.
2. Python-Code unterstützt die Wiederverwertbarkeit von Code durch Objektorientiertheit und die
Aufteilung von Code in Module.
Das Argument aus dem vorigen Punkt der Aufzählung gilt auch hier wieder: time is money.
3. Python-Code ist plattformunabhängig. Ein auf einem Rechner geschriebenes Programm in Python
ist meistens ohne Veränderung auf einem anderen Rechner lauffähig.
Selbstverständlich müssen die betriebssystembedingten Befehle jeweils angepasst werden, so zum
Beispiel Dateinamen, Verzeichnisnamen, die Trennzeichen zwischen Dateinamen und Verzeichnis-
namen und vieles mehr. Aber auch dazu gibt es in Python Bibliotheken, die das machen. Wahr-
scheinlich wird es vielen Programmierern so gehen, dass sie, wenn sie solche Systemaufrufe“

in Python benutzen, es sich durch den Kopf gehen lassen, ob sie einen für alle Betriebssysteme
gültigen Code schreiben könnten, und stellen dann fest: ja, in Python könnte ich das wahrschein-
lich selber schreiben.
4. Python bringt schon eine große Zahl von Bibliotheken mit, viele weitere können aus dem Internet
besorgt werden. Batteries included“ ist ein immer wieder gehörter oder gelesener Spruch, wenn

es um Python geht. Das meiste, was man für die tägliche Arbeit braucht, ist im Standard-Umfang
der Sprache dabei.
4 Skripte bezeichnen Programme, mit denen man andere Programme aufruft, Betriebssystem-Aufrufe macht, Geräte anspricht,
Dateien im Dateisystem manipuliert . . .
5 [Programming Python], S. 9
6 [Python], Seite 13

28
KAPITEL 1. WAS IST PYTHON? 1.3. WARUM PYTHON UND NICHT EINE . . .

5. Python-Code ist im Verhältnis zu Java-Code relativ kurz, im Verhältnis zu perl-Code sehr klar.
Wie Lutz in [Programming Python], S. 4, schreibt, sind Python-Programme nur ein Fünftel bis ein
Drittel so lang wie Programme in C++ oder Java. Schau einfach noch mal zurück zum Vergleich
zwischen perl, Python und Java
Eine schöne Seite, die eine Idee davon gibt, was die Unterschiede der Programmiersprachen sind,
ist <[Link] Unter den Aufgaben sind ein paar klassische
Probleme in verschiedenen Sprachen gelöst. Es lohnt sich wirklich, hier zweimal hereinzuschauen.
Schau zum ersten Mal jetzt rein, und schau Dir speziell Probleme an, bei denen auch eine Lösung
in Python vorliegt. Vergleiche den Code (insbesondere die Länge des Codes) von Python mit dem
in anderen Sprachen. Ich empfehle für einen ersten Blick die Lösungen zu Prüfziffer auf Euro-

Banknoten“. Ein zweites Mal kann man dann auf diese Seite schauen, wenn man einen ersten
Eindruck von Python hat, denn dann sieht man, warum Lösungen in Python nicht nur besonders
kurz, sondern vor allem besonders elegant sind.
6. Als Folge davon ist Python schnell bei der Entwicklung und Erstellung von Programmen. Die
Kürze der Programme, die im vorigen Punkt angesprochen wurde, bewirkt, dass man oft keine
Klimmzüge machen muss, um ein Problem zu lösen.
7. Python ist freie Software. Es ist in den meisten Linux-Distributionen schon enthalten, zu Windows
frei aus dem Internet herunterzuladen. Das heißt, dass die (Weiter-)Entwicklung von Python nicht
von den finanziellen Interessen eines Unternehmens abhängt, sondern von den Bedürfnissen der
Nutzer, also der Programmierer. Oder anders gesagt: die Sprache bleibt so schön, wie sie ist, wenn
WIR es wollen.
8. Python-Programme können wie ganz normale Programme ausgeführt werden; es gibt aber auch
eine Test-/Entwicklungsumgebung, in der man Programm-Fragmente leicht und ohne großen
Aufwand testen kann. Außerdem kann man Python-Code interaktiv auf der Shell / Komman-
dozeile schreiben.
9. Python hat eine gute Datenbank-Schnittstelle.
10. Die meisten (alle?) Python-Distributionen haben schon eine grafische Bibliothek dabei, nämlich
Tkinter. Die hat den Vorteil, dass sie freie Software ist (ich weiß, ich wiederhole mich). Außer-
dem ist Tcl/Tk selbständig lauffähig, das heißt, man kann für die grafische Oberfläche eine Art
Prototyping“ machen und dann das erzeugte Fenster relativ einfach nach Tkinter umwandeln.

11. Seit kurzer Zeit ist ein weiterer wichtiger Punkt dazugekommen: der Raspberry Pi. Wer sich diesen
Zigarettenschachtel-PC kauft, will ihn auch bedienen. Der wird in Python programmiert.

(Womit ich es geschafft habe, von der seriösen Zahl 10 (10 Gebote ...) wegzukommen, und auf der
närrischen Zahl 11 gelandet bin. Geschrieben im Juli 2014, zu der Zeit der Monty Python Reunion Show.
)
Inzwischen habe ich von C. Severance das Buch Python for Informatics“ durchgeblättert. In seinem

Vorwort schreibt er:

In 2003 I started teaching at Olin College and I got to teach Python for the first time. The
contrast with Java was striking. Students struggled less, learned more, worked on more in-
teresting projects, and generally had a lot more fun.

Bill Lubanovic schreibt in seinem Introducing Python“



Python is the most popular language for introductory computer science courses at the top
American colleges.

Warum nicht in Deutschland?


Gibt es auch Nachteile? Ja sicher! Aber die will ich hier nicht aufzählen, da ich ja von Python überzeugt
bin. Als größte Schwäche von Python — aber da muss man schon wieder etwas über die Ausführung
von Programmen in verschiedenen Sprachen wissen — muss die Ausführungsgeschwindigkeit ge-
nannt werden. Richtig. Nur wird das wahrscheinlich von uns (den Lesern und mir, dem Schreiber)
nur ein ganz kleiner Prozentsatz merken, denn Programme, die wir schreiben, sind so klein“, dass die

Ausführungsgeschwindigkeit kein ernstzunehmendes Kriterium ist. Wichtiger ist wahrscheinlich für
jeden von uns die gesamte Zeit, die wir in ein Programm stecken: die Zeit für den Entwurf, für die Um-
setzung, also die eigentliche Programmierung, die Zeit für die Tests und dann letztendlich die Laufzeit
des Programms. Dabei werden wir merken: Python ist schnell!!

29
KAPITEL 1. WAS IST PYTHON? 1.4. AUSFÜHRUNG VON . . .

1.4. Ausführung von Python-Programmen


Hier steht in der Überschrift der Begriff Programm“. Was ein Programm ist, wurde bisher aber noch

nicht erwähnt; und die Erklärung folgt auch erst im nächsten Kapitel.
Grundsätzlich unterscheidet man bei der Ausführung von Programmen zwei verschiedene Metho-
den: Programm-Code kann entweder interpretiert werden oder er wird kompiliert7 und das Kompilat
wird dann ausgeführt. Die unterschiedliche Verarbeitung wird in dem Bild dargestellt.

Abbildung 1.2. Interpreter und Compiler

Zuerst soll in kurzen Worten die zweite Methode beschrieben werden.


Das, was ein Programmierer schreibt, wird als Programm-Quellcode bezeichnet. Dieser Quellcode
ist in einer Programmiersprache geschrieben, die sich meistens vom Vokabular her an der englischen
Sprache orientiert. Dieser Quellcode ist vom Computer nicht zu verstehen, sondern muss erst mittels
eines eigenen Programms in Maschinensprache — das sind die langen Reihen von Nullen und Einsen
— umgewandelt, auf englisch compiliert, werden.

Abbildung 1.3. Compiler

Python wird nicht compiliert, sondern interpretiert. Das Programm, das Python-Quelltexte interpre-
tiert, heißt auch python (allerdings mit kleinem p“). Ein Interpreter“ liest einen Quelltext zeilenweise
” ”
und führt die Anweisung, die diese Zeile enthält, aus. Wenn Python auf dem Rechner installiert ist 8 ,
kann man diesen Interpreter sofort aufrufen.9 Das machen wir jetzt! Nachdem der Interpreter sich mit
7 Englisch wird dieses Wort und alle davon abgeleiteten natürlich mit c“ geschrieben, im Deutschen mit k“ aber im folgenden
” ”
Text wird es in beiden Formen auftauchen. Compiler“ sieht nur so, mit C“, genießbar aus!
8 ” ”
das heißt auch, dass die Pfade alle richtig gesetzt sind
9 Das gilt für Linux- und Mac-Systeme. Unter den Windows-Systemen muss unter Umständen zuerst die Position des Python-
Interpreters in die Umgebungsvariablen eingetragen werden.

30
KAPITEL 1. WAS IST PYTHON? 1.4. AUSFÜHRUNG VON . . .

dem Python-Prompt ( >>> ) arbeitsbereit gemeldet hat, geben wir dem Interpreter die erste Aufgabe:

Abbildung 1.4. Interpreter

Brav, der Interpreter hat die Zeile richtig gelesen und die Aufgabe zu unserer Zufriedenheit gelöst.
Was passiert aber, wenn wir etwas ganz anderes, weniger sinnvolles, schreiben, oder mit Monty Python
And now for something completely different“?

Beispiel 1.4.1 Hier fehlt eine korrekte Zuweisung!
>>> The Spanish Inquisition
File "<stdin>", line 1
The Spanish Inquisition
ˆ
SyntaxError: invalid syntax

Python beschwert sich hier, weil hier etwas auftaucht, was es nicht erwartet.10 Diese 3 Wörter gehören
nicht zum Sprachumfang von Python.

10 Wer Monty Pythons Flying Circus gesehen hat, weiß es: Nobody expects the Spanish Inquisition!“

31
2. Programmieren

Computer programming is an art, because it


applies accumulated knowledge to the world,
because it requires skill and ingenuity, and
especially because it produces objects of
beauty.
(Donald E. Knuth1 )
There are two ways of constructing a software
design: One way is to make it so simple that
there are obviously no deficiencies, and the
other way is to make it so complicated that
there are no obvious deficiencies
(C. A. R. Hoare2 )

2.1. Was heißt Programmieren“?



In grauer Vorzeit, also etwa vor 50 Jahren, wurden Computer hauptsächlich dazu benutzt zu rech-
nen (denkt heute noch irgendjemand daran, wenn er seinen Rechner einschaltet, dass der rechnen
könnte oder sollte).3 Heute, in den ersten Jahren des 21. Jahrhunderts, wird der Computer meistens
dazu benützt, Zeichenketten, so die allgemeinste Bezeichnung für etwas, das sowohl Buchstaben als
auch Ziffern und Sonderzeichen zum Inhalt hat, zu bearbeiten.4
Was macht ein Programmierer also? Er schreibt Programme. Na gut, das hilft auch nicht weiter. Oder
doch? Ein Programm ist ein Algorithmus, der von einer Maschine abgearbeitet werden kann. Algorith-
mus? Nehmen wir doch dafür einfach mal die Beschreibung Kochrezept“.5 Wer schon einen Algorith-

mus formuliert hat, der weiß, dass die Umgangssprache oft nicht das geeignete Werkzeug dazu ist, da
die Umgangssprache Mehrdeutigkeiten zulässt. Wenn man etwa das erste Kochrezept auf der in der
Fußnote zitierten Seite betrachtet, dann wird auch dem in Küchendingen nicht so bewanderten Leser
klar sein, dass es einen Unterschied macht, ob man einen oder zwei zarte Elefanten“ nimmt. Also ist es

angebracht, eine formale Sprache zu entwerfen, die Mehrdeutigkeiten vermeidet. Existiert eine solche
formale Sprache, dann muss man noch einen Übersetzer schreiben, der den Algorithmus, geschrieben
in dieser formalen Sprache, in die Maschinensprache des Rechners übersetzt.
Ein Algorithmus besteht aus einzelnen Anweisungen. Oft benützt man statt Anweisung das Wort
Befehl“ oder das englische Wort statement“ Ein Befehl ist eine Wortfolge, die aus Wörtern besteht,
” ”
die der Computer, genauer die Programmiersprache, kennt, die nach Regeln aneinandergereiht werden,
die den Regeln der Programmiersprache genügen.

1 zitiert nach: [Link] Knuth


2 zitiert nach: [Link] A. R. Hoare
3 Das Beste, was ich zu diesem Thema gesehen habe, war ein (ernstgemeinter!! wirklich!!) Artikel mit Bild in einer Tageszeitung
über einen Sachbearbeiter einer Behörde. Auf dem Bild waren zu sehen: vor ihm der Computer, in der Hand der Taschen-
rechner. Darunter als Bildunterschrift sinngemäß etwa, dass der Computer diesem guten Menschen viel Arbeit abnimmt, aber
dass der gute Sachbearbeiter manche Sachen eben doch noch mit dem Taschenrechner berechnen muss. So weit zum Thema
Volksverdummung.
4 So wie ich das gerade auch mache (obwohl Programmieren oder Mathematik mir jetzt mehr Spaß machen würde).
5 Beispiele für Kochrezepte findet man z.B. unter <[Link]
t=2769129>

33
KAPITEL 2. PROGRAMMIEREN 2.1. WAS HEISST PROGRAMMIEREN“?

2.1.1. Warum soll man überhaupt programmieren lernen?


Most of the good programmers do
programming not because they expect to get
paid or get adulation by the public, but
because it is fun to program.
(Linus Torvalds 6 )
Für das Lernen einer natürlichen Sprache gibt es meistens ganz natürliche Gründe: man lernt Spa-
nisch, weil man im nächsten Urlaub nach Spanien fahren will, man lernt Französisch, weil man Sartres
Huis Clos“ im Original lesen will, man lernt Italienisch, weil man eine nette Italienerin oder einen

netten Italiener kennengelernt hat, mit dem man sich auch manchmal in deren bzw. dessen Sprache
unterhalten möchte.
Aber was gibt es für Gründe, eine Programmiersprache zu lernen?
• Will ich den Computer bedienen oder beherrschen?
• Will ich verstehen, wie ein so komplexes Programm wie eine Textverarbeitung aufgebaut ist?
• Will ich wissen, warum ein Computer kein Schwäbisch versteht? Und warum er überhaupt keine
natürliche Sprache versteht?
• Habe ich ein spezielles Problem, von dem ich im Prinzip“ weiß, wie man das lösen könnte, aber

noch nirgends eine Lösung für den Computer gefunden habe?
• Muss ich am Computer immer wieder die selben stupiden Arbeiten erledigen, von denen ich den-
ke, dass sie so stupide sind, dass der Computer das alleine können sollte?
Vielleicht weil ich eine dieser Fragen beantworten will!
Wenn man dann einen Einstieg gefunden hat, fallen einem auch ganz schnell Dinge ein, die für einen
Menschen langweilig sind, weil sie die Intelligenz eines Menschen unterfordern, um nicht zu sagen:
manche Arbeiten sind eine Beleidigung für intelligente Menschen. Maschinen sind da nicht so schnell
beleidigt, und vor allem sind Maschinen auch nicht dadurch aus der Fassung zu bringen, dass man sie
auffordert, immer wieder das selbe zu machen.
Nehmen wir ein zugegeben sehr unrealistisches Beispiel (obwohl vielleicht die Linguisten das nicht
uninteressant finden): suche in einem etwas längeren Text, nehmen wir also mal von Marx Das Kapital“

oder die Bibel, das Wort mit 5 Buchstaben, das am häufigsten auftritt. Wer wollte das von Hand machen?
Und wer wäre sicher, dass er keinen Fehler, weder beim Buchstabenzählen der einzelnen Wörter noch
beim Zählen der verschiedenen 5-buchstabigen Wörter macht?
Nach einigen Stunden Programmierung wäre das Problem selbst für einen Anfänger kein Problem
mehr. Es wäre vielleicht noch eine Herausforderung, aber in Python ist ein Programm, das genau die
oben geschilderte Aufgabe löst
• kurz
• schnell zu schreiben
• und absolut sicher
Dem Computer ist es dabei völlig egal, welche Bedeutung der Text hat, den er gerade verarbeitet, Das

Kapital“ und die Bibel sind für ihn nur Mengen von Zeichen, die er nach bestimmten von uns vorge-
gebenen Regeln zu durchsuchen hat. Er wird nicht müde dabei, ihn langweilt es nicht, er muss keine
Pausen machen, er arbeitet einfach, bis er fertig ist.
Beim Schreiben des Programms tut man etwas sehr menschliches, man trainiert seine Intelligenz, und
während das Programm läuft, kann man etwas machen, was dem Menschen angemessener ist, als auf
Hunderten von Seiten Buchstaben zu zählen (übrigens nicht sehr lange, denn das Programm wäre sehr
schnell mit seiner Arbeit fertig).
Und man ist kreativ! Wir erinnern uns vielleicht an die ersten Holzbauklötzchen, kleine, bunte Qua-
der, mathematisch eine ziemlich langweilige Form. Trotzdem konnten wir als kleine Kinder damit
Häuser, Drachen, Ritter, Bäume und vieles anderes bauen. Die Phantasie macht es! Später kamen dann
Lego-Steine, die flexibler waren und besser zusammenhielten, und auch hier konnte man mit einfa-
chen Formen recht komplexe Gebilde machen.7 Programmieren ist irgendwie ähnlich: aus einfachen
(programmier-)sprachlichen Strukturen kann man mit viel Kreativität komplexe Programme schreiben.
6 zitiert nach: [Link] Torvalds , dort: Rishab Aiyer Ghosh, interviewer (1998-03-02). First Monday
Interview with Linus Torvalds: What motivates free software developers?
7 Ob die Lego-Baukästen, die heutzutage viele Spezialsteine enthalten, dafür aber nur noch ermöglichen, ein bestimmtes Objekt

zu bauen, die Kreativität genauso fördern?

34
KAPITEL 2. PROGRAMMIEREN 2.2. WAS IST ALSO EIN PROGRAMM?

Programmieren lehrt Lernen. Wo sonst kann ich Fehler machen, die zwar gleich bestraft werden (da-
durch, dass das Programm nicht läuft), aber die ich verbessern kann, ohne dass jemand anderer mich
deswegen tadelt. Dabei lerne ich, dass Lernen nicht nach dem ersten Versuch, ob erfolgreich oder nicht,
endet, sondern dass Lernen daraus besteht, etwas aufzunehmen, es anzuwenden, festzustellen, dass ich
es doch noch nicht beherrsche, und es dann nochmals zu versuchen.
Kapiert? Fehler sind in Ordnung!!! ... wenn man bereit ist, sie zu verbessern.8

2.1.2. Sprache lernen


Eine Programmiersprache zu lernen ist gar nicht so verschieden vom Lernen einer natürlichen Sprache.
Man muss Vokabeln lernen und die Grammatik beherrschen. Das Vokabelnlernen ist in einer Program-
miersprache aber schön überschaubar: schau doch mal bei den reservierten Wörtern nach, wie viele
Vokabeln das sind! Die Grammatik ist ein bißchen aufwendiger. Hier geht es darum, zu lernen, wie
man in der Programmiersprache korrekte Sätze“ bildet. Das wird mit Syntax“ bezeichnet, und hier
” ”
ist die große Hürde, dass die Syntax einer Programmiersprache im Gegensatz zu der einer natürlichen
Sprache keine Varianten zulässt. Wenn in einer natürlichen Sprache die Syntaxregel Subjekt - Prädikat

- Objekt“ gilt, dann ist ein Satz“ zwar nicht korrekt, aber oft noch verständlich, der sich nicht an die-

se Regel hält. Ein Satz in einer Programmiersprache, der sich nicht an eine Syntax-Regel hält ist falsch
und unverständlich, was bedeutet, dass ein Programm mit einem solchen falschen Satz einfach nicht
ausgeführt wird.

2.1.3. Übersetzung ... in welche Sprache denn?


Für diese Übersetzung gibt es vom Prinzip her 2 Möglichkeiten:

1. Das in einer Programmiersprache geschriebene Programm, der sogenannte Quelltext oder auf
neudeutsch die Source, wird als ganzes in Maschinensprache umgewandelt. Dabei wird es auf
Syntaxfehler untersucht; im Falle, dass Syntaxfehler auftreten, wird die Umwandlung abgebro-
chen und eine Fehlermeldung ausgegeben.
Falls Programmcode aus anderen Quell-Dateien benutzt werden soll, wird dieser auch eingebun-
den. Das Ergebnis wird als Datei auf die Festplatte des Rechners geschrieben und liegt ab diesem
Zeitpunkt in Maschinensprache vor. Beim erneuten Aufruf des Programms wird diese Datei be-
nutzt.
Dieser Übersetzer wird Compiler genannt.
2. Das Programm, das als Quellcode vorliegt, wird Befehl für Befehl in Maschinensprache übersetzt
und ausgeführt. Das bedeutet insbesondere, dass auf die Festplatte des Rechners keine Datei mit
einem ausführbaren Programm geschrieben wird. Bei jedem erneuten Aufruf des Programms wird
der Quelltext wieder Zeile für Zeile abgearbeitet.
Ein Programm, das diese Arbeit verrichtet, wird Interpreter genannt.

Man kann es auch so beschreiben: nachdem ein Compiler den Quellcode in ein ausführbares Programm
umgewandelt hat, kann man dieses Programm immer wieder laufen lassen, ohne es neu zu kompilieren,
auf jeden Fall auf dem selben Computer, aber auch auf jedem Rechner mit dem selben Betriebssystem.
Ein interpretiertes Programm benötigt aber für jeden weiteren Programmlauf wieder den Interpreter,
um den Quellcode Zeile für Zeile in einen ausführbaren Befehl umzuwandeln.

2.2. Was ist also ein Programm?


Im vorigen Kapitel haben wir schon gesehen, dass Python interpretiert wird. Das bedeutet insbesondere,
dass, sofern Python installiert ist und der Interpreter zur Verfügung steht, eine (korrekte) Anweisung in
Python ausgeführt werden kann. Aber eine Anweisung ist noch kein Programm; na ja, jedenfalls kein
richtiges Programm.
Ein Programm besteht nach der klassischen Definition aus einer Eingabe, einer Verarbeitung und ei-
ner Ausgabe. Man spricht deshalb vom EVA-Prinzip, wenn man die Anfangsbuchstaben der 3 Bereiche
aneinanderreiht. Heutzutage erfolgt die Eingabe meistens über die Tastatur, die Verarbeitung ist das
8 Ja, ich bin für Verbesserungen bei Klassenarbeiten, Hausaufgaben etc.!!!

35
KAPITEL 2. PROGRAMMIEREN 2.3. GESCHICHTE

Ausführen eines Algorithmus, so wie er durch den Programmcode vorgegeben ist und das Ausgabeme-
dium ist standardmäßig der Bildschirm.

2.3. Geschichte
Im Laufe der vergangenen 50 Jahre wurden viele solche formale Sprachen entworfen, meistens mit dem
Ziel, Probleme aus einem bestimmten Anwendungsbereich zu lösen. Zu diesen Programmiersprachen
wurden dann auch verschiedene Compiler entwickelt, verschiedene, weil es verschiedene Zielrechner
und damit verschiedene Maschinensprachen gibt, aber auch, weil es manchmal an einem Compiler
Verbesserungsmöglichkeiten gab, auch, weil handfeste wirtschaftliche Interessen dahinterstecken.

A NMERKUNG
Die Sprache COBOL wurde zum Beispiel entworfen, um vor allem administrati-
ve oder wirtschaftliche Probleme zu lösen, die Sprache Fortran, um technische,
mathematische oder naturwissenschaftliche Probleme zu bearbeiten, bei denen
es darauf ankam, große Mengen an Zahlen zu bearbeiten, die Sprache C ent-
stand, weil man eine Sprache benötigte, die sehr maschinennah arbeitet aber
trotzdem leicht zu programmieren ist. Dabei gilt, dass jede Programmiersprache
(mit Einschränkungen) alles kann, aber nicht alles gleich gut. Die wenigsten Pro-
grammierer hätten Spaß daran, Mathematik-Programme in COBOL zu schrei-
ben!!

Es gibt aber auch Programmiersprachen, die für eine breite Vielfalt von Problemstellungen geeignet
sind, die genausogut für die Verarbeitung von Zahlen wie für die Verarbeitung von Texten genommen
werden können. Welche Programmiersprache man lernt, und auch, welche Programmiersprache man
später hauptsächlich benutzt, hängt von den persönlichen Vorlieben ab: denen des Lehrers und später
den eigenen. Die erste Programmiersprache, die man lernt, sollte aber vor allem eines sein: leicht zu
erlernen.

2.4. Was braucht man, um mit Python zu arbeiten?


Nun, man braucht zuerst einmal Python selber. Python ist eine Programmiersprache (ich weiß, ich wie-
derhole mich), aber als eine solche ist sie zweierlei: erstens ein Konzept, eine Idee. Irgendjemand, genau-
er gesagt Guido von Rossum, ist auf die Idee gekommen, dass es doch gut wäre, wenn es ein Programm
gäbe, das bestimmte Anweisungen versteht und sie ausführen kann. Also hat Guido sich vorgenom-
men, einen Entwurf zu schreiben, in dem erst einmal steht, welche Vokabeln das Programm kennen
soll und dann, welche grammatikalischen Regeln gelten sollen, um diese Wörter zu sinnvollen Sätzen
zusammenzufügen. Das ist das Konzept.
Und zweitens ist Python natürlich ein Programm, damit eine Datei (genauer gesagt: ein ganzes Paket
von Dateien), das eine Umsetzung von Guidos Konzept bildet.
Also muss sich jeder, der in Python programmieren will, diese Datei besorgen. Und da haben wir
Glück: Python (als Konzept) und die Dateien, die Python auf einem Rechner ausführbar machen, sind
freie Software.9 Freie Software“ hat etwas mit Freiheit zu tun, nicht mit dem Preis. Um das Konzept zu

verstehen, ist an frei“ wie in freier Rede“ 10 , und nicht wie in Freibier“ zu denken.11
” ” ”

9 hierzu sollte man sich das gute Buch von Grassmuck [Freie Software] besorgen, das — das Thema erfordert es ja schon — auch
fast frei“ ist, nämlich bei der Bundeszentrale für politische Bildung für einen geringen Unkostenbeitrag zu erhalten ist. siehe:

<[Link]>
10 [FSF]
11 Hat eigentlich schon einmal jemand untersucht, inwiefern Freibier die Entwicklung freier Software fördert?

36
KAPITEL 2. PROGRAMMIEREN 2.5. HILFSPROGRAMME

A NMERKUNG
So ist Python unter jedem gebräuchlichen Betriebssystem verfügbar. Linux-
Benutzer haben den Vorteil, dass Python zu fast jeder Distribution dazugehört
und meistens bei Standard-Installationen mitinstalliert wird, weil einige Program-
me unter Linux eben Python benötigen.

Unter Microsoft-Betriebssystemen 12 muss Python gesondert besorgt werden.


Falls dieser Text auf CD zu Dir gekommen ist, ist die Chance groß, dass auch in einem Verzeichnis
Windows“ auf dieser CD alle Programme sind, die zur Arbeit mit Python nötig sind, zusammen mit ei-

ner README-Datei und einem Installationsprogramm ([Link]), das alles für den Betrieb von Python
erledigt.

2.5. Hilfsprogramme
Als wichtigste Voraussetzung für das Programmieren wird ein Editor benötigt. Das ist KEIN Textverar-
beitungsprogramm. Open Office und Word und wie die Textverarbeitungsprogramme alle heißen sind
ungeeignet. Ein Editor soll keine Formatierungsanweisungen produzieren, sondern den Text genauso
speichern, wie ich ihn eingebe.
Wohl aber soll ein Editor die Strukturen einer Programmiersprache unterstützen. Die bei Windows
mitgelieferten Editoren (Wordpad, Editor) sind aus diesem Grund ungeeignet. Unter Unterstützung
einer Programmiersprache verstehe ich:

• Der Editor sollte bestimmte Konstrukte einer Sprache farblich hervorheben (englischer Fachaus-
druck: syntax highlighting)
• Der Editor sollte mehrere Dateien parallel geöffnet halten können. Du wirst es schnell merken,
dass es Deine Arbeit ungemein erleichtert, wenn Du im Editor Dein letztes Werk neben der aktu-
ellen Arbeit sehen kannst, denn meistens verwendest Du eine Technik, die beim letzten Programm
erfolgreich war, gleich noch einmal.
• Ein Editor sollte das Ordnunghalten unterstützen und, das ist bei Python besonders wichtig, die
vorgeschriebenen Ordnungskriterien beherrschen. Damit ist gemeint, dass der Editor automatisch
die zusammengehörigen Dinge als zusammengehörig sichtbar macht.
• Der Editor sollte automatische Wortvervollständigung beherrschen. Damit ist gemeint, dass der
Editor bei allen längeren Wörtern, die ich tippe, in seinem Gedächtnis kramt und einen sinnvollen
Vorschlag macht, wie das Wort jetzt zu Ende geschrieben wird. Das wird auch jeder schätzen,
wenn ein Programm einen gewissen Umfang erreicht. Und die Anwendung dieser Fähigkeit hilft
bei der Reduzierung der Fehlerzahl. Wenn ich eine Variable mindestAbnahme deklariert habe,
dann hilft es Tippfehler zu vermeiden, wenn ich nach den ersten 3 Buchstaben min“ schon den

Vorschlag destAbnahme“ bekomme. Wenn ich dieses Wort zehn Mal tippen müsste, dann würde

ich sicher den einen oder anderen Fehler machen.

Es gibt viele Editoren, die diese Bedingungen erfüllen und Open Source Software sind. Die sind meis-
tens von Programmierern für Programmierer gemacht — wirklich nicht die schlechteste Voraussetzung.
Da möge jeder sich seinen Lieblingseditor heraussuchen. Der beste Editor ist immer der, mit dem ich
selber gut auskomme.
Zwei Vorschläge mache ich trotzdem:

1. atom erfüllt diese Bedingungen, und wer seinen Editor nach seinen Bedürfnissen einrichten möchte,
liegt hier richtig. 13
2. SciTE (beachte die Groß-/Kleinschreibung) ist Open Source, und SciTE gibt es für Windows und
für Unix/Linux.

Ein Programm in einer Skriptsprache wie Python wird anfangs in einer Shell (für Windows-Benutzer:
auf der Kommandozeile) aufgerufen und macht seine Ausgaben genau dort. Deswegen sollte jeder die
12 , die ab jetzt einfach mit Windows bezeichnet werden, gleichgültig welcher Ausprägung (Windows XP, Vista etc.)
13 Nicht nur, wenn er programmieren will. Auch diesen Text in XML schreibe ich mit atom.

37
KAPITEL 2. PROGRAMMIEREN 2.6. VORAUSSETZUNGEN

wichtigsten Shell-Befehle (für Windows-Benutzer: die guten, alten DOS-Befehle) kennen und auch auf
der Shell sich im Verzeichnisbaum zurechtfinden.
Die nächste Stufe der Hilfsprogramme sind die Integrierten Entwicklungsumgebungen“, kurz IDE

(Integrated Development Environment). Hier existieren nebeneinander ein Editor, eine Shell, oft noch
ein Debugger und öfters noch andere Anwendungen unter einem Dach. Für Python bietet sich in erster
Linie Eric“ an, allerdings muss auf Windows noch eine Qt-Bibliothek installiert werden. Eine Alterna-

tive auf Windows ist der PyScripter, der auch Open Source ist. Eher spartanisch, aber für die Belange
eines Anfängers völlig ausreichend, ist die IDE geany“, natürlich auch Open Source.

2.6. Voraussetzungen
2.6.1. Das Dateisystem
Als Vorkenntnisse sollte man einiges über die Organisation des Dateisystems auf dem eigenen Rechner
wissen, nämlich was eine Datei, was ein Verzeichnis ist, wie man Verzeichnisse anlegt, Dateien kopiert,
umbenennt, verschiebt. Hilfreich ist, wenn man das nicht nur mittels einer grafischen Oberfläche14 kann,
sondern auch als Betriebssystem-Befehl (also unter Linux auf einer shell und unter Windows auf der
Kommandozeile). Aber das ist wahrscheinlich im 21. Jahrhundert zuviel verlangt. Mark Lutz schreibt in
einer Fußnote seines Buches [Programming Python] auf Seite 266,

In the first edition of the book Learning Python, for example, my coauthor and I directed
readers to do things like open a file in your favourite text editor“ and start up a DOS
” ”
command console“. We had no shortage of email from beginners wondering what in the
world we meant.

Dem ist fast nichts hinzuzufügen. Oder doch? Eine Frage sei erlaubt: Warum richten sich Dozenten,
Lehrer, Didaktiker nach dem, was große Konzerne propagieren, nämlich, dass man Computer bedienen
kann, ohne zu verstehen, was man da tut und warum legen sie nicht mehr Wert darauf, dass Prinzipien
des Computers verstanden werden, bevor man mit einer schönen grafischen Oberfläche herumspielt?
Also muss man sich (oder als Dozent: den Lernenden) zuerst einmal klarmachen, dass das, was man
in einen Editor oder in eine Entwicklungsumgebung eingibt, erst dann im Rechner“ ist, wenn man es

in einer Datei gespeichert hat. Zum Glück bieten sowohl Editoren als auch Entwicklungsumgebungen
hier Icons an, mit Hilfe derer man diese Operationen durchführen kann. Nach dem Anwählen dieser
Icons öffnet sich in der Regel ein Fenster, in dem man

1. angeben kann, in welchem Verzeichnis


2. und unter welchem Dateinamen

die Datei gespeichert werden soll. Zum zweiten Punkt folgt gleich noch ein eigenes Unterkapitel. Hier
soll allerdings schon auf die Eigenart eines Software-Konzerns von der Westküste der USA eingegan-
gen werden. Die Entwickler, die für diesen Konzern ein Betriebssystem“ entworfen haben, meinen seit

einigen Jahren, dass sie wissen, was wir, die Benutzer wollen. So ist unter diesem Betriebssystem stan-
dardmäßig eingestellt, dass in allen Dateisystem-Betrachtern, also auch bei dem, der beim Speichern
einer Datei aufgerufen wird, bekannte Dateiendungen“ nicht angezeigt werden. Das führt oft zu uner-

warteten Schwierigkeiten und ungeahnten Ergebnissen.

A CHTUNG

Wer unter Windows ernsthaft arbeiten will, sollte sich von Microsoft nicht bevor-
munden lassen und sofort den Schalter umlegen, um grundsätzlich alle Dateien-
dungen anzeigen zu lassen.

14 Glück gehabt! Das [dummdeutsch]e Wort Benutzeroberfläche“ konnte ich im Text gerade noch vermeiden. Der Benutzer bin

ich, meine Oberfläche nenne ich Haut, und was die auf einem Computer-Bildschirm soll, habe ich noch nie verstehen können.

38
KAPITEL 2. PROGRAMMIEREN 2.6. VORAUSSETZUNGEN

2.6.2. Regeln für Dateinamen


Es gibt einen großen Software-Konzern, der versucht, seinen Benutzern weiszumachen, dass Datei-
und Verzeichnisnamen Sonderzeichen und Leerzeichen enthalten dürfen. Nun, über die Sonderzeichen
könnte man noch diskutieren. Aber dann muss auch gewährleistet sein, dass jedes mögliche Betriebssys-
tem in jeder möglichen Lokalisierung15 auch diese Sonderzeichen anzeigt, und diese Fähigkeit auch an
alle vom Betriebssystem aufgerufenen Programme weitergibt. Bei den Leerzeichen hört aber der Spaß
auf. Ein Leerzeichen ist im normalen Text das Zeichen, das zwei Wörter voneinander trennt; es trennt
zwei Informationseinheiten voneinander. Aus der Sicht des Betriebssystems ist aber ein Datei- bzw. Ver-
zeichnisname eine Informationseinheit. Da hat ein Leerzeichen überhaupt nichts zu suchen.

A CHTUNG

Wer unter Windows die IDE pyscripter“ benutzt, merkt es sehr schnell, dass er

Leerzeichen in Dateinamen hat: das Programm hängt sich auf.

Das im vorigen Absatz Gesagte gilt auch für Verzeichnisnamen. Auch hier haben Sonderzeichen und
Leerzeichen nichts zu suchen.

2.6.3. Datei-Operationen
Falls man die nötigen Befehle des Betriebssystems nicht beherrscht, sollte man sich ein Handbuch neh-
men und nachschlagen, wie man unter seinem Betriebssystem

• eine Datei anlegt


• eine Datei löscht
• eine Datei kopiert
• eine Datei verschiebt / umbenennt
• ein Verzeichnis anlegt
• ein Verzeichnis löscht
• einen Link auf eine Datei anlegt (geht das überhaupt unter den Microsoft-Betriebssystemen?) 16
• Zugriffsberechtigungen liest
• Zugriffsberechtigungen setzt

Ohne den Anspruch der Vollständigkeit gebe ich hier die Befehle, die für die oben aufgelisteten Ope-
ration benutzt werden, unter Unix-artigen Betriebssystemen und unter Windows in einer Tabelle wieder.

Tabelle 2.1. Betriebssystem-Befehle


Aktion Unix/Linux Windows
Datei anlegen touch dateiname
Datei löschen rm dateiname del dateiname
Datei kopieren cp alteDatei neueDatei copy alteDatei neueDatei
Datei verschieben / umbenennen mv alteDatei neueDatei ren alteDatei neueDatei
Verzeichnis anlegen mkdir verzeichnisname md verzeichnisname
Verzeichnis löschen rmdir verzeichnisname rmdir verzeichnisname
Link auf eine Datei anlegen ln originalName neuerName
Zugriffsberechtigung lesen ls -l dateiname attrib dateiname
Zugriffsberechtigung setzen chmod xxxx dateiname attrib xxxx dateiname

15 also
der Einstellung der Sprache der Darstellung
16 Einen Link auf eine Datei anzulegen bedeutet, dass die Datei nur einmal existiert, aber unter verschiedenen Namen angespro-
chen werden kann. Das erscheint sinnlos? Ist es aber nicht. Mit Name“ ist dabei natürlich der voll-qualifizierte Name gemeint,

d.h. dass vor allem in einem Verzeichnis die reale“ Datei existiert, in einem anderen Verzeichnis nur der Link, der Verweis

auf die Originaldatei.

39
KAPITEL 2. PROGRAMMIEREN 2.7. WAS HEISST PROGRAMMIEREN“? . . .

2.7. Was heißt Programmieren“? Fortsetzung!



Without a program,
a computer is an overpriced door stopper.

—David Evans17

Programmieren heißt erst einmal, Befehle (Anweisungen, oft auch mit dem englischen Wort statements
bezeichnet) zu schreiben, die der Computer mit Hilfe von Python (oder einer anderen Programmierspra-
che) versteht und ausführen kann. Aber warum soll der Computer das machen? Erstens: er kann vieles
schneller als ich. Zweitens: ihm wird nicht so schnell langweilig wie mir. Drittens: auch nach Stunden
wird er nicht müde und macht deswegen keine Leichtsinnsfehler.

2.7.1. Strukturierte Programmierung: Ein Überblick

Lerne gehen, bevor du rennen lernst.

—unbekannt

Gerade im Hinblick auf Programmieranfänger, vor allem Schüler, wurde die objektorientierte Pro-
grammierung als die Errungenschaft gefeiert, die einen intuitiveren Zugang zur Programmierung ver-
schafft und so die Einstiegshürden senkt. Leider wurde dabei übersehen, dass das beste (objektorientier-
te) Paradigma nichts nützt, wenn Lernende nicht wissen, was an der Basis passiert: was eine Variable
ist, was WENN - DANN“ bedeutet, was eine Wiederholung ist und vieles mehr. Nein, das ist noch

nicht die Basis: dazu gehört auch, dass man weiß, was Bedingungen sind und wie man diese formuliert,
wie man einer Variablen einen Wert zuweist, wie eine Wiederholung beendet wird usw.
Lehrer, die an Schulen unterrichten, wissen, was ich meine. Da wird etwa in der Mittelstufe ein
schlichtes Anwendungsprogramm zur Tabellenkalkulation benutzt, und man muss froh sein, wenn die
Schüler mit viel Anleitung verstehen, wie man darin die WENN-DANN“-Funktion benutzt. Und jeder

Lehrer weiß, wieviel davon im darauffolgenden Schuljahr noch vorhanden ist.
Ich bin überzeugt, dass der Einstieg in die (objektorientierte) Programmierung nicht geht, wenn man
nicht die oben beschriebenen Grundlagen beherrscht: wenn man nicht die elementaren Regeln der struk-
turierten Programmierung gelernt hat. Und so ist dieses Buch auch aufgebaut: die Objektorientierung
kommt ziemlich weit hinten.
Die langweiligste Art der Programmierung ist die, dass man einem Rechner die Aufforderung gibt,
zehn oder hundert oder tausend verschiedene Befehle nacheinander auszuführen. So etwas wird eine
Sequenz genannt. Das bedeutet, dass ich dem Rechner erst einmal diese vielen Befehle aufschreiben
muss. Die meisten von uns würden das als völlig uneffektiv ablehnen, denn in der Zeit, in der wir die
Befehle aufgeschrieben hätten, hätten wir das Problem schon zu Fuß“ gelöst.

In der Frühzeit der Datenverarbeitung war das allerdings ein übliches Vorgehen. Es gab verhältnismäßig
wenige Rechner und relativ viele Benutzer, es gab wenige Eingabegeräte und wenige Ausgabegeräte.
Also habe ich meine Befehle aufgeschrieben, irgendwann in der Nacht hat ein freundlicher Mitarbei-
ter des Rechenzentrums meine Befehle dem Computer zum Fressen gegeben und am nächsten Morgen
konnte ich das Ergebnis abholen.
Interessanter ist es da schon, den selben Befehl tausendmal ausführen zu lassen. Das ist doch schon
eine ganz schöne Zeitersparnis: ich schreibe einen Befehl auf und weise meinen Rechenknecht an, das
doch bitte 3000mal zu machen.18 Dies wird in der Datenverarbeitung eine Schleife, mit einem Fremd-
wort Iteration, genannt.
Es ist auch interessanter für uns, wenn wir dem Rechner überlassen können, was er macht, zum
Beispiel in allen Dateien, in denen sowohl das Wort Salat“ als auch das Wort Gurke“ auftaucht, die
” ”
Gurke durch eine Salatgurke zu ersetzen, in allen anderen die Gurke durch eine Gewürzgurke. Der
Rechner (das Programm) steht also vor der Alternative: entscheide mal, ob das eine Salatgurke oder
17 aus: [Evans], S. 35
18 Denken wir an unsere Schulzeit zurück und die Strafarbeit: Du schreibst jetzt 100mal Ich soll meinen Nachbarn nicht mit der

Stecknadel pieksen.“

40
KAPITEL 2. PROGRAMMIEREN 2.7. WAS HEISST PROGRAMMIEREN“? . . .

eine Gewürzgurke ist, aber bitte intelligent! Diese Entscheidung wird in der Programmierung eine Al-
ternative genannt.
Das sind also die Elemente der strukturierten Programmierung:

• die Sequenz

• die Alternative

• die Iteration

A NMERKUNG
Soll ein Programm-Quelltext (in Python) Kommentare enthalten? Allgemein gilt:
den Programm-Quelltext sollte nicht nur ich, der Schreiber, auch noch nach eini-
gen Monaten oder Jahren verstehen können, sondern auch ein eventueller Le-
ser, der etwas an dem Programm ergänzen oder verbessern möchte. Hilfreich
dabei ist natürlich, dass man die Variablen, grundsätzlich alle Bezeichner, mit
Namen versieht, die auf die Bedeutung verweisen. Natürlich könnte man bei-
spielsweise in einem Programm zur Berechnung von Größen in rechtwinkligen
Dreiecken die Variablen so benennen: Gandhi, Hilde und Schatzi Aber ob
dadurch der folgende Quelltext besonders verständlich wäre, ist doch zu be-
zweifeln: Schatzi = Gandhi / Hilde Etwas besser wäre schon die Benennung
gegenkathete, hypotenuse und sinus womit das obige Programmfragment
zu sinus = gegenkathete / hypotenuse wird und damit doch verständlicher.
Trotzdem: auch so würde das wahrscheinlich kein Programmierer schreiben,
denn diese Spezies Menschen zeichnet sich durch Faulheit aus, und selbst bei
Editoren, die automatische Wort-Ergänzung beherrschen, ist das für viele Pro-
grammierer zu viel Schreibarbeit, weswegen man eher etwas fände wie sin =
gegenk / hyp
Manchmal ist es aber hilfreich, wenn man im Quelltext eine kurze Erläuterung fin-
det, was die Variable für eine Bedeutung hat. Mathematiker speziell — das sind
in der Regel noch faulere Menschen als Programmierer — benennen Zähler
grundsätzlich mit i, wenn sie einen weiteren Zähler brauchen, heißt der i2
und das Optimum an Kreativität ist der Name j für einen weiteren Zähler. Ein
häufiges Problem in der Informatik ist es, eine Matrix zu durchsuchen. Dazu
benötigt man in der Regel zwei Zähler, einen für die Zeilen, einen für die Spal-
ten. Also, pfiffig wie Programmierer sind, werden diese beiden Zähler zz und sz
benannt. In einem Quelltext ist es dann durchaus sinnvoll, dass man dazu einen
Kommentar schreibt. Kommentare werden durch einen Lattenzaun (#) eingelei-
tet. Alles von diesem # bis zum Zeilenende wird von Python ignoriert und ist nur
für die Augen eines eventuellen Lesers bestimmt:

Beispiel 2.7.1 Kommentare


# zz ist der Zeilenzähler für die Matrix
# sz ist der Spaltenzähler für die Matrix
zz = 1

Eine besonders hilfreiche Eigenschaft von Kommentaren in Python ist, dass man damit eine einfache
Hilfe-Funktion für zum Beispiel eine Funktion schreiben kann. Der Hilfetext wird in die dreifachen
Anführungszeichen an den Anfang der zu beschreibenden Funktion geschrieben.

41
KAPITEL 2. PROGRAMMIEREN 2.8. OBJEKTORIENTIERUNG

Beispiel 2.7.2 Dokumentation einer Funktion


>>> def quadrate(zahl):
’’’Der Funktion quadrate wird als
Parameter eine Zahl mitgegeben,
die Funktion liefert das Quadrat der
Zahl zurück’’’

return zahl * zahl

Der Hilfetext kann jetzt auf zwei Arten aufgerufen werden:

1. Mit help(quadrate) wird ein gegliederter Hilfetext ausgegeben. Das sieht so aus:

Beispiel 2.7.3 Hilfe zu dieser Funktion mittels help“



>>> help(quadrate)
Help on function quadrate in module __main__:

quadrate(zahl)
Der Funktion quadrate wird als
Parameter eine Zahl mitgegeben,
die Funktion liefert das Quadrat der
Zahl zurück

2. Mit der print-Funktion, indem man den Namen der Funktion, gefolgt von zwei Unterstrichen,
gefolgt vom Text doc, gefolgt von nochmals zwei Unterstrichen eingibt.

Beispiel 2.7.4 Hilfe zu dieser Funktion mittels doc “



>>> print(quadrate.__doc__)
Der Funktion quadrate wird als
Parameter eine Zahl mitgegeben,
die Funktion liefert das Quadrat der
Zahl zurück

Die print-Funktion wird erst weiter hinten angesprochen, aber es ist wahrscheinlich klar, was sie macht:
sie gibt etwas aus, in diesem Fall auf den Bildschirm.
Und die Funktion funktioniert so wie gewünscht:

Beispiel 2.7.5 Beispiel für eine einfache Funktion


>>> quadrate(3)
9

2.8. Objektorientierung
Dieses Kapitel greift vor: über Objektorientierung wird erst wieder im Kapitel Klassen gesprochen. Aber
bereits in den Kapiteln zuvor wird immer wieder eine Notation benutzt, die aus dem Bereich der Ob-
jektorientierung stammt.

42
KAPITEL 2. PROGRAMMIEREN 2.9. PROGRAMMIERSTIL UND . . .

In (fast) allen Programmiersprachen muss man beim Anlegen einer Variablen angeben, welchen Typ
diese Variable hat. Man muss etwa festlegen, dass die Variable zahl1 eine Variable des Typs int ist,
wobei int die Abkürzung für das englische Wort für ganze Zahl“ nämlich integer ist; oder eine

vorname soll vom Typ string sein, also eine Zeichenkette zum Inhalt haben.
In Python muss das nicht festgelegt werden. Bei der ersten Wertzuweisung an eine Variable merkt Py-
thon selbst, zu welcher Klasse (gemerkt? nicht zu welchem Typ) diese Variable gehört. Klassen sind Mo-
delle für Variablen, die nicht nur bestimmte Eigenschaften haben, sondern auch festgelegte Fähigkeiten;
das heißt, dass durch die Klassenzugehörigkeit einer Variablen festgelegt wird, was diese Variable kann
und darf.
Die Eigenschaften bzw. die Fähigkeiten einer Variablen, also eines Objektes einer Klasse, werden
durch einen Punkt an den Namen der Variablen angehängt. Ein Beispiel: wenn ich also eine Variable
mit Namen name habe, die den Wert Meier“ enthält, ist dies ein Text, und dieser Text hat die Fähigkeit,

sich selber in reinen Großbuchstaben schreiben zu lassen:

Beispiel 2.8.1 Schreibweise für Fähigkeit einer Variablen“



>>> name = ’meier’
>>> [Link]()
’MEIER’

Fähigkeiten sind Funktionen, und die Schreibweise ähnelt auch der Schreibweise einer Funktion in
der Mathematik: hinter den Funktionsnamen wird dort in Klammern die Variable der Funktion angege-
ben. Das ist hier auch so, aber die Funktion upper benötigt keine Variable, also bleibt hier die Klammer
leer.

2.9. Programmierstil und Konventionen

The ideal programmer would have


the vision of Isaac Newton,
the intellect of Albert Einstein,
the creativity of Miles Davis,
the aesthetic sense of Maya Lin,
the wisdom of Benjamin Franklin,
the literary talent of William Shakespeare,
the oratorical skills of Martin Luther King,
the audacity of John Roebling,
and the self-confidence of Grace Hopper.

—David Evans19

Solange man an seinem eigenen Rechner sitzt und nur für das eigene Vergnügen programmiert, kann
man das machen, wie man will. Viele Programmierer sind auf diese Art groß geworden. Wenn man
aber aus seinem stillen Kämmerlein herauskommt, wird das eigene Werk auf einmal kritisch beäugt.
Und das ist gut so. Auch wenn D. Knuth sein Werk The Art of Computer Programming“ genannt hat,

sollte man sich nicht zuviel künstlerische Freiheiten herausnehmen— vor allem dann, wenn man unter
künstlerischer Freiheit hauptsächlich Chaos und Unordnung versteht. Jede Kunst besitzt auch Struktur.
Struktur entsteht, indem man das Handwerkszeug beherrscht, das für die Beherrschung der Kunst(-
richtung) nötig ist. So sollte man sich nach den ersten paar Programmen diese noch einmal anschauen
und sich die Variablennamen vornehmen: sind die alle nach einer Regel (die ich mir selber gegeben
habe und in Worte fassen kann) aufgebaut? Oder gibt es da Inkonsistenzen in der Schreibweise? Sind
logische Zusammenhänge durch die Schreibweisen sichtbar gemacht?
Viele der Bemerkungen, die in Büchern zu anderen Programmiersprachen gemacht werden, sind in
Python zum Glück überflüssig. Ordnung (und damit ein guter Programmierstil) ergibt sich in Python
19 aus: [Evans], S. 35

43
KAPITEL 2. PROGRAMMIEREN 2.9. PROGRAMMIERSTIL UND . . .

automatisch durch das Prinzip der Einrückung. So wie in jedem Text einer natürlichen Sprache wie
Deutsch ist der Leser froh, wenn er auf einen Blick erkennt, was zusammenhängt. Der Autor benutzt zu
diesem Zwecke die altbekannten Mittel der Gliederung: Kapitel, Absätze, Sätze, Satzteile.

In Python ist Einrückung nicht eine Möglichkeit, sondern eine Pflicht. Was zusammengehört, muss
auf der selben Einrückungsstufe stehen. Wer schon einmal einen Programmierkurs gegeben hat, weiß
das sehr zu schätzen. Jeder weiß, dass Anfänger des Programmierens, wenn sie nicht müssen, oft schnell
etwas hinschreiben, ohne sich eine Struktur zu überlegen. Das kann dann in einer Sprache wie perl so
aussehen:

Beispiel 2.9.1 Schlechter Stil! So nicht!! (Das ist auch nicht Python)
#!/usr/bin/perl
$caps = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";$kls = "abcdefghijklmnopqrstuvwxyz";
$gesamt = 0;

sub toCaps {local($c) = @_;

if (ord($c) > 96 & & ord($c) < = 123) {


$cc = substr($caps,index($kls,$c),1);
$gesamt++;} elsif (ord($c) > 64 & & ord($c) <= 91) {$cc = $c;
$gesamt++;} else {$cc = " ";}return $cc;
} print "Eingabe eines Textes: ";

$zeile = <STDIN>;
chomp $zeile;
foreach $j(0..25) {$anz[$j] = 0;}

foreach $i(0..length($zeile)-1) {$z = substr($zeile,$i,1);


if ($z ne " ") {
&toCaps($z); $caps_pos = index($caps,$cc); $anz[$caps_pos]++; } else {
$cc = $z;}
}

open(AUS,">[Link]");
print AUS "Buchstaben insgesamt: $gesamt\n";
print AUS "Buchstabe absolut relativ\n";
foreach $j(0..25) {
print AUS " ".substr($caps,$j,1)." : ".
$anz[$j]." ".$anz[$j]/$gesamt."\n";}close AUS;
exit 0;

Das sieht aus, wie wenn es ohne Punkt und Komma geschrieben wäre.20 Dieses perl-Programm ist
lauffähig. 21 Aber wirklich nicht gut lesbar. Eine Gliederung ist nicht zu erkennen. In Python ginge so
etwas nicht!

20 Ist es auch. Die Gliederungsmerkmale sind die Strichpunkte und die geschweiften Klammern.
21 Perl: The only language that looks the same before and after RSA encryption. – Keith Bostic

44
KAPITEL 2. PROGRAMMIEREN 2.10. RESERVIERTE WÖRTER

A NMERKUNG
In jedem Unternehmen gibt es heutzutage etwas wie eine corporate identity“. In

jeder EDV-Abteilung mit Programmierern gibt es dafür eine Sammlung von Kon-
ventionen. Da wird dann etwa festgelegt, oder dass Variablennamen immer mit
einem Kleinbuchstaben anfangen, oder dass der Variablenname von Variablen,
die eine Zahl zum Inhalt haben, immer mit z “ anfangen. Jede dieser Sammlun-

gen von Richtlinien kann unterschiedlich sein, jede hat aber ihre Berechtigung.
Für sich selber als Anfänger der Programmierung sollte man solche Richtlinien
auch aufstellen und sich daran halten. Es hilft!
Für Python gibt es auch eine solche Richtlinie. Man findet sie unter PEP 8
<[Link]

Da Python-Entwickler und Python-Programmierer eine gewisse Neigung zu dummen Sprüchen ha-


ben22 , findet man auch Regeln für die Programmierung in Python in Python selber: Das Zen von Python.
Dazu gibt man einfach in Python den Befehl import this ein.

2.10. Reservierte Wörter


In einer Programmiersprache muss man, wie in jeder gesprochenen Sprache auch, Vokabeln lernen. In
einer Progammiersprache heißen diese Vokabeln Reservierte Wörter“ oder Schlüsselwörter“. Der er-
” ”
freuliche Aspekt einer Programmiersprache: es gibt sehr wenige Vokabeln. 23 Keine Sorge: Vokabeln
abfragen, wie früher im Latein-Unterricht, wird es bei der Python-Programmierung nicht geben. Man
sollte aber hier einmal kurz drüberlesen, um sich vielleicht das eine oder andere Wort doch einzu-
prägen. Das einzige Problem mit den reservierten Wörtern ist, dass man sie nur in dem von den Python-
Entwicklern vorgesehenen Zusammenhang benutzen darf. Dafür sind sie reserviert!
Die reservierten Wörter in Python lässt man sich anzeigen durch

Beispiel 2.10.1 Befehl, um reservierte Wörter anzuzeigen


>>> import keyword
>>> print([Link])
[’False’, ’None’, ’True’,
’and’, ’as’, ’assert’, ’break’, ’class’, ’continue’,
’def’, ’del’, ’elif’, ’else’, ’except’,
’finally’, ’for’, ’from’, ’global’,
’if’, ’import’, ’in’, ’is’, ’lambda’,
’nonlocal’, ’not’, ’or’, ’pass’, ’raise’,
’return’, ’try’, ’while’, ’with’, ’yield’]

Wir, die Programmierer, erweitern durch unsere Programme das Vokabular, indem wir neue Vokabeln
für neue Sachverhalte erfinden.

2.11. Fehler (zum ersten)


She knows there’s no success like failure
And that failure’s no success at all
(Bob Dylan 24 )
22 Du weißt noch, woher die Sprache ihren Namen hat?
23 Wer eine masochistische Ader hat: es gibt Sprachen mit noch wesentlich weniger Vokabeln. Die Sprache brainfuck“(J’y suis

pour rien) hat überhaupt keine Vokablen und kennt auch nur acht Befehle. Viel Spaß. Siehe: <[Link]
wiki/Brainfuck>
24 Love Minus Zero auf: Bringing it all back home

45
KAPITEL 2. PROGRAMMIEREN 2.12. ... UND DAS FEHLT

Wie in jeder natürlichen Sprache auch kann man in einer Programmiersprache etwas richtig aus-
drücken mit dem Ergebnis, dass der Empfänger das versteht; man kann aber auch etwas fehlerhaft
ausdrücken, was zur Folge hat, dass der Empfänger nichts versteht. In einer Programmiersprache ist
der Empfänger der Interpreter oder der Compiler.
Die Reaktion des Empfängers ist aber sehr unterschiedlich. In einer Nachricht, die in einer natürlichen
Sprache vom Sender zum Empfänger geht, versucht der Empfänger auch bei Fehlern noch den Inhalt
der Nachricht zu verstehen, im Zweifelsfall dadurch, dass er den Sender um Bestätigung der Interpre-
tation bittet. In einer Programmiersprache ist die Reaktion eindeutig: der Compiler bzw. der Interpreter
beendet seine Arbeit einfach dadurch, dass er meldet: mit dem Geschriebenen kann ich nichts anfangen,
weil es einen oder mehrere Fehler enthält.
Das ist für den Schreiber zuerst mal sehr enttäuschend. Und dann ist es mit Arbeit verbunden, denn
jetzt muss der Schreiber seinen Text auf mögliche Fehler untersuchen. Bevor ich auf die einzelnen Arten
von Fehlern eingehe muss ich aber hier eine allgemeine Bemerkung machen.
Zu Beginn des 21. Jahrhunderts ist das Unterrichten von Programmierung, ganz unabhängig von der
Programmiersprache, wesentlich schwieriger als in den 70er-Jahren des 20. Jahrhunderts. Der Grund ist
ganz einfach: kaum jemand kann heute noch richtig schreiben. Besonders schwierig ist das Unterrich-
ten in Programmierung an der Schule, denn korrektes Schreiben ist leider überhaupt nicht mehr nötig,
um einen Schulabschluß zu erhalten, nicht einmal mehr im Abitur. Das schöne Wort Verbesserung“ ist

sowieso aus dem Wortschatz jedes (Deutsch-)Lehrers verschwunden nach dem Motto: das tu ich mir

doch nicht an, dass ich den Quatsch ein zweites Mal lese“, weswegen Schüler dieses Wort und die damit
verbundene Tätigkeit nicht mehr kennen. Ein Beispiel aus einer durchschnittlichen 12. Klasse: in einem
Programm sollte eine Funktion erhöhen“ geschrieben werden. Die verschiedenen Schreibweisen für

das Wort erhöhen“ variierten je nach Schüler von 2 bis 4 (erhoeen, erhöen, errhöhn, erhoehn . . . ). Auf-

gefordert, den Programmtext nochmals zu lesen, war die Antwort meistens: Das hab ich schon gemacht,
da seh ich keinen Fehler.
Was also in einem Aufsatz die Note 2-3 ergibt, führt in der Programmierung zur Note 6.
Jetzt also zu den verschiedenen Arten von Fehlern:

• Syntax-Fehler. In der deutschen Sprache gelten etwa die Syntax-Regeln, dass ein Satz mit einem
Großbuchstaben beginnt und mit einem Satzzeichen (Punkt, Ausrufezeichen, Fragezeichen) en-
det. In jeder Programmiersprache gibt es ähnlich einfache Syntax-Regeln. Fehler in der Syntax
sind die am einfachsten zu findenden Fehler (sollte man meinen; siehe aber dazu nochmals den
vorhergehenden Absatz). In einer natürlichen Sprache sind Syntaxfehler noch kein Hindernis für
eine funktionierende Kommunikation. In einer Programmiersprache ist der Unterschied der von
einem lauffähigen Programm zu . . . nix. Ein Stück Programmcode mit Syntaxfehlern ist nix.
• Semantische Fehler. Diese Fehler sind gekennzeichnet durch syntaktisch korrekte Anweisungen
in einem Programm. Verglichen mit einer natürlichen Sprache bedeutet das, dass die einzelnen
Sätze in dem kommunizierten Text korrekt sind. Trotzdem macht das Programm nicht das, was es
soll. Der Text ergibt keinen Sinn (oder nicht den erwarteten Sinn). Semantische Fehler sind nicht
immer leicht zu finden, selten durch Probieren, Umkodieren, Ändern von Programmen. Leichter
findet man solchen Fehler, wenn man sich vom Rechner löst und das Problem neu durchdenkt.
• Laufzeitfehler. Wie der Name schon sagt, treten solche Fehler erst bei der Ausführung des Pro-
gramms auf. Syntax und Semantik scheinen in Ordnung, aber das Programm bricht aus irgend-
einem (auf den ersten Blick unerklärlichen) Grund ab. Ein typisches Beispiel ist, dass man im
Programm codiert hat, dass etwas an der 5. Stelle (von irgendetwas) gelesen werden soll. Das
irgendetwas“ hat aber nur 3 Stellen.

2.12. ... und das fehlt


Vor allem jüngere Lernende vermissen vielleicht Spiele. Auch hierzu gibt es natürlich viele schöne Bei-
spiele in Python, denn Python ist auch eine Sprache, in der man gut Spiele programmieren kann. Aber
die Programmierung von Spielen setzt viel mehr voraus, als hier in diesem Skript beschrieben wird. Man
wird auch kaum ein sinnvolles Buch zum Einstieg in die Programmierung finden, das sich mit Spiele-
Programmierung befasst. Wer sich trotzdem darin probieren will, sollte zuerst auf grafische Oberflächen
verzichten. Ein Vorschlag, den man in Erwägung ziehen könnte, wenn man die ersten objektorientierten
Programme erstellt hat, ist Schiffe versenken“. Try it!

46
KAPITEL 2. PROGRAMMIEREN 2.13. FEHLER FINDEN

2.13. Fehler finden


Wie findet man aber Fehler? Es gibt natürlich Programme, bei denen man eventuelle Fehler mit klassi-
schen Mitteln findet, nämlich mit

• exaktem Lesen
• gründlichem Nachdenken

Vor allem bei den Übungsprogrammen, die ja selten mal länger als 50 oder 100 Zeilen sind, ist der
Aufwand überschaubar, und scharfes Hinschauen und Nachdenken hilft hier. Aber bei längeren Pro-
grammen ist man dankbar für eine Hilfe, aus historischen Gründen debugger“ genannt. Ein Debugger

erlaubt es, die Ausführung eines Programmes an einer beliebigen Stelle zu unterbrechen und den Inhalt
der Variablen zu diesem Zeitpunkt anzuschauen. Für viele Programmiersprachen und in vielen IDE’s
(siehe nächstes Kapitel) existieren Debugger. Auch das sollte sich ein Programmieranfänger einmal an-
schauen, wenn er eine IDE auswählt: die IDE ist die beste, die mir am besten gefällt.
Die Hardcore“-Programmierer verschmähen natürlich einen Debugger. Okay, in Wirklichkeit tun sie

es nicht, aber ihr Debugger heißt print! Das, was ich im vorigen Absatz geschrieben habe, erledigen sie
durch die Ausgabe von Variablen-Inhalten mittels der print-Anweisung . . . und haben dadurch einen
Minimal-Debugger.

2.14. Aufgaben
1. Lies diagonal über die Python-Seite im WWW: <[Link] (Gewöhne Dich
gleich daran: in der Informatik ist vieles nur auf Englisch zu finden!)
2. Wenn Du Kinderbücher magst: schau Dir mal Snake Wrangling for Kids“ an. Das gibt es in einer

deutschen Übersetzung unter <[Link]

47
Teil II.

IDE

49
3. Die Entwicklungsumgebung IDLE: Zahlen
und Variable

A ship in port is safe;


but that is not what ships are built for.
Sail out to sea and do new things.
(Admiral Grace Hopper 1 )

3.1. . . . und bevor es losgeht . . .

Die fast wichtigste Regel, wenn man sich ans Programmieren begibt, kommt natürlich hier auch als
erstes: Erst denken, dann tippen
Das hört sich einfach an und selbstverständlich, aber viele, auch erfahrene Programmierer lesen ei-
ne Aufgabenstellung, setzen sich an die Tastatur und fangen an zu schreiben. Dann ist das Programm
fertig, und der Programmierer stellt fest: ist das umständlich geschrieben, ist das unschön, das geht doch
verständlicher. Es ist wie beim Aufsatzschreiben: ein gutes Konzept macht das eigene Werk übersichtlicher,
verständlicher und meistens auch kürzer.
Die zweite Regel ist fast genauso wichtig: Ein Programm ist erst fertig, wenn es ausreichend getestet
ist.
Und dann hast Du das Programm geschrieben, hast es einmal gestartet und es hat funktioniert, wie Du
Dir das vorgestellt hast. Also legst Du die Füße hoch, freust Dich, dass Du mit Deiner Arbeit fertig bist
und gibst das Ergebnis Deinem Chef (wenn programmieren Dein Job ist) oder Deinem Lehrer (wenn
Du Schüler oder Student oder sonst irgend ein Lernender bist und das eine Hausaufgabe oder eine
Prüfungsaufgabe war). Der Chef (oder Lehrer) startet das Programm, und es tut sich nichts (oder etwas
ganz unerwartetes).
Denn Du als Programmierer hast vergessen, dass derjenige, der das Programm anwendet (oder überprüft)
leider nicht genau die Daten eingibt, die Du eingegeben hast und mit anderen Daten läuft das Programm
überhaupt nicht.

3.2. Rechnen in der Entwicklungsumgebung

Eine Entwicklungsumgebung, auf englisch Integrated Development Environment, wird mit IDE abgekürzt.
Da ist es kein Zufall, dass die Entwicklungsumgebung von Python idle heißt. Zum einen, weil idle ja
ein schönes englisches Wort ist, dessen Bedeutung Mathematikern und Programmierern zum Prinzip
geworden ist, zum anderen weil der fröhliche Mensch auf dem Bild, wie allen Freunden des Leben des

Brian“ bekannt, Eric Idle heißt. 2

1 (Erfinderin der Programmiersprache COBOL)


2 Eduardo Unda-Sanzana, Bild lizensiert unter

51
KAPITEL 3. DIE . . . 3.2. RECHNEN IN DER . . .

Abbildung 3.1. Eric Idle (CC BY 2.0)

Rufen wir also einfach mal IDLE auf! Der Bildschirm von IDLE sieht so aus!

Abbildung 3.2. Die IDE Idle

Jetzt geben wir einfach mal etwas in IDLE ein, in Erinnerung dessen, dass ein Computer ein Rechner
ist, eine komplizierte Mathematik-Aufgabe. Zuerst müssen den Variablen, hier der Einfachheit halber
x1 und x2 genannt, Werte zugewiesen werden. Der Zuweisungsoperator in Python ist das Gleichheits-
zeichen.

>>> x1 = 3
>>> x2 = 4
>>> ergebnis = x1 + x2

Jede einzelne Zeile, die wir oben geschrieben haben, ist eine Anweisung (oder ein Befehl) in Python.
Manchmal wird dafür auch das englische Wort statement“ benutzt. Damit wird Python gesagt: mach

52
KAPITEL 3. DIE . . . 3.2. RECHNEN IN DER . . .

dies, mach das. Die obigen 3 Zeilen geben Python genau 3 Befehle, und diese Befehle heißen in mensch-
licher Sprache:

1. Gib einem Speicherplatz den Namen x1 und weise diesem Speicherplatz den Wert 3 zu.
2. Gib einem anderen Speicherplatz den Namen x2 und weise diesem Speicherplatz den Wert 4 zu.
3. Gib einem weiteren Speicherplatz den Namen ergebnis und weise diesem Speicherplatz die
Summe der Werte zu, die auf den Speicherplätzen mit den Namen x1 und x2 gespeichert sind.

Das ist jeweils eine sehr umständliche Sprech- und Schreibweise. Man drückt das deswegen oft einfa-
cher aus durch:

1. Weise der Variablen x1 den Wert 3 zu.


2. Weise der Variablen x2 den Wert 4 zu.
3. Weise der Variablen ergebnis die Summe der Werte der Variablen x1 und x2 zu.

Das IDLE-Fenster sieht danach so aus:

Abbildung 3.3. Erste Berechnung in der IDE Idle

Es ist wohl fast selbstverständlich, wie eine Anweisung abgearbeitet wird: von links nach rechts;
dabei gelten aber die Regeln, die aus der Mathematik bekannt sind: was in Klammern steht, wird zuerst
verwertet, danach kommen (im Falle von mathematischen Anweisungen) die Punkt-“Rechnungen,

dann die Strich-“Rechnungen.

A NMERKUNG
Wer sich für diese schrittweise Ausführung von Befehlen interessiert, aber auch
für alle Anfänger, für die das oben beschriebene völliges Neuland ist: es gibt eine
nette Entwicklungsumgebung mit Namen thonny, die genau das macht. Diese
IDE ist auch freie Software und existiert wohl für alle Betriebssysteme.
Im Menu unter Run -> Debug(Nicer) werden die einzelnen Aktionen von
Python Schritt für Schritt angezeigt.

Nachdem wir unser erstes Python-Programm geschrieben haben, werden wir mutig bis übermütig.
Lassen wir den Rechner rechnen! Die arithmetischen Operatoren sehen vertraut aus, zwar nicht so, wie
man sie mit der Hand schreibt, sondern so wie man sie auf der Computer-Tastatur sieht.

• Addition 6 + 3
• Subtraktion 6 - 3
• Multiplikation 6 * 3
• Division 6 / 3
• Exponentiation 2**3

53
KAPITEL 3. DIE . . . 3.2. RECHNEN IN DER . . .

• Modulus (Rest) 5%3

Das ist der passende Zeitpunkt, um in IDLE ein bißchen herumzuspielen und ein paar Rechnungen
ausführen zu lassen. Und vielleicht ist das auch ein Grund, immer IDLE laufen zu lassen. 3

Das Ergebnis überrascht uns nicht. Der Rechner kann rechnen.

Abbildung 3.4. Rechnungen in Idle

Wenn man im obigen Bild genau hinschaut, erkennt man 2 Dinge:

1. In der ersten steht die Version des Python-Interpreters. Hier ist es Version 3.6.5. Die Division von
9 durch 3 ergibt 3.0 Das Ergebnis einer Division ist immer eine Division.

2. Die ganzzahlige Division, die als Ergebnis auch eine ganze Zahl liefert und diese beim Dezimal-
komma abschneidet wird durch den doppelten Schrägstrich erledigt. (Wie damals in der Grund-
schule: 9 : 4 = 2 (Rest 1))

In Python 2 sähe das etwas anders aus. Die Division von 9 durch 3 ergibt hier das Ergebnis 3 (als
ganze Zahl). Also stellen wir hier einen gravierenden Unterschied zwischen Python 2.x und Python 3.x
fest. Das stelle ich hier in einer Tabelle gegenüber:

3 Wer unter Linux / KDE arbeitet, weiß die Möglichkeit von virtuellen Bildschirmen zu schätzen und wird sich wahrscheinlich
jetzt schon längst einen virtuellen Bildschirm eingerichtet haben, auf dem nur IDLE läuft.
Und wer unter Windows arbeitet, weiß vielleicht gar nicht, wie komfortabel grafische Oberflächen sein können!!!

54
KAPITEL 3. DIE . . . 3.2. RECHNEN IN DER . . .

Tabelle 3.1. Division in Python 3.x bzw. Python 2.x


Python 3.x Python 2.x
>>> 9 / 3 >>> 9 / 3
3.0 3
>>> 9 // 4 >>> 9 / 4
2 2
>>> 9 / 4 >>> 9.0 / 4
2.25 2.25
Der Divisionsoperator / steht für die Division Der Divisionsoperator / steht für die Ganzzahl-
von beliebigen Zahlen. Das Ergebnis ist immer Division.
eine Dezimalzahl.
1. Wenn sowohl Divisor als auch Dividend
ganze Zahlen sind, ist das Ergebnis eine
ganze Zahl. (zur Erinnerung: Divisor: die
Zahl, durch die geteilt wird; Dividend: die
Zahl, die geteilt wird)
2. Wenn Divisor oder Dividend (oder beide
Zahlen) eine Dezimalzahl ist, ist das Er-
gebnis eine Dezimalzahl.

Der Divisionsoperator // steht für die


Ganzzahl-Division. Hier wird also gerechnet
wie in der Grundschule, nämlich 9 geteilt durch
4 ist 2 (Rest 1; und das wird einfach wegge-
schmissen)

Wenn wir einer Variablen einen Wert zuweisen, kann es passieren, dass wir sehr bald nicht mehr
wissen, ob wir eine ganze Zahl oder eine Dezimalzahl zugewiesen haben. Das können wir in Python
aber leicht rauskriegen.

Beispiel 3.2.1 Zahlentypen


>>> x = 3
>>> y = 123.156156
>>> type(x)
<class ’int’>
>>> type(y)
<class ’float’>

Und manchmal ist es nötig, eine Variable, die den Typ int hat, in den Typ float umzuwandeln,
oder umgekehrt.

Beispiel 3.2.2 Umwandlung in einen anderen Zahlentyp


>>> x_float = float(x)
>>> y_int = int(y)
>>> print(x_float)
3.0
>>> print(y_int)
123

Eine wichtige Kleinigkeit muss an dieser Stelle festgehalten werden: die Grundlage bei der Entwick-
lung von Python (wie von fast allen Programmiersprachen) ist englisch, also gibt es kein Dezimalkom-

55
KAPITEL 3. DIE . . . 3.2. RECHNEN IN DER . . .

ma, sondern einen Dezimalpunkt.

A NMERKUNG
In Python 3 ist die Division (ausgeführt durch den Schrägstrich /) immer
eine Fließkomma-Division. Wenn man in Python 3 eine Ganzzahl-Division
durchführen will, also eine Division, bei der das Ergebnis eine ganze Zahl ist,
muss man den Doppel-Schrägstrich // benutzen.

Das probieren wir gleich aus, indem wir in IDLE

Beispiel 3.2.3 Divisionen


>>> x1 = 3.0
>>> x2 = 4.0
>>> ergebnis = x2 / x1
>>> ergebnis
1.3333333333

eingeben.
Ebenso gilt:

>>> x1 = 3
>>> x2 = 4
>>> ergebnis = x2 / x1
>>> ergebnis
1.3333333333

Für die Division, wie sie in der Grundschule gelernt wird, nämlich

4 : 3 = 1 (Rest 1)

muss eingegeben werden:

>>> 4 // 3
1

Es gibt aber wirklich viele Anwendungen, bei denen man genau das will, und dazu will man noch
den Rest berechnet haben. Dazu gibt es den Rest-Operator, korrekt Modulus genannt. Wir geben also
ein, um das zu testen:

Beispiel 3.2.4 Modulo-Rechnen


>>> 8 % 3
2

und das liefert uns den Rest 2 bei der Division von 8 durch 3.
Das, was wir im vorigen Absatz Python vorgeworfen haben, ist kein Befehl. Es ist ein Ausdruck, auf
englisch eine expression“. Auf der Python-Konsole, im Python-Interpreter, kann man auch Ausdrücke

auswerten lassen, ohne einen Befehl auszuführen. Das macht man manchmal, um zu testen, welchen

56
KAPITEL 3. DIE . . . 3.2. RECHNEN IN DER . . .

Wert ein Ausdruck hat. Allerdings ist der Wert des Ausdrucks sofort verloren, wenn ich etwas anderes
mache, da er nicht gespeichert wird, nicht ausgegeben wird ... Deswegen lasse ich Ausdrücke so gut es
geht weg.
Python bietet uns sogar noch mehr:

Beispiel 3.2.5 Division und Rest


>>> divmod(13,3)
(4,1)

liefert als Ausgabe ein Paar von Zahlen, wobei die erste Zahl das ganzzahlige Ergebnis von 13 / 3 ist,
die zweite Zahl der Rest bei dieser Division. Dieses Paar ist ordentlich in Klammern geschrieben, und
das soll an dieser Stelle uns erst einmal nur erfreuen. Was diese Schreibweise genau bedeutet, folgt in
einem späteren Kapitel.

Tabelle 3.2. Arithmetische Operatoren in Python


Operation math. Zeichen Beispiel Ergebnis
Addition + 6+3 9
Subtraktion - 6-3 3
Multiplikation * 6*3 18
Division / 6/3 2
Modulus % 8%3 2
Exponentiation ** 6**3 216

Bisher haben wir Berechnungen durchgeführt und das Ergebnis der Rechnung implizit ausgeben las-
sen, das heißt, wir haben Python nicht ausdrücklich angewiesen, etwas auszugeben. Der Befehl, um
etwas an den Bildschirm auszugeben, lautet print.
print nimmt die Argumente, die in der Klammer stehen, wandelt jedes einzelne in eine Zeichenket-
te (einen String) um, setzt die einzelnen Zeichenketten zusammen und gibt diese zusammengesetzte
Zeichenkette aus. Dabei wird die Zeichenkette vollständig“, das heißt, dass ein Zeilenvorschub hin-

zugefügt wird.4 Dieses Verhalten, dass jeder Aufruf der print-Funktion eine vollständige Zeile liefert,
kann man dadurch ändern, dass man der print-Funktion den Parameter end=’ ’ mitgibt. Hier ist der
Parameter standardmäßig mit einem Zeilenvorschub ’\n’ belegt.
Das scheint keinen Unterschied zu machen, ob man in IDLE

>>> 3 + 4

oder

>>> print(3 + 4)

eingibt. Aber das ausdrückliche Ausgeben mit print“ ist intelligent, wenn mit Dezimalzahlen gerechnet

wird. Ein Beispiel dazu:

Beispiel 3.2.6 Rundungsfehler


>>> 2 / 5.0
0.40000000000000002
>>> print(2 / 5.0)
0.4

4 Das entspricht einem println in Pascal.

57
KAPITEL 3. DIE . . . 3.3. EIN SPEICHERPLATZ MIT EINEM . . .

Man sieht: die Ausgabe mit print“ rundet intelligent! 5



Klar: wenn ich zu der Zahl 0 in einer Schleife 10 mal 0,1 addiere, ergibt das 1. Aber nicht beim Pro-
grammieren mit Dezimalzahlen.

Beispiel 3.2.7 Dezimalzahlen und Rundungsfehler


>>> summe = 0
>>> for i in range(10):
... summe += 0.1
...
>>> print(summe)
0.9999999999999999

Das sollte man sich immer klar machen, wenn man viele Rechnungen mit Dezimalzahlen zu machen
hat.
Wenn man mit Brüchen rechnet, passiert das nicht. Bruchrechnen kommt weiter hinten in diesem
Kapitel, und darin wird dieses Beispiel nochmals mit Brüchen gerechnet.

3.2.1. Aufgaben zu Zahlen und elementaren Berechnungen


1. Weise mindestens 5 Variablen irgendwelche numerische Werte zu, und zwar sowohl ganze Zahlen
als auch Dezimalzahlen. Führe alle möglichen Rechenoperationen mit diesen Zahlen aus, gib die
Ergebnisse aus und halte Auffälligkeiten in den Ergebnissen fest.

3.3. Ein Speicherplatz mit einem Namen: Variable


Man gave names to all the animals
In the beginning
Long time ago
(Bob Dylan 6 )

3.3.1. Variable in Mathematik und in der Programmierung


Sinnvoll werden Berechnungen erst, wenn man die Werte nicht jedes Mal eingeben muss, sondern sie
irgendwo speichern kann. Hier kommt das Prinzip der Variablen ins Spiel.
Variable haben einen Variablennamen und einen Wert. Der Wert wird einer Variablen zugewiesen
durch den Zuweisungsoperator =“. Durch x = 3 wird der Variablen x der Wert 3 zugewiesen. (Der

Typ der Variablen wird in Python implizit gesetzt. So könnte man meinen, aber es ist viel schöner,
als man es sich vorstellen kann: durch die Zuweisung eines Wertes an eine Variable wird die Variable
ein Objekt des Typs, der durch den zugewiesenen Wert bestimmt ist. Dazu später mehr, wenn Objek-
torientierte Programmierung besprochen wird. ) Vorerst benutzen wir nur einfache Typen, das heißt
Zahlen-Typen und Text-Typen.
Man kann sich eine Variable wie einen Karton vorstellen, der ordentlich beschriftet ist. Die Beschrif-
tung gibt dabei an, was in dem Karton ist. Damit man sich das nicht nur vorstellen muss, sondern auch
sehen kann, gibt es hier ein Bild: der Karton ist mit dem Namen zahl versehen und hat als Inhalt einen
Zettel, auf dem der Wert 15“ steht.

5 Das hört sich für den Laien seltsam an: dass 0.4 eine gerundete Zahl sein soll, ist doch sehr gewöhnungsbedürftig. Aber man
muss sich ins Gedächtnis rufen, dass der Computer im Dualsystem rechnet. Das heißt, unsere Eingaben (in diesem Fall 2
und 5) werden zuerst in Dualzahlen umgewandelt. Dabei entstehen bereits Fehler (das sind eigentlich nur Ungenauigkeiten).
Danach wird mit diesen Dualzahlen gerechnet, am Ende wird das Ergebnis wieder in eine Dezimalzahl verwandelt. Aus Sicht
des Rechners ist das exakte Ergebnis für diese Division also 0.40000000000000002.
6 Man gave names to all the animals auf: Slow Train Coming

58
KAPITEL 3. DIE . . . 3.3. EIN SPEICHERPLATZ MIT EINEM . . .

Abbildung 3.5. Ein Variablen-Karton mit Inhalt

Die Beschriftung sollte nicht nur gut lesbar sein, sondern auch etwas über den Inhalt aussagen. Stell
Dir vor, Du hast vor ein paar Monaten Deinen Keller aufgeräumt, alles was herumliegt in Kisten gepackt
und diese alle fein säuberlich beschriftet: Kruscht“ steht auf allen drauf!!! Und jetzt such mal in den

Kisten den USB-Stick mit den Bildern von der Geburtstagsfeier: er ist in einer der Kisten, aber wo?
Das im vorhergehenden Abschnitt beschriebene Verhalten von Python wird in der Informatik mit dem
Begriff dynamische Typisierung“ bezeichnet. Bei der dynamischen Typisierung wird einer Variablen

ein Typ zugeordnet, und damit verhält sich die Variable so wie es in der Typ-Beschreibung vorgegeben
ist. Das hat gewisse Vorteile, weil sich der Programmierer zum Beispiel keine Gedanken darüber ma-
chen muss, wie groß mögliche Werte für diese Variable sein können (so kann man also einer Variablen
textbeispiel sowohl den Wert Python als auch den Wert Donaudampschifffahrtsgesell-
schaftskapitän zuweisen). Python kümmert sich automatisch darum, dass ausreichend Speicher
zur Verfügung gestellt wird und dass, nachdem die Variable ihren Dienst getan hat, auch der Speicher
wieder freigegeben wird.7 Auf jeden Fall muss der Programmierer hier darauf achten, dass zum Bei-
spiel in der Variablen erg das Ergebnis 2.71828 steht. Das Ergebnis Always look on the bright
side of life ist vielleicht als mentale Aufmunterung erfreulicher, aber mit diesem Ergebnis kann
niemand, auch nicht Python, weiterrechnen.
Das Gegenteil der dynamischen Typisierung ist die statische Typisierung“. Hier muss der Program-

mierer von vorneherein festhalten, welche Art von Information in einer Variablen gespeichert werden
soll (eine Zahl, ein Text, eine Liste, eine Matrix), und meistens auch noch, wieviel Platz diese Information
(maximal) einnehmen kann.
Wir müssen noch festhalten, dass in der Informatik Ausdrücke benutzt werden, die einen Mathe-
matiker den Kopf schütteln lassen: es kann nämlich auf der rechten und der linken Seite des Zuwei-
sungsoperators, also des Gleichheitszeichens, die selbe Variable stehen. In Mathematik ist das folgende
sinnlos:

Beispiel 3.3.1 zweimal dieselbe Variable


x = 7
x = 2 + x

In Mathematik widersprechen sich die beiden Anweisungen: in der ersten steht, dass x den Wert 7
hat, die zweite Anweisung ist für keinen Wert von x richtig.
In der Programmierung ist das sehr sinnvoll. In der ersten Anweisung wird der Variablen x der Wert
7 zugewiesen, d.h. ab jetzt hat die Variable x den Wert 7. In der zweiten Anweisung steht (in einer Art
Pseudocode formuliert): nimm das, was in der Variablen x steht, zähle 2 dazu und weise das Ergebnis
der Variablen x zu; ab jetzt hat also x den Wert 9.
Einem Mathematiker oder Programmierer erscheint es selbstverständlich, aber es wird trotzdem hier
erwähnt: man kann einer Variablen beliebig oft einen Wert zuweisen.
7 Obdas ein Vorteil oder ein Nachteil ist, darüber können sich Programmierer prima streiten, vor allem zwischen Mötzingen und
Baisingen.

59
KAPITEL 3. DIE . . . 3.3. EIN SPEICHERPLATZ MIT EINEM . . .

Beispiel 3.3.2 Mehrere Werte einer Variablen


>>> x = 7
>>> print(x)
7
>>> x = 2 + 7
>>> print(x)
9

Python erlaubt auch die Mehrfachzuweisung, und zwar in zwei Varianten.


• Es ist möglich, mit einer Anweisung mehreren Variablen den selben Wert zuzuweisen.

Beispiel 3.3.3 Mehrfachzuweisung eines Wertes an mehrere Variable


>>> x = y = z = 7
>>> print(x)
7
>>> print(z)
7
>>> print(y)
7

• Mit einer Anweisung kann auch verschiedenen Variablen verschiedene Werte zugewiesen werden.

Beispiel 3.3.4 Mehrfachzuweisung eines Wertes an mehrere Variable


>>> a, b, c, d = 3,7,5,9
>>> print(a)
3
>>> print(b)
7
>>> print(c)
5
>>> print(d)
9

Variable kennen wir schon aus der Mathematik. Allerdings sind die Mathematiker da sehr einfallslos
(jedenfalls in der Schule), denn Variable heißen hier grundsätzlich x. Aber das Prinzip der Variablen ist
hier das selbe: es wird ein Platzhalter geschaffen, der einen Namen bekommt, und diesem Platzhalter
kann man einen Wert zuweisen. Und nach einer Weile einen anderen Wert, so dass man mit der Zeit in
der Mathematik eine Wertetabelle bekommt.
In der (Schul-)Mathematik kennt man in der Analysis eine Variable, die dann fast immer x heißt, ganz
selten t, wenn man Funktionen in der Physik untersucht, bei der die Zeit variabel ist. In der Linearen
Algebra gibt es dann in der Schule schon mal 3 Variable, die dann x, y und z heißen, wenn man sie
nicht sogar einfach x1 , x2 und x3 nennt. In der Informatik benötigt man, um die Herstellungskosten
eines Produktes zu berechnen, viel mehr Informationen, also auch viel mehr Variable, die diese Infor-
mationen speichern, wie zum Beispiel stromkosten, abschreibungskosten, personalkosten,
materialkosten und noch viele mehr.
In der Programmierung ist man da viel flexibler (aber das hat man auch erst im Laufe der Jahre
gelernt). Variablennamen können länger als ein Zeichen sein, und das ist für die Lesbarkeit eines Pro-
gramms immer sehr sinnvoll. Denn ein Programm ist besser zu lesen und zu verstehen, wenn die Va-
riablennamen schon einen Hinweis auf die Werte geben, die sie später enthalten sollen. Natürlich kann

60
KAPITEL 3. DIE . . . 3.3. EIN SPEICHERPLATZ MIT EINEM . . .

man in einem Programm für geometrische Berechnungen auch Variablen l und b nennen, aber auf den
ersten Blick verständlicher sind die Variablennamen laenge und breite.

3.3.2. Variablennamen
Variablennamen müssen mit einem Buchstaben oder mit einem Unterstrich beginnen, dann dürfen eine
beliebige Anzahl von Buchstaben, Zahlen oder Unterstrichen folgen.

A CHTUNG
Auch wenn die Entwickler eines weitverbreiteten Betriebssystems etwas ande-
res behaupten: in allen Bezeichnern, so auch in Variablennamen, haben Leer-
zeichen und Sonderzeichen nichts zu suchen.
Python lehnt zwar eine Variable länge nicht ab; besser ist die Variable laenge.
Denn Python arbeitet mit UTF-8, aber wer weiß, ob ein Entwickler, der mein
Programm weiterbearbeitet, auch schon diesen Standard auf seinem Rechner
hat.

Es ist sinnvoll und in produktiven Umgebungen oft auch gefordert, dass man sich beim Schreiben
von Programmen an gewisse Regeln hält. Firmen etwa legen in internen Richtlinien fest, dass z.B. Va-
riablennamen mit einem Kleinbuchstaben beginnen. Wenn der Variablenname ein zusammengesetztes
Wort ist, dann wird der Wortanfang des zweiten (und jedes folgenden Wortes) mit einem Großbuch-
staben geschrieben. Eine andere mögliche Vereinbarung ist, dass jeweilige weitere Wortanfänge durch
einem Unterstrich “ mit dem vorigen Teil des Variablennamens verbunden werden. Es trägt einerseits

zur Lesbarkeit von Programmcode bei, wenn hier Einheitlichkeit herrscht.8 Andererseits ist es auch für
die maschinelle Verarbeitung von Dateien, und Programme sind aus der Sicht des Dateisystems erst mal
nur Dateien, hilfreich, wenn etwa eine Python-Prozedur eine ganze Menge von Dateien bearbeiten soll
und Variablennamen nach dem selben Schema aufgebaut sind.

Tabelle 3.3. Variablennamen


erstes Zeichen weitere Zeichen
Buchstabe; Unterstrich Buchstabe; Ziffer; Unterstrich

Beispiele für zulässige Variablennamen:

• zahl1
• zahl2
• grosseZahl
• ganzGrosseZahl

Nicht zulässig sind (aus den angegebenen Gründen):

• 12Grad (fängt nicht mit Buchstaben oder Unterstrich an)


• grosse Zahl (enthält Leerzeichen)

Auch hier muss ich auf etwas eingehen, was in unserem Kulturkreis lange Zeit eine Selbstverständlichkeit
war: der Satz Brandt hat in Moskau liebe Genossen“ hat eine andere Bedeutung als der Satz Brandt
” ”
hat in Moskau Liebe genossen“. Wenn man verschiedene Zeichen benutzt, bewirkt das eine unterschied-
liche Bedeutung. Erst mit dem Aufkommen von PC’s und dem eines (sehr schlichten) Betriebssystems
aus einem inzwischen sehr großen Softwarehaus von der Westküste der USA9 versuchte man, uns weis-
zumachen, dass die Datei [Link] und die Datei [Link] das selbe ist. Und leider schlagen sich
immer noch viele Software-Entwickler und PC-Benutzer mit diesem Übel herum.
In der Programmierung gilt einfach: Die Groß-/Kleinschreibung ist bei Variablen relevant!! liebe ist
etwas anderes als Liebe. Punkt. Aus. Ende der Diskussion.
8 siehe hierzu auch PEP 8 <[Link]
9 schon rausgekriegt, welches ich meine?

61
KAPITEL 3. DIE . . . 3.3. EIN SPEICHERPLATZ MIT EINEM . . .

3.3.3. Wertzuweisung
Die Zuweisung eines Wertes an eine Variable ist leider inzwischen für viele Programmieranfänger ein
riesiges Problem. Also muss ich hier ein paar Sätze darüber schreiben. Ein Wert, egal ob ein Zahlenwert
wie 2,56“ oder ein Zeichenkettenwert wie And now for something completely different“ schwebt aus
” ”
der Sicht eines Programmierers nie frei in der Landschaft herum: er steht auf einem Speicherplatz. Wie
ich oben geschrieben habe: der Speicherplatz hat in modernen Programmiersprachen einen Namen.
Egal, ob ich den Wert lesen will, mit diesem Wert arbeiten möchte (ihn vergrößern, verändern, Teile
davon ersetzen usw.), ihn löschen will oder was mir sonst noch einfällt: ich muss als Programmierer
wissen, in welcher Variablen dieser Wert gespeichert ist. Wenn ich weiß, dass der Wert And now for

something completely different“ in der Variablen unsinn gespeichert ist, dann kann ich in einem Pro-
gramm zum Beispiel die Anweisungen

• gib (den Inhalt der Variablen) unsinn aus


• verändere (den Text, der in der Variablen) unsinn (steht), so dass darin strange statt different
steht
• lösche (den Inhalt der Variablen) unsinn

schreiben.
In fast allen Programmiersprachen, auch in Python, ist der Zuweisungsoperator das =“, das Gleich-

heitszeichen.10 Links des Gleichheitszeichens steht der Name der Variablen, der etwas zugewiesen wird,
rechts des Gleichheitszeichens steht der Wert, der zugewiesen wird. a = 17 bedeutet also, dass der Va-
riablen mit dem Namen a der Wert 17 zugewiesen wird.

W ICHTIG
Gewöhne Dir gleich an, vor und nach dem Gleichheitszeichen genau ein Leer-
zeichen zu lassen . . . und merke Dir das auch für alle anderen Texte, die Du
schreibst, nicht nur für Programme! a

a siehe hierzu auch PEP 8 <[Link]

Gültige Zuweisungen sind also:

Beispiel 3.3.5 Korrekte Zuweisungen


>>> zahl1 = 123.56
>>> zahl2 = 99
>>> text1 = ’Das Leben des Brian’
>>> text2 = ’Volleyball macht Spass’

Ungültige Zuweisungen (die dann zu Fehlermeldungen führen) sind:

Beispiel 3.3.6 Fehlerhafte Zuweisungen


>>> 6 = zahl
>>> ’Mathematik’ = 12

10 Eine Ausnahme bilden die Wirth“-Sprachen, also Pascal, Modula und Oberon, die alle auf Niklaus Wirth zurückgehen. Hier

ist der Zuweisungsoperator ein :=“. Dafür ist der Vergleichsoperator auf Gleichheit hier ein einfaches =“.
” ”
Das hat den großen Nachteil, dass Zuweisungen immer zwei Tastendrücke bedeuten, und Zuweisungen sind häufiger als
Vergleiche! Den Mathematiker allerdings erfreut es, denn so lernt er es in den Anfangssemestern: a := 17 bedeutet: a hat jetzt
per Definition den Wert 17. Genau das ist aber eine Zuweisung.

62
KAPITEL 3. DIE . . . 3.3. EIN SPEICHERPLATZ MIT EINEM . . .

3.3.4. Aufgaben zu Variablen


And there shall in that time
be rumours of things going astray,
and there will be a great confusion
as to where things really are,
(Monty Python 11 )
Weil dieses Konzept der Wertzuweisung an Variable für Anfänger so problematisch ist, folgen hier ei-
nige Übungen. Die Übungen sind sehr ausführlich formuliert: so langatmig bekommt man wahrschein-
lich nie mehr Anweisungen, wie etwas programmiert werden soll!!

1. Weise einer Variablen mit dem Namen laenge den Wert 4 zu, weise einer anderen Variablen
mit dem Namen breite den Wert 12 zu, weise einer Variablen mit dem Namen flaeche den
Ausdruck laenge * breite zu. Was macht das Programm also? Welchen Namen würdest Du
diesem Programm geben?
2. Weise einer Variablen mit dem Namen laenge den Wert 4 zu, weise einer anderen Variablen
mit dem Namen breite den Wert 12 zu, weise einer Variablen mit dem Namen umfang den
Ausdruck 2 * laenge + 2 * breite zu. Was macht das Programm also? Welchen Namen
würdest Du diesem Programm geben?
3. Weise einer Variablen mit dem Namen laenge den Wert 4 zu, weise einer anderen Variablen
mit dem Namen breite den Wert 12 zu, weise einer dritten Variablen mit dem Namen hoehe
den Wert 7 zu,weise einer Variablen mit dem Namen volumen den Ausdruck 1 / 3 * laenge
* breite * hoehe zu. Was macht das Programm also? Welchen Namen würdest Du diesem
Programm geben?

3.3.5. Zuweisungsmuster
Aus einer netten Internetseite von (siehe [Lusth] ) übernehme ich hier die Idee der Zuweisungsmuster“.

Lusth unterscheidet

• das Transfer-Muster
• das Veränderungs-Muster
• das Wegschmeiß-Muster

Nehmen wir uns also die drei Muster der Reihe nach vor, aber in einer Kurzfassung. Wer interessiert ist,
sollte sich den Originaltext vornehmen!

1. Beim Transfer-Muster betrachten wir 2 Variable:

Beispiel 3.3.7 Transfer-Muster


>>> a = 5
>>> b = 7

(oder in Worten: der Variablen a wird der Wert 5, der Variablen b der Wert 7 zugewiesen.) Was
passiert aber, wenn ich schreibe: a = b? Welchen Wert hat nach dieser Zuweisung die Variable a,
welchen die Variable b?
Nun, einfach ist eine Antwort für b: an b ändert sich nichts, also muss der Wert von b immer noch
7 sein. Anders sieht es bei a aus: a wird b zugewiesen. Genau muss ich sagen: der Variablen a
wird der Wert zugewiesen, der in der Variablen b steht. Folglich steht in der Variablen a nach der
Zuweisung a = b auch der Wert 7.
2. Beim Veränderungs-Muster wird der Inhalt einer Variablen verändert.
11 in: Life of Brian

63
KAPITEL 3. DIE . . . 3.4. BRUCHRECHNEN

Beispiel 3.3.8 Veränderungs-Muster


>>> a = 5
>>> a = a + 3

Was passiert? In der ersten Zeile wird der Variablen a der Wert 5 zugewiesen. In der zweiten Zeile
steht, in Worte gefasst: nimm den Wert der Variablen a, zähle zu diesem Wert 3 dazu und speichere
das Ergebnis wieder in der Variablen a. Damit hat a den Wert 8.
3. Das Wegschmeiß-Muster ist das, was viele Anfänger benutzen!

Beispiel 3.3.9 Wegschmeiß-Muster


>>> a = 5
>>> a + 3

Das sieht sehr ähnlich aus wie das vorige Muster. Der Variablen a wird in der ersten Zeile der Wert
5 zugewiesen. In der folgenden Zeile wird der Wert von a um 3 erhöht . . . und weggeschmissen.
Genau gesagt: der erhöhte Wert wird nirgends gespeichert, ist also für alle Zeit verloren.

3.4. Bruchrechnen
Wie oben schon einmal gesagt: bei Python gilt batteries included“. Aber nicht alles ist im Kern von

Python. Manche Sprachelemente sind in Modulen ausgelagert. Obwohl Module erst später besprochen
werden, will ich hier schon einen Modul benutzen: den Modul fractions“. 12

Ein Modul wird in ein selbstgeschriebenes Programm (in der einfachsten Form) eingebunden durch

import fractions

Damit stehen in meinem Programm einige Möglichkeiten für das Bruchrechnen zur Verfügung. Einen
Bruch deklariere ich durch

bruch1 = [Link](3,4)

Und damit können wir lustig Bruchrechnen!!

>>> import fractions


>>> bruch1 = [Link](3,4)
>>> bruch2 = [Link](1,2)
>>> produkt = bruch1 * bruch2
>>> quotient = bruch1 / bruch2
>>> summe = bruch1 + bruch2
>>> differenz = bruch1 - bruch2
>>> print(’Summe: ’,summe)
(’Summe: ’, Fraction(5, 4))
>>> print(’Differenz: ’,differenz)
(’Differenz: ’, Fraction(1, 4))
>>> print(’Produkt: ’,produkt)
(’Produkt: ’, Fraction(3, 8))
>>> print(’Quotient: ’,quotient)
12 Fraction ist das englische Wort für Bruch.

64
KAPITEL 3. DIE . . . 3.5. RECHNEN UND VERGLEICHEN

(’Quotient: ’, Fraction(3, 2))


>>>

Selbstverständlich verträgt sich“ ein Bruch auch mit anderen Zahlen:


>>> i = 2
>>> summe2 = i + bruch1
>>> print(’Summe2:’, summe2)
(’Summe2:’, Fraction(11, 4))
>>> produkt2 = i * bruch1
>>> print(’Produkt2:’, produkt2)
(’Produkt2:’, Fraction(3, 2))
>>>

Hier kommt das Stück Code, das beim Rechnen mit Dezimalzahlen einen Fehler anzeigt. Mit Brüchen
ist alles in Ordnung.

Beispiel 3.4.1 Dezimalzahlen und kein Rundungsfehler mehr


>>> import fractions
>>> zehntel = [Link](1,10)
>>> summe = 0
>>> for i in range(10):
... summe += zehntel
...
>>> print(summe)
1

3.5. Rechnen und vergleichen


3.5.1. Zahlen, Zahlen, Zahlen
Mathematiker unterscheiden verschiedene Klassen von Zahlen: natürliche Zahlen, ganze Zahlen, ra-
tionale Zahlen, reelle Zahlen, komplexe Zahlen. Hier soll aber keine Einführung in Algebra gegeben
werden, darum werden die wichtigsten Zahlenmengen (so) anschaulich (wie möglich) beschrieben.

1. natürliche Zahlen sind die Zahlen 0, 1, 2, 3, ...

2. ganze Zahlen sind eine Obermenge der natürlichen Zahlen. Sie enthalten zusätzlich noch negative
Zahlen: ..., -2, -1, 0, 1, 2, 3, ...

3. rationale Zahlen sind Brüche; rationale Zahlen können als endliche Dezimalzahlen oder als un-
endliche periodische Dezimalzahlen geschrieben werden

4. reelle Zahlen sind alle Dezimalzahlen, also auf jeden Fall alle rationale Zahlen und zusätzlich noch
alle nicht-periodischen unendlichen Dezimalzahlen

5. komplexe Zahlen bestehen aus einem Realteil und einem Imaginärteil und haben die Form z = 1
+ 3i

Da die Unendlichkeit für Computer und Programmiersprachen noch schwieriger zu behandeln ist als
für (menschliche) Philosophen und Mathematiker, werden alle Komma“-Zahlen mit einer endlichen

Zahl Stellen gespeichert und unter dem Typ float“ zusammengefasst.

In Python muss nicht angegeben werden, welche Art von Zahl in einer Variablen gespeichert wird.
Deshalb ist es manchmal sinnvoll, die Art der Zahl festzustellen. Das folgende kleine Python-Schnipselchen

65
KAPITEL 3. DIE . . . 3.5. RECHNEN UND VERGLEICHEN

benutzt Strukturen, die erst später erklärt werden. 13 Darum gibt es hier ansatzweise eine Erklärung,
was in dem Beispiel unten steht und was passiert. Die eckige Klammer enthält eine Menge von Zahlen,
als letztes Element allerdings ein Wort, das im Deutschen für eine Zahl steht. Das Schlüsselwort for
leitet eine Schleife ein, wodurch mit jedem Eintrag in der Liste etwas gemacht wird, es wird nämlich
überprüft, ob der jeweilige Eintrag eine Zahl der Klasse ganze Zahlen“ (int), der Klasse Fließkom-
” ”
mazahlen“ (float) oder der Klasse komplexe Zahlen“ (complex) ist. Das geschieht mit der Funktion

isinstance. Hier folgt das Beispiel dazu:

Beispiel 3.5.1 Typ der Variablen bestimmen


>>> zahlen = [1, 1.0, 1+1j, ’eins’]
>>> for zahl in zahlen:
... if isinstance(zahl, (int, float, complex)):
... print(str(zahl)+’ ist eine ’+type(zahl).__name__)
... else:
... print(zahl+’ ist keine Zahl ’)
...
1 ist eine int
1.0 ist eine float
(1+1j) ist eine complex
eins ist keine Zahl

3.5.2. Operatoren
[Link]. Vergleichsoperatoren
Nachdem wir jetzt elementares Rechnen in IDLE ausprobiert haben, sollten auch noch weitere Operato-
ren genannt werden. Hier kommen zuerst einmal die üblichen Vergleichsoperatoren.

Tabelle 3.4. Vergleichsoperatoren


Zeichen Bedeutung Bemerkung
< kleiner
<= kleiner oder gleich
> größer
>= größer oder gleich
== gleich (gleicher Wert)
is gleich (das selbe Objekt)
!= ungleich (verschiedene Werte)
is not ungleich (verschiedene Objekte)

Besonders zu beachten in der obigen Tabelle sind die beiden Operatoren für die Gleichheit“. Das

sollte man auch in IDLE einmal ausprobieren, indem man zwei Variable definiert, die den selben Inhalt
haben:

Beispiel 3.5.2 Gleichheit


>>> p1 = 431 * 1289
>>> p2 = 555 559

Dann ergibt

>>> p1 == p2
13 Da es mehrere Strukturen sind, steht hier auch kein Verweis auf diese Strukturen.

66
KAPITEL 3. DIE . . . 3.5. RECHNEN UND VERGLEICHEN

True

das Ergebnis True, während

>>> p1 is p2
False

das Ergebnis False liefert. True bzw. False sind hier selbstverständlich die beiden logischen Wahr-
heitswerte wahr“ bzw. falsch“.
” ”

A NMERKUNG
Die Wahrheitswerte True und False sind eigentlich ganzzahlige Werte; True
hat den Wert 1, False den Wert 0. Das sieht man bei folgenden Berechnun-

gen“:

Beispiel 3.5.3 Rechnen mit Wahrheit


>>> print(True)
True
>>> print(True + True)
2
>>> print(True * 3)
3
>>> print(True + False)
1
>>> print(False + False)
0
>>> print(False * 3)
0

Ebenso ist beachtenswert, dass Python hier beim Vergleich von Zahlen den Typ berücksichtigt.

>>> a = 3

belegt eine Variable a mit dem Wert 3. Der Vergleich

>>> a == 6 / 2
True

liefert folglich den Wert True. Auch wenn man vergleicht

>>> a == 6. / 2.
True

(man beachte die beiden Punkte! Hier werden zwei Dezimalzahlen geteilt!), erhält man den Wert True.
Der Vergleich

67
KAPITEL 3. DIE . . . 3.5. RECHNEN UND VERGLEICHEN

>>> a is 6 / 2
True

liefert auch den Wert True, wenn man allerdings Python fragt, ob

>>> a is 6. / 2.
False

gilt, bekommt man die Antwort False.


Python kann vieles miteinander vergleichen . . . wenn es es kann. Einen Text mit einer Zahl kann
Python nicht vergleichen.

Beispiel 3.5.4 Vergleich nicht zulässig


>>> x = ’a’
>>> y = 2
>>> x < y
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: ’<’ not supported between instances of ’str’ and ’int’

Und Vorsicht: es ist auch ein Unterschied, ob man Zahlen und Texte miteinander vergleicht.

Beispiel 3.5.5 Vergleich von Zahlen und Texten


>>> xz = 3
>>> yz = 123
>>> xs = ’3’
>>> ys = ’123’
>>> xz < yz
True
>>> xs < ys
False

Die Zahl 3 ist kleiner als die Zahl 123; aber der Text 123“ kommt im Alphabet vor dem Text 3“, ist
” ”
also aus Sicht von Python kleiner.
Wenn man bereits andere Programmiersprachen kennengelernt hat, ist es interessant zu wissen, dass
man Vergleichsoperatoren verketten kann. Um in anderen Programmiersprachen zu überprüfen, ob eine
Zahl x zwischen 10 und 20 liegt, ist dort die Schreibweise

(10 < x) and (x < 20)

(wobei die Klammern normalerweise nicht nötig sind). In Python geht das einfacher durch

10 < x < 20

Man kann in Python bei Vergleichen vieles schreiben, aber man sollte nicht alles schreiben. Auch

y < x > z

68
KAPITEL 3. DIE . . . 3.5. RECHNEN UND VERGLEICHEN

ist für Python korrekte Syntax, aber hässlich (und wahrscheinlich in ein paar Wochen selbst für den
Schreiber unverständlich).
Weiter hinten bei Funktionen steht als Beispiel, wie man sich also eine kleine Funktion schreibt, die
ausgibt, ob eine Zahl zwischen zwei anderen Zahlen liegt.

[Link]. Verschiebeoperatoren
Speziell für Mathematiker und Informatiker interessant sind die Verschiebe-Operatoren. Verschiebe-
Operatoren verschieben das (unter Umständen gedachte) Dezimalkomma nach rechts oder links. Im
Dezimalsystem bewirkt das eine Multiplikation mit 10 (Komma wird um eine Stelle nach rechts verscho-
ben: aus 12,0 wird 120) oder eine Division durch 10 (Komma wird um eine Stelle nach rechts verschoben:
aus 12,0 wird 1,20)
So sieht das also im Dezimalsystem aus.

>>> 753 * 10 = 7530

Da der Computer Zahlen im Dualsystem darstellt, bedeutet die oben beschriebene Operation (Zif-
fernfolge um eins nach links verschieben, hinten mit Null auffüllen) hier eine Multiplikation mit 2. Aus
diesem Grund gibt es in Python (wie in vielen anderen Programmiersprachen) spezielle Operatoren für
die Multiplikation mit 2 (bzw. mit Potenzen von 2) und die Division durch 2 (bzw. durch Potenzen von
2).

Tabelle 3.5. Verschiebeoperatoren


Operator Beschreibung Bedeutung mathematisches Beispiel
<< Verschiebung nach links Multiplikation mit 2 (Potenz von 2) 3 << 1 = 6
3 << 2 = 12
3 << 4 = 48
>> Verschiebung nach rechts Division durch 2 (Potenz von 2) 16 >> 1 = 8
16 >> 2 = 4
16 >> 3 = 2

3.5.3. Komplexe Zahlen


You say you want a real solution
(John Lennon / Paul McCartney14 )
Für Mathematiker, Physiker und Techniker besonders interessant ist, dass Python von Haus aus kom-
plexe Zahlen beherrscht. Komplexe Zahlen werden (fast) genauso15 geschrieben, wie es Mathematiker
gewöhnt sind, das kleine i“ wird durch ein kleines j“ ersetzt:
” ”

>>> (1 + 2j)

Das sollte man jetzt (sofern man gerade vor dem Rechner sitzt) einmal ausprobieren. Eine komplexe
Zahl besteht ja aus einem Realteil und einem Imaginärteil. Auch die kann man sich natürlich anzeigen
lassen:

Beispiel 3.5.6 Komplexe Zahlen


>>> kzahl = 5 + 2j
>>> [Link]
5
>>> [Link]
2

14 Revolution auf The Beatles (White Album)


15 und genauso wie Physiker und Ingenieure es machen

69
KAPITEL 3. DIE . . . 3.5. RECHNEN UND VERGLEICHEN

Jetzt erinnert man sich daran, dass die imaginäre Einheit i definiert ist durch i*i = -1. Probieren
wir also einmal aus:

Beispiel 3.5.7 Was ist i*i (oder pythonisches j*j)?


>>> j*j
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name ’j’ is not defined
>>> (0+j)*(0+j)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name ’j’ is not defined
>>> 1j*1j
(-1+0j)
>>> (0+1j)*(0+1j)
(-1+0j)

Die ersten beiden Versuche sind fehlgeschlagen, denn Python erwartet eine imaginäre Zahl in der
Form bj bzw. eine komplexe Zahl in der Form a +bj
Und jetzt ziehen wir endlich die Wurzel aus -1. Die Quadratwurzel (siehe weiter unten bei import
sqrt ) steckt im Modul math, der also zuerst importiert werden muss

Beispiel 3.5.8 Wurzel aus -1


>>> import math
>>> [Link](-1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: math domain error
>>> import cmath
>>> [Link](-1)
1j

Auch das funktioniert im ersten Versuch nicht. Die Quadratwurzel im Modul math kann nur die
Wurzel aus positiven reellen Zahlen berechnen. Für die Funktionen von komplexen Zahlen benötigt
man den Modul cmath.

3.5.4. Andere Zahlsysteme


Für Programmierer interessant und deswegen in fast jeder Programmiersprache als ein Merkmal rea-
lisiert ist die Fähigkeit, Zahlen in anderen Zahlsystemen als dem Dezimalsystem darzustellen. Oktal-
zahlen werden mit einer führenden 0 eingegeben, Hexadezimalzahlen mit einem führenden 0x und
Dualzahlen mit einem führenden 0b.

Tabelle 3.6. Verschiedene Zahlsysteme und Umrechnung


010 ist die Oktalzahl 10 010 = 8dez
0x10 ist die Hexzahl 10 0x10 = 16dez
0b10 ist die Dualzahl 10 0b10 = 2dez

Dann sollte es natürlich auch möglich sein, von einem in das andere Zahlsystem umzurechnen. Die
dafür zuständigen Funktionen heißen
1. hex für die Umrechnung einer Zahl im Dezimalsystem in eine hexadezimale Zahl. Das Ergebnis
ist eine Zeichenkette mit vorangestelltem 0x.

70
KAPITEL 3. DIE . . . 3.5. RECHNEN UND VERGLEICHEN

2. oct für die Umrechnung einer Zahl im Dezimalsystem in eine oktale Zahl. Das Ergebnis ist eine
Zeichenkette mit vorangestelltem 0o.

3. int für die Umrechnung einer Zeichenkette (also auch einer Hexadezimal- oder Oktalzahl) in eine
Zahl im Dezimalsystem.

In idle eingegeben sieht das so aus:

Beispiel 3.5.9 Umwandlung von Zahlen in ein anderes Zahlsystem


>>> zahl = 15
>>> hex(zahl)
’0xf’
>>> oct(zahl)
’017’
>>> bin(zahl)
’0b1111’
>>> x = 0b1111
>>> x
15
>>> oct(x)
’017’
>>> hex(zahl)
’0xf’

3.5.5. Zufall

Selbstverständlich kann Python auch Zufallszahlen erzeugen. Dazu muss man einen Modul einbinden,
den Modul random. Ein Modul ist ein Stück Code, das jemand anderer geschrieben hat, und das funk-
tioniert. Das ist irgendwann einmal der Welt zur Verfügung gestellt worden. Das Einbinden geschieht
durch den Befehl import, hier also durch import random.
Jetzt wüssten wir natürlich gerne, was uns denn da alles bereitgestellt ist. Diese Information kann
man sich in zwei Darstellungsformen beschaffen:16

1. in der Kurzfassung, indem man sich nur ein Inhaltsverzeichnis anzeigen lässt

Beispiel 3.5.10 Kurz-Inhalt eines Moduls


>>> import random
>>> dir(random)
[’BPF’, ’LOG4’, ’NV_MAGICCONST’, ’RECIP_BPF’, ’Random’, ’SG_MAGICCONST’, ...]

2. ausführlich, indem man sich die Hilfe zu dem Modul anzeigen lässt

16 Die Ausgabe wurde nach den ersten 6 Einträgen aus Platzgründen abgeschnitten.

71
KAPITEL 3. DIE . . . 3.5. RECHNEN UND VERGLEICHEN

Beispiel 3.5.11 Hilfe-Text eines Moduls


>>> help(random)
Help on module random:

NAME
random - Random variable generators.

FILE
/usr/lib/python2.7/[Link]

MODULE DOCS
[Link]

DESCRIPTION
integers
--------
uniform within range

und jetzt folgen noch 1000 Zeilen Hilfetext.

[Link]. Zufällige ganze Zahlen


Denken wir uns also einen ganz normalen Würfel mit den Seiten 1 bis 6. Der soll 10 mal geworfen
werden (warum auch immer). Dazu wird aus dem Modul random die Methode random importiert. Da
ich die Syntax von randint nicht kenne, lasse ich mir sie mit Hilfe von help anzeigen. Aha, randint
benötigt zwei Variable, eine obere und eine untere Grenze. Damit ist klar was zu tun ist:

Beispiel 3.5.12 Zufällig würfeln


>>> from random import randint
>>>help(randint)
Help on method randint in module random:

randint(a, b) method of [Link] instance


Return random integer in range [a, b], including both end points.

>>> for i in range(10):


... print(randint(1,6))
...
4
6
1
5
6
6
5
1
3
6

Hier wurde der Befehl range benutzt. Der wird erst später bei den XrefId[?Schleifen?] eingeführt.
Wer nachblättern möchte: bitte schön. Für den, der das nicht will: range ist einfach ein Bereich.

72
KAPITEL 3. DIE . . . 3.6. SHORTCUT-OPERATOREN

[Link]. Zufällig ausgewählte Buchstaben aus einer Textzeile


Der Modul random enthält aber noch mehr. Wer das alles wissen will, gibt import random ein und
ruft danach die Hilfe mit help(random) auf. Ich will hier nur noch eine Methode von random zeigen:
eine zufällige Auswahl aus einem gegebenen Text. Dazu erstelle ich eine Textzeile alfabet, die das
Alfabet enthält. Aus dem Modul random importiere ich die Methode choice.

Beispiel 3.5.13 Zufällig 5-buchstabige Wörter bilden


>>> for i in range(10):
... wort = ’’
... for j in range(5):
... wort += choice(alfabet)
... print(wort)
...
tbuoh
jakrq
czhuy
lyywg
zybmc
nrxot
kedjq
haiyk
sagpi
nrkan

3.6. Shortcut-Operatoren
Es gibt in Python (wie in vielen anderen Programmiersprachen) Abkürzungen für oft benutzte Rechen-
operationen, auf englisch shortcuts“. Für den Programmieranfänger sind diese abgekürzten Schreib-

weisen oft nicht so übersichtlich wie eine ausführliche Schreibweise. Aber wenn man sich das laut vor-
liest, was gemacht werden soll, dann ist das eine große Erleichterung, wenn man diese Abkürzungen
benutzt.
Immer wieder muss man zum Beispiel den Wert einer Variablen erhöhen. In einem konkreten Beispiel
heißt das, dass die Variable alter“ den Wert 17 hat, aber am nächsten Geburtstag muss die Variable auf

18 erhöht werden. Der Programmieranfänger schreibt das meistens so:

Beispiel 3.6.1 noch kein Shortcut


>>> alter = 17
>>> alter = alter + 1

Klar, das löst das Problem. Auf den aktuellen Wert, den die Variable hat, wird 1 addiert und nach der
Addition wird der erhöhte Wert wieder in der Variablen alter“ gespeichert.

Die Abkürzung schreibt sich so:

Beispiel 3.6.2 Jetzt mit Shortcut


>>> alter = 17
>>> alter += 1

Das kann man sich selbst so vorlesen, wie vor diesem Beispiel!

73
KAPITEL 3. DIE . . . 3.6. SHORTCUT-OPERATOREN

Shortcuts gibt es für alle elementaren arithmetischen Operationen. Das wird in der folgenden Tabelle
so aufgelistet.

Tabelle 3.7. Shortcut-Operatoren


Operation lange Version Shortcut
Addition x=x+2 x += 2
Subtraktion x=x-3 x -= 3
Multiplikation x=x*5 x *= 5
Division x = x / 12 x /= 12

74
4. Richtig programmieren
4.1. Entwicklungsumgebungen
4.1.1. Die Entwicklungsumgebung Eric
Nachdem wir also eine ganze Weile jetzt mit IDLE gearbeitet haben, stellen wir fest: um einen oder
vielleicht zwei oder drei Python-Befehle zu testen ist das nicht schlecht. Auch ein erfahrener Program-
mierer hat IDLE oft nebenher geöffnet, um einmal die Wirkungsweise eines Befehls auszuprobieren. Um
größere Programme zu schreiben, ist IDLE aber nicht sehr geeignet. Da gibt es wirklich komfortablere
Entwicklungsumgebungen.
Und wie heißt wohl der Nachfolger (oder die Erweiterung; oder Verbesserung) von IDLE? Na, blättern
wir zum Anfang des vorigen Kapitels, dort findet sich doch ein kleiner Tipp. Hast Du es rausgekriegt?
Die mächtigere Entwicklungsumgebung ist Eric“. Und sie sieht so aus:

Abbildung 4.1. Die IDE Eric

In Eric“ können wir uns zum ersten Mal richtig daran machen, ein Programm zu schreiben. Das

richtig“ soll heißen, dass wir im Editor von Eric den Programmtext (auch Quelltext oder Quellcode

genannt) schreiben, in einer Datei speichern, und jetzt außerhalb von Eric auch diese Datei aufrufen
können.

4.1.2. IDE unter Windows


Die Installation von Eric unter Windows setzt eine Bibliothek voraus, die separat installiert werden
muss.

75
KAPITEL 4. RICHTIG PROGRAMMIEREN 4.1. ENTWICKLUNGSUMGEBUNGEN

Unter Windows ist deswegen eine andere IDE sehr verbreitet, der PyScripter“. Der sieht so aus:

Abbildung 4.2. Die IDE PyScripter

Für kleinere Arbeiten existiert eine IDE unter Windows, die schlank und schnell ist und für Anfänger
ausreichend, die Geany“. Allgemein gilt hier: die IDE ist die beste, mit der ich am besten arbeiten kann.

Und die Geschmäcker sind verschieden.

4.1.3. So sieht’s aus


Programmier-IDEs haben alle einen sehr ähnlichen Aufbau. Es gibt immer 4 große Bereiche in einer
solchen IDE, und bei manchen IDEs gibt es dann noch mehrere kleine Bereiche. Am oberen Rand der IDE
ist eine Menu-Zeile, darunter eine Button-Zeile für häufig benötigte Operationen. Links darunter ist ein
Bereich, in dem das Dateisystem abgebildet ist, so dass man hier navigieren und eine Datei auswählen
kann. Rechts daneben ist der Editor-Bereich, in dem man seinen Quelltext schreibt. Für diesen Editor
gibt es natürlich auch Buttons, mit denen man Editier-Operationen durchführen kann. Es ist aber sehr
sinnvoll, sich die wichtigsten Tastatur-Befehle zu merken, denn das geht meistens viel schneller!1 Unter
diesen beiden Bereichen ist dann der Ausgabe-Bereich, in den die Programme ihre Ausgabe schreiben.
Unter Python ist dieser Ausgabebereich eine interaktive Python-Shell, in der man auch einzelne Befehle
eingeben und testen kann.

4.1.4. Der Programm-Rahmen


Weil Python-Programme von der Syntax her portabel sind, das heißt ohne Veränderung des Quellco-
des auf einem beliebigen Rechner (auf dem natürlich der Python-Interpreter installiert ist!) unter ei-
1 (Ein
Bild, das diese veranschaulicht, findet man unter <[Link]
uploads/2011/02/[Link]>.)

76
KAPITEL 4. RICHTIG PROGRAMMIEREN 4.2. DAS ABSOLUTE MUSS: HALLO IHR ALLE

nem beliebigen Betriebssystem lauffähig sind, sollten wir uns hier bemühen, das Programm auch so zu
schreiben, dass das gewährleistet ist.2 Dazu gewöhnt man sich an, die unter Unix und MacOS übliche
sha-bang“-Zeile einzufügen, die dem Betriebssystem sagt, mit welcher Art von Programm (hier also:

mit dem Python-Interpreter) die Datei zu bearbeiten ist und wo sich der Interpreter befindet:

Beispiel 4.1.1 Sha-Bang


#!/usr/bin/python

Der ist unter Unixen normalerweise im Verzeichnis /usr/bin . Aber leider nicht immer, deswegen ist
die bessere Methode die, dass man das Betriebssystem auffordert, den Interpreter selber zu suchen:

Beispiel 4.1.2 Programmaufruf mit Umgebungsvariable


#!/usr/bin/env python

Hier wird das env-Kommando benutzt, das in der Umgebung (dem Environment) des Betriebssys-
tems nach dem Interpreter sucht.
Und diese Zeile wird von den DOS-ähnlichen Betriebssystemen (also Windows) großmütig ignoriert,
stört also in keinem Fall.

4.2. Das absolute Muss: Hallo Ihr alle


Es gibt ernsthafte Stimmen, die behaupten, dass es Unglück bringt, zum Beispiel 3 Tage lang Linsen
mit Spätzle oder dass Bayern München schon wieder Deutscher Fußballmeister wird oder dass man die
Blumen für den Hochzeitstag, an die man glücklich gedacht hat, geklaut bekommt, wenn man nicht
als erstes Programm eine Begrüßung an den Rest der Welt schreibt: das berühmte Hallo world“. Also

dann, das sieht in Python so aus:

Beispiel 4.2.1 Hallo world


#!/usr/bin/env python
# -*- coding: utf-8 -*-

print(’hallo world’)

So einfach! Es ist keine Einbindung von Bibliotheken nötig (denke daran: batteries included!), keine
Tricks, die den Anfänger verwirren.
In der Zeile nach dem sha-bang steht etwas, das wie ein Kommentar aussieht. Das ist aber eine An-
weisung an den Interpreter, die ihm mitteilt, welche Kodierung das Programm benutzt. Hier ist die
Unicode-Kodierung utf-8“ eingestellt. Unter Windows 3 ist es oft sinnvoller, die Kodierung auf iso8859-

1 oder latin1 umzustellen.

2 Zu beachten hierbei ist allerdings, dass DOS (und damit Windows), Unix (und damit Linux) und MacOS verschiedene Zei-
chen benutzen, um den Zeilenvorschub zu kennzeichnen. Aber jedes der Betriebssysteme hat irgendein Hilfsmittel, um die
Zeilenende-Zeichen zu übersetzen.
3 wie immer zeitlich ein bißchen hinterher

77
KAPITEL 4. RICHTIG PROGRAMMIEREN 4.3. DIE ERSTEN EINFACHEN PROGRAMME

A NMERKUNG
Unter Python 3.x hat sich das geändert. Hier wird als Standard-Kodierung utf-8“

angenommen, das heißt, dass man diese Zeile nur noch schreiben muss, wenn
man auf einem System arbeitet, das noch nicht Unicode benutzt.a

a Also hoffentlich bald überhaupt nicht mehr.

4.3. Die ersten einfachen Programme


In einem Saftladen soll eine einfache Rechnung geschrieben werden. Das Programm dazu hat die Preise
für die 3 Getränke, die zur Auswahl stehen, fest eincodiert. Vom Benutzer werden jetzt die konsumierten
Getränke abgefragt, dann wird der Rechnungsbetrag ermittelt und ausgegeben.
Eine Eingabe durch den Benutzer wird über den Python-Befehl input“ gemacht. Die Syntax lautet:

variable = input(”Text zur Eingabeaufforderung”) Texte müssen in Anführungsstriche geschrieben wer-
den. input“ fasst die Eingabe als Text auf. Soll das, was eingegeben wird, als Ganzzahl oder als Fließ-

kommazahl verwendet werden, so muss das umgewandelt werden durch int(input(...)) bzw.
durch float(input(...)).

Beispiel 4.3.1 Saftladen


#!/usr/bin/env python
# -*- coding: utf-8 -*-

print("Saftladen\n\n")
prApfelschorle = 0.70
prBananenmilch = 1.20
prOrangensaft = 0.80

anzAschorle = int(input(’Wieviel Apfelschorle? ’))


anzBmilch = int(input(’Wieviel Bananenmilch? ’))
anzOsaft = int(input(’Wieviel Orangensaft? ’))

preis = anzAschorle * prApfelschorle + anzBmilch * prBananenmilch


+ anzOsaft * prOrangensaft
print(’Summe: ’, preis)

Im zweiten Programm werden zwei Minuten-Zahlen von Benutzern eingegeben, und diese werden
in die üblichen Einheiten (x Stunden, y Minuten) umgerechnet:

Beispiel 4.3.2 Rechnen mit Uhrzeiten


#!/usr/bin/env python
# -*- coding: utf-8 -*-

min1 = int(input(’erste Minuten-Zahl: ’))


min2 = int(input(’zweite Minuten-Zahl: ’))

sum = min1 + min2


std = sum // 60
min = sum % 60

print(std,’ Stunde(n) ’,min,’ Minuten’)

78
Teil III.

Texte und andere Daten

79
5. Texte
And now for something completely different
(John Cleese 1 )

5.1. Grundlegendes zu Texten


Python kennt nicht den Datentyp des Zeichens; ein Zeichen ist einfach eine Zeichenkette der Länge 1.
Für Zeichenketten ist der englische Ausdruck strings“ üblich.

Strings sind unveränderlich (engl. immutable), d.h. sie können nicht am ursprünglichen Speicherplatz
verändert werden. Die wichtigste Regel für Zeichenketten ist, dass Zeichenketten in Anführungszeichen
geschrieben werden. Texte nicht in Anführungszeichen zu schreiben ist bei Anfängern in vielen Pro-
grammiersprachen einer der häufigsten Fehler. Wir werden aber sehen, dass Python da hilfreich ist, so
dass viele der üblichen Fehler schon beim Schreiben eines Programmes abgefangen werden.
In Python ist es egal, ob man einfache Anführungszeichen (auf der Tastatur über dem Lattenzaun #
zu finden) oder doppelte Anführungszeichen (auf der Tastatur über der 2 zu finden) benutzt.
Ein Beispiel dazu:

>>> zKette = "Martin"

ist gleichwertig zu

>>> zKette = ’Martin’

Die Art der Anführungsstriche ist bedeutsam, wenn der Text selber Anführungsstriche bzw. Apostro-
phe enthält. Es funktioniert also

>>> zKette1 = "Zeig mir, wie’s geht"

bzw.

>>> zKette2 = ’Gasthaus zum "Goldenen Ochsen" ’

Eine andere Möglichkeit, einfache Anführungsstriche in einem Text, der von doppelten Anführungsstrichen
eingeschlossen ist, zu benutzen (oder umgekehrt), ist das Maskieren“ von Anführungsstrichen:

>>> text = "Gasthaus zum \"Goldenen Ochsen\""


>>> text
’Gasthaus zum "Goldenen Ochsen"’
>>> print(text)
Gasthaus zum "Goldenen Ochsen"

Maskiert wird ein Zeichen durch das Voranstellen eines Backslashes.


Dreifache Anführungszeichen haben eine besondere Bedeutung: sie begrenzen mehrzeiligen Text. Das
wichtigste Beispiel (in Python) ist also:
1 Ansage in: Monty Python’s Flying Circus

81
KAPITEL 5. TEXTE 5.1. GRUNDLEGENDES ZU TEXTEN

>>>sinn = ’’’Always look


on the bright
side of life’’’

Wenn wir das so in IDLE eingeben, ist es interessant zu sehen, wie das wieder ausgegeben wird. Es ist
wieder ein Unterschied ob man diesen Spruch ausgibt, indem man einfach den Variablennamen

>>> sinn

eingibt, oder ob man IDLE ausdrücklich anweist, sinn“ auszudrucken:


>>> print(sinn)

Abbildung 5.1. Texte in der IDE Idle

Man achte auch auf die Anführungsstriche in der Ausgabe!!


Die seltsame Zeichenkombination \n taucht hier zum ersten Mal auf. Das muss erklärt werden. In je-
dem Computer-System gibt es eine Anzahl Steuerzeichen. So nennt man Zeichen mit einer besonderen
Bedeutung, die für die Steuerung des Rechners, genauer des Ausgabemediums, das in der Regel der
Bildschirm ist, benötigt werden. Das wichtigste Steuerzeichen ist wohl das Zeichen für den Zeilenvor-
schub. Es wird mit \n codiert.

82
KAPITEL 5. TEXTE 5.1. GRUNDLEGENDES ZU TEXTEN

Beispiel 5.1.1 Zeilenvorschub (Steuerzeichen)


>>> vierZ = ’Das\nsind\n4\nZeilen’
>>> vierZ
’Das\nsind\n4\nZeilen’
>>> print(vierZ)
Das
sind
4
Zeilen

Die wichtigsten Steuerzeichen stehen in der folgenden Tabelle:

Tabelle 5.1. Steuerzeichen


Zeichen Bedeutung
\a Piepser (alarm)
\b ein Zeichen zurück (backspace)
\f Seitenvorschub (forward 1 page)
\n Zeilenvorschub (new line)
\r Wagenrücklauf (return)
\t Tabulator

Python kann auch mit Texten rechnen.2 Was dabei herauskommt, wenn man Texte addiert oder einen
Text mit einer Zahl multipliziert, sieht man hier

Abbildung 5.2. Multiplikation von Texten

So kann man also ganz schnell mal den Bildschirm von IDLE löschen:

>>> print(40*"\n")

2 Das hört sich seltsam an. Aber lies einfach weiter!

83
KAPITEL 5. TEXTE 5.2. OPERATIONEN AUF TEXTEN

5.2. Operationen auf Texten


And the first one now
Will later be last
(Bob Dylan3 )
Texte, also Zeichenketten, sind aus einzelnen Zeichen zusammengesetzt. Die dafür übliche Daten-
struktur ist das Feld, auf englisch array“. Ein Feld ist dadurch gekennzeichnet, dass jedes Element

des Feldes eine Hausnummer hat. Zu beachten dabei ist, dass Informatiker oft auch Mathematiker sind,
weswegen niemand von Hausnummer, sondern jeder von Index“ redet und die erste Hausnummer,

also der erste Wert für den Index, nicht die 1“ ist, sondern die 0“. Wenn wir also eine typische Zei-
” ”
chenkette betrachten

>>> FilmDerWoche = ’Das Leben des Brian’

dann kann man das als Feld so betrachten:

Tabelle 5.2. Zeichenkette als Feld betrachtet


Index 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
Wert D a s L e b e n d e s B r i a n

Selbstverständlich kann man somit auch jedes einzelne Element der Zeichenkette ansprechen:

Beispiel 5.2.1 Elemente eines String


>>> FilmDerWoche = ’Das Leben des Brian’
>>> print(FilmDerWoche[2])
s
>>> print(FilmDerWoche[5])
e

Damit hat man schon das wichtigste Prinzip für die Bearbeitung von Texten verstanden! Man kann je-
den Text als Aneinanderreihung von Zeichen auffassen, und jedes einzelne Zeichen herausfiltern, indem
man den Namen der Zeichenkette gefolgt von der Hausnummer in eckigen Klammern angibt.
Dieses Prinzip wird jetzt aufgebohrt: man will ja oft nicht nur einen Buchstaben herausfiltern, son-
dern einen ganzen Bereich. Der technische Begriff dafür in Python lautet Slicing“. Der gewünschte

Teilbereich wird einfach in eckigen Klammern in der Form Anfangs-Element : End-Element an-
gegeben, wobei zu beachten ist, dass das Anfangs-Element mit ausgewählt wird, das Endelement das
erste Element ist, das nicht mehr ausgewählt wird.

Beispiel 5.2.2 Slicing


>>> filmDerWoche = ’Das Leben des Brian’
>>> print(filmDerWoche[5:9])
eben
>>> print(filmDerWoche[2:6])
s Le

Für Texte nicht so interessant ist, dass man hier auch noch einen dritten Parameter mitgeben kann.
Dieser gibt eine Schrittweite an, in der etwas aus einem Text herausgeschnitten werden soll
3 The times they are a-changing auf: The times they are a-changing

84
KAPITEL 5. TEXTE 5.2. OPERATIONEN AUF TEXTEN

Beispiel 5.2.3 Slicing (Forts.)


>>> filmDerWoche = ’Das Leben des Brian’
>>> print(filmDerWoche[1:9:2])
a ee

Zur Erläuterung: das 3. Zeichen ist ein Leerzeichen!! (Nicht vergessen: man fängt bei 0 an zu zählen!!)
Am besten gefällt mir das folgende Problem: einen Text umdrehen (also von hinten nach vorne schrei-
ben), das, was wir als kleine Kinder gespielt haben. Wie heißt denn Du von hinten nach vorne?“ Mit

Hilfe von Python ist das ganz einfach:

Beispiel 5.2.4 Umgekehrter Text


>>> vorname1 = ’martin’
>>> vorname2 = ’hannah’
>>> print(vorname1[::-1])
nitram
>>> print(vorname2[::-1])
hannah

Klar? Nimm den Text von Anfang bis Ende und gib ihn in der Schrittweite -1 aus.

5.2.1. Methoden von Zeichenketten


Der Begriff Methode“ gehört noch gar nicht hier her. Methode bezeichnet eine Funktion innerhalb einer

Klasse. Aber Klassen werden erst im Kapitel Klasse weiter hinten bearbeitet.
Ups! Der Begriff Funktion“ gehört noch gar nicht hier her. Funktion bezeichnet ein Programm in-

nerhalb eines Programms, ein Unterprogramm. Aber Funktionen werden erst im Kapitel Funktionen
weiter hinten bearbeitet.
Methoden werden aufgerufen, indem man an den Klassennamen einen Punkt und dann den Metho-
dennamen anhängt.
Eine wichtige Methode von Zeichenketten ist das Splitten. Eine Zeichenkette kann so an einem be-
stimmten Zeichen aufgespalten werden. Das Ergebnis ist eine Liste von Zeichenketten (siehe weiter
hinten bei Listen ). Das als Standard eingestellte Trennzeichen ist das Leerzeichen. Das soll an einem
Beispiel verdeutlicht werden.

Beispiel 5.2.5 Splitten


>>> name = ’Martin Schimmels Oberndorf’
>>> [Link]()
[’Martin’, ’Schimmels’, ’Oberndorf’]
>>> [Link]()[1]
’Schimmels’
>>> [Link]()[-1]
’Oberndorf’
>>> [Link]()[-2]
’Schimmels’
>>>

Hier wird also wirklich an den Leerzeichen getrennt. Das Trennzeichen kommt dann in keiner der
Teillisten vor. Die einzelnen Teile kommen in eine Liste, und damit kann man die einzelnen Elemente
der Liste mit ihrer Hausnummer ansprechen (Beachte: das Zählen fängt bei 0 an!!). Wenn man als Index
eine negative Zahl benutzt, wird von hinten gezählt!

85
KAPITEL 5. TEXTE 5.2. OPERATIONEN AUF TEXTEN

Als Trennzeichen kann ein beliebiges Zeichen fungieren, sogar eine Zeichenkette ist möglich:

Beispiel 5.2.6 Splitten bei einer vorgegebenen Zeichenkette


>>> text = ’Martinxyzistxyzdoof’
>>> fuellzeichen = ’xyz’
>>> [Link](fuellzeichen)
[’Martin’, ’ist’, ’doof’]

Die Methode join macht das Splitten rückgängig.

Beispiel 5.2.7 Splitten und Wiederherstellen


>>> name = ’Martin Schimmels Oberndorf’
>>> liste = [Link]()
>>> print(liste)
[’Martin’, ’Schimmels’, ’Oberndorf’]
>>> ’ ’.join(liste)
’Martin Schimmels Oberndorf’

Aber Vorsicht: join ist eine Methode,4 die mit Texten arbeitet, nicht mit Listen. Deswegen steht ein
Text, in diesem Fall der Text, der aus einem einzigen Leerzeichen besteht, voran, gefolgt von einem
Punkt und dem Methodennamen. Das Argument der Methode ist in diesem Fall eine Liste.
Weitere Operationen auf Texten sind das Finden und das Ersetzen. Erinnere Dich an das oben gesagte:
Texte sind unveränderbar. Ein Ersetzen ändert den Inhalt der Variablen nicht. Aber das veränderte Stück
Text kann einer (anderen) Variablen zugewiesen werden. Das sieht so aus:

Beispiel 5.2.8 Suchen und ersetzen


1

2 >>> name = ’Martin Schimmels Oberndorf’


3 >>> [Link](’Schi’)
4 7
5 >>> [Link](’Oberndorf’, ’Rottenburg’)
6 ’Martin Schimmels Rottenburg’
7 >>> name
8 ’Martin Schimmels Oberndorf’
9 >>> [Link](’S’)
10 7 # Beachte: man fängt bei 0 an zu zählen!
11

12

In Zeile 3 wird als Ergebnis des Suchens die Zahl 7 ausgegeben. Das heißt, dass das Programm den
gesuchten Text an der 7. Stelle des Namens gefunden hat. In Zeile 5 wird der Name ausgegeben mit der
Ersetzung, aber in Zeile 7 sieht man, dass der Wert der Variablen name noch unverändert ist.
Auch die Untersuchung, ob ein Textstück in einem Text enthalten ist, kommt relativ häufig vor. Das
geschieht über das Schlüsselwort in.

4 was das ist, kommt leider erst später, wenn ich Klassen einführe

86
KAPITEL 5. TEXTE 5.2. OPERATIONEN AUF TEXTEN

Beispiel 5.2.9 Enthaltensein


1

2 >>> name = ’Martin Schimmels Oberndorf’


3 >>> if ’mm’ in name:
4 >>> print(’gefunden’)
5 gefunden
6

Weitere Methoden, mit denen man mit Texten arbeiten kann, werden hier unten als Befehl in eine
Shell eingegeben. Die Ausgabe spricht für sich selbst.

Beispiel 5.2.10 Mehr mit Texten


1

2 >>> name = ’Martin Schimmels Oberndorf’


3 >>> [Link]()
4 ’MARTIN SCHIMMELS OBERNDORF’
5 >>> [Link]()
6 ’martin schimmels oberndorf’
7 >>> [Link](40)
8 ’ Martin Schimmels Oberndorf ’
9 >>> [Link](40,’*’)
10 ’*******Martin Schimmels Oberndorf*******’
11

Wenn man mit Texten arbeitet, ist es oft nötig, überflüssige“ Zeichen zu entfernen, so etwa alle

möglichen Leerzeichen, auf englisch whitespaces“, am Anfang oder am Ende eines Textes. Zu diesen

Leerzeichen gehören

• das Leerzeichen

• der Tabulator

• der Zeilenvorschub

Dafür (und allgemeiner für die Entfernung beliebiger Zeichen) steht die Methode strip zur Verfügung.
Ohne einen Parameter werden genau die oben genannten Leerzeichen entfernt, aber man kann auch
einen oder mehrere Parameter in der Klammer angeben.

Beispiel 5.2.11 Strippen


1

2 >>> text = ’\n Hendrix:Voodoo Chile \t’


3 >>> [Link]()
4 ’Hendrix:Voodoo Chile’
5 >>> text = ’****Hendrix:Voodoo Chile****’
6 >>> [Link](’*’)
7 ’Hendrix:Voodoo Chile’
8 >>> text = ’*-*-*Hendrix:Voodoo Chile*-*-*’
9 >>> [Link](’*-’)
10 ’Hendrix:Voodoo Chile’
11

Ein Sonderfall für das Strippen ist das Entfernen eines Zeilenvorschubs am Ende einer Zeile. Das wird
später beim Lesen aus einer Datei relevant. Es wird erledigt durch [Link]()
Weiter oben in diesem Kapitel wurden die Steuerzeichen angesprochen. Während es in der Unix-Welt
fast keine Probleme mit Backslashes gibt, hat Microsoft leider dieses Zeichen als Pfad-Trenner miss-

87
KAPITEL 5. TEXTE 5.3. KODIERUNGEN

braucht.5 Das bringt Probleme mit sich, wenn man aus einem Programm heraus auf einen vollqualifi-
zierten Dateinamen zugreifen muss, also auf etwas in der Art

C:\Benutzer\Texte\Liebesbriefe

Da gibt es die Möglichkeit, den Backslash durch einen Doppelbackslash zu maskieren. Das macht ein
Programm nicht unbedingt lesbar. Die andere Möglichkeit ist, einen Text, der wie der obige Backslashes
enthält, als raw string“ zu codieren. Raw strings schalten die Interpretation des Backslashes als Steu-

erzeichen aus und interpretieren ihn als normales Zeichen. Das geschieht durch ein Voranstellen eines
r“. Beispiel:

verzeichnis = r’C:\Benutzer\Texte\Liebesbriefe’

5.2.2. Wie und wo gespeichert wird

Bin ich? Und wenn ja,


wieviele bin ich?

—frei nach R.D. Precht

Geben wir folgende Anweisungen ein:

Beispiel 5.2.12 Kopie oder keine Kopie


>>> schlange = ’Python’
>>> sprache = ’Python’
>>> schlange == sprache
True
>>> schlange is sprache
True
>>> id(sprache)
140169203725008
>>> id(schlange)
140169203725008

Der erste Vergleich mit == stellt fest: ja, die beiden Variablen haben den selben Wert. Der zweite
Vergleich mit is stellt fest: das ist sogar das selbe Objekt, auf das jetzt nur zwei verschiedene Zeiger
weisen. Mittels der Funktion id sieht man jetzt, dass schlange und sprache tatsächlich die selbe
Adresse haben.

5.3. Kodierungen
Das ist unter Python3 (fast) kein Problem mehr! Zeichenketten in Python3 sind Unicode-Zeichenketten.
Das ganze Problem der Kodierung und Dekodierung taucht in Python3 nicht mehr auf.
Die Umsetzung von Zeichen in Maschinenzahlen (die berühmten 01000111 - Folgen) kann selbst-
verständlich auf verschiedene Art erfolgen. Dies ist eine Frage der Vereinbarung. Übliche Vereinbarun-
gen sind der ASCII 6 , der EBCDIC 7 , beide aus der Steinzeit der Datenverarbeitung. Das Problem dieser
alten Kodierungen ist, dass sie nur eine begrenzte Menge von Zeichen darstellen können. Aus diesem
Grund hat man sich Kodierungen überlegt, die mehr Zeichen aufnehmen können. Zuerst hat man beim
ASCII, der ursprünglich nur 128 Zeichen aufnehmen konnte, den Platz verdoppelt. Mit westeuropäisch-
nordamerikanischer Arroganz dachte man, damit alle Probleme gelöst zu haben: 26 Großbuchstaben, 26
5 ganz zu schweigen von dem mittleren Blödsinn, den uns manche weismachen wollen, dass in Dateinamen, Verzeichnisnamen
etc. Leerzeichen und Sonderzeichen auftreten dürfen
6 ASCII: American Standard Code for Information Interchange
7 Extended Binary Coded Decimals Interchange Code

88
KAPITEL 5. TEXTE 5.3. KODIERUNGEN

Kleinbuchstaben, ein paar Satzzeichen, die 10 Ziffern und dann für Französisch noch ein paar Vokale
mit Akzenten, für Deutsch noch ein paar Umlaute, da reichen doch 256 Zeichen.
Schnell hat man dann aber gemerkt, dass es so nicht geht. Kyrillisch, griechisch, türkisch, alle diese
Sprachen haben wieder eigene Zeichen. Also hat man für Sprachfamilien (wie zum Beispiel für die
nordeuropäischen Sprachen oder für die südosteuropäischen Sprachen) eigene Kodierungen erstellt,
die dann normiert wurden unter iso8859-x“. Dabei war x eine Zahl zwischen 1 und 15. Immerhin

konnte man dann in jeder Sprache die üblichen Zeichen darstellen, aber wenn man die Sprache (bzw.
die Sprachfamilie) verließ, musste man auch eine neue Kodierung auswählen.
Die Lösung heißt Unicode. Hier hat man Platz geschaffen, um auch Sprachen mit wesentlich mehr
Zeichen (wie zum Beispiel Chinesisch) aufzunehmen und dabei alles in eine Kodierung zu packen.
Unicode enthält weit über 100 000 Zeichen. Diese sind in Ebenen zusammengefasst, von denen jede 65
536 Zeichen enthält. Ebene 0 enthält die ASCII-Zeichen.
In Python3 können Unicode-Zeichen angegeben werden durch
1. \u gefolgt von einer vierstelligen Hexadezimalzahl. Damit werden Zeichen der elementaren Ebe-
nen (0 bis 256, in Hexadezimalschreibweise 00 bis FF) angegeben. Die ersten beiden Stellen der
Zahl geben die Ebene an, wobei 00 die ASCII-Ebene ist, die letzten beiden Stellen geben die Posi-
tion des Zeichens in der Ebene an.
2. \U gefolgt von einer achtstelligen Hexadezimalzahl. Damit werden Zeichen der höheren Ebenen
(größer als256) angegeben.
3. \N{Bezeichnung}, wenn die Bezeichnung des Zeichens bekannt ist.

Beispiel 5.3.1 Unicode-Strings


>>> z = ’\u0041’
>>> print(z)
A
>>> z = ’\u00E9’
>>> print(z)

>>> z = ’\N{LATIN SMALL LETTER E WITH ACUTE}’
>>> print(z)

89
KAPITEL 5. TEXTE 5.4. FORMATIERUNG VON ZEICHENKETTEN

5.3.1. Unicode in Python 3

Beispiel 5.3.2 Unicode-Strings


>>> import unicodedata
>>> [Link](’$’)
’DOLLAR SIGN’
>>> [Link](’\euro\/ ’)
’EURO SIGN’
>>> [Link](’\u2603’)
’SNOWMAN’
>>> [Link](’é’)
’LATIN SMALL LETTER E WITH ACUTE’
>>> p = ’caf\u00e9’
>>> print(p)
café
>>> t = ’th\u00e9 \N{LATIN SMALL LETTER A WITH GRAVE} la menthe’
>>> print(t)
thé à la menthe
>>> t2 = ’th\N{LATIN SMALL LETTER E WITH ACUTE}
\N{LATIN SMALL LETTER A WITH GRAVE} la menthe’
>>> print(t2)
thé à la menthe
>>>

Leider wird in diesem Skript der Schneemann nicht angezeigt. Aber auch dazu gibt es in unicodedata
eine Methode: [Link](’SNOWMAN’)

5.4. Formatierung von Zeichenketten


Ziele der Formatierung von Zeichenketten sind:

1. Die Ausgabe soll schön, ordentlich, übersichtlich, lesbar . . . sein


2. Der Ausgabe-Befehl soll variabel sein.

5.4.1. Die C-ähnliche Formatierung mit dem %-Operator


Die Regeln für die formatierte Ausgabe sind nicht schwer zu merken: das alleinstehende Prozentzeichen
trennt die Formatierungsanweisung von den zu formatierenden Variablen. Diese Syntax lehnt sich an
die Syntax der C-ähnlichen Sprachen an, wo eine solche Formatierung beim printf-Befehl verwendet
wird. Hier noch formal:

print(FORMATIERUNGSANWEISUNG % (VAR1, VAR2, etc.))

Nehmen wir an, wir wollen einen Gruß ausgeben, in den ein Name eingefügt werden soll.

Beispiel 5.4.1 Formatierungsanweisungen


>>> du = ’Hannah’
>>> print(’Guten Tag, %s, wie geht es Dir?’ % du)
Guten Tag, Hannah, wie geht es Dir?

90
KAPITEL 5. TEXTE 5.4. FORMATIERUNG VON ZEICHENKETTEN

Zuerst wird die Variable du deklariert, dann wird ein print-Befehl ausgegeben, der mit dem Text
Guten Tag,“ beginnt. Es folgt der Platzhalter für die Variable, versehen mit einem Formatierungsbefehl:

das erste %-Zeichen steht für die erste zu formatierende Variable; das darauffolgende s gibt an, dass
es sich bei der zu formatierenden Variablen um einen String, eine Zeichenkette, handelt. Es folgt ein
weiteres Stück Text, worauf sich das %-Zeichen, das Formatierungsanweisung von zu formatierenden
Variablen trennt, anschließt. Da wir in diesem Beispiel nur eine Variable haben, steht dort also nur die
Variable du.

A CHTUNG
In Python ab Version 3.x ist die Formatierung mit Hilfe der C-ähnlichen Syntax,
also der oben beschriebenen %-Anweisungen“ entweder verpönt oder verboten

(je nach Version). Hier funktioniert die Formatierung mittels der format-Methode
von Strings.

Ein weiteres Beispiel folgt, diesmal mit zwei Variablen:

Beispiel 5.4.2 Formatierung mit 2 Parametern


>>> mann = ’Romeo’
>>> frau = ’Julia’
>>> print(’Berühmte Liebespaare: %s und %s’ % (mann, frau))
Berühmte Liebespaare: Romeo und Julia
>>> m = ’Loriot’
>>> f = ’Evelyn Hamann’
>>> print(’Berühmte Liebespaare: %s und %s’ % (m, f))
Berühmte Liebespaare: Loriot und Evelyn Hamann

Das ganze wird interessant, wenn man auch Zahlen formatiert ausgeben will. Hier folgt eine Liste der
Format-Codes:

Tabelle 5.3. Format-Codes


Code Bedeutung
%s Zeichenkette (oder beliebiges anderes Objekt)
%i Integers (ganze Zahlen)
%f Fließkommazahl
%e Fließkommazahl in Exponentialschreibweise

Die Format-Codes für Zahlen können noch Optionen bekommen.

Tabelle 5.4. Format-Option-Codes


neue Option Beispiel Erläuterung
. ([Link]) %4.2f Die Zahl wird in einer Feldbreite von 4 Zeichen da-
von 2 Nachkommastellen ausgegeben.
0 (vorangestellt) %06.2f Die Zahl wird in einer Feldbreite von 6 Zeichen da-
von 2 Nachkommastellen und mit führenden Nul-
len ausgegeben.
- (Minuszeichen) %-6.2f Die Zahl wird in einer Feldbreite von 6 Zeichen da-
von 2 Nachkommastellen linksbündig ausgegeben.
+ (Pluszeichen) %+6.2f Die Zahl wird in einer Feldbreite von 6 Zeichen mit
2 Nachkommastellen und mit Vorzeichen ausgege-
ben.

91
KAPITEL 5. TEXTE 5.4. FORMATIERUNG VON ZEICHENKETTEN

5.4.2. Die Formatierung mit Hilfe der format-Methode

Seit Python 2.6 existiert eine weitere Möglichkeit, Ausgaben zu formatieren. Die Methode format bietet
ein paar zusätzliche Möglichkeiten, die die Formatierung komfortabler machen. Außerdem ist eine Feh-
lerquelle, die doppelte Bedeutung des Prozentzeichens innerhalb der Formatierungsanweisung, damit
hinfällig. Die allgemeine Syntax einer Formatierung mittels der format-Methode sieht so aus:

Beispiel 5.4.3 format in Pseudocode


fs = Format-Muster
[Link](Werte)

Das soll an einem Beispiel gezeigt werden. Hier sollen die Zahlen 1 bis 10, ihre Quadrate und ihre
Kuben (3. Potenzen) angezeigt werden. Zuerst läuft das Programm ohne Formatierung ab:

Beispiel 5.4.4 Unformatierte Ausgabe (Quelltext)


#!/usr/bin/python
# -*- coding: utf-8 -*-

for i in range(10):
print(i, i**2, i**3)

Das sieht nicht gut aus, denn wir erwarten schon die Ausgabe in Spalten untereinander, wobei die
Zahlen wie gewohnt rechtsbündig geschrieben sein sollten.

Beispiel 5.4.5 Unformatierte Ausgabe


>>>
0 0 0
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729

Jetzt wird formatiert! Das kann auf zwei Arten realisiert werden:

1. indem man die zu formatierenden Werte direkt in die Ausgabe schreibt

2. indem man einen Format-Muster aufbaut und die Format-Methode von Zeichenketten mit dem
Format-Muster aufruft.

Zuerst kommt hier also die direkte Ausgabe:

92
KAPITEL 5. TEXTE 5.4. FORMATIERUNG VON ZEICHENKETTEN

Beispiel 5.4.6 Formatierte Ausgabe direkt (Quelltext)


>>> for i in range(1,11):
print(’{zahl:>4}{quadr:>6}{kubus:>8}’.format(
zahl = i, quadr = i*i, kubus = i*i*i))

1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729
10 100 1000

Und jetzt kommt das selbe mittels eines Format-Musters.

Beispiel 5.4.7 Formatierte Ausgabe mittels Format-Muster(Quelltext)


#!/usr/bin/python
# -*- coding: utf-8 -*-

formatMuster = "{:>4} {:>6} {:>8}"

for i in range(10):
print([Link](i, i**2, i**3))

In dem Formatmuster steht für jeden Ausdruck, der ausgegeben werden soll, in einem Paar von ge-
schweiften Klammern eine Formatierungsanweisung. Nach dem Doppelpunkt steht dann in jeder ge-
schweiften Klammer in unserem Fall zuerst die Positionierungsanweisung >, die signalisiert, dass die
Ausgabe nach rechts geschoben wird, also rechtsbündig stehen soll. Danach steht die Feldbreite für die-
sen Teil der Ausgabe. Die 3 geschweiften Klammern geben also an, dass die erste Zahl auf 4 Stellen
Breite rechtsbündig geschrieben werden soll. Und die Ausgabe sieht doch gut aus!

Beispiel 5.4.8 Formatierte Ausgabe


>>>
0 0 0
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729

Auch vor dem Doppelpunkt kann noch etwas stehen. Im einfachsten Fall kann dort eine Positionsan-
gabe der Werte, die ausgegeben werden sollen, gemacht werden. (Nicht vergessen: man fängt bei 0 an
zu zählen!!)

93
KAPITEL 5. TEXTE 5.4. FORMATIERUNG VON ZEICHENKETTEN

Beispiel 5.4.9 Formatierte Ausgabe in umgekehrter Reihenfolge (Quelltext)


#!/usr/bin/python

formatMuster = "{2:>4} {1:>6} {0:>8}"

print()
for i in range(10):
print([Link](i, i**2, i**3))

Beispiel 5.4.10 Formatierte umgekehrte Ausgabe


>>>
0 0 0
1 1 1
8 4 2
27 9 3
64 16 4
125 25 5
216 36 6
343 49 7
512 64 8
729 81 9

Eine der oben erwähnten Verbesserungen der format-Methode ist, dass man Argumente an die For-
matierungsanweisung per Name übergeben kann. Das macht ein Programm besser lesbar (auch wenn
es für unser einfaches Beispiel noch nicht nötig ist), und deswegen steht der Quelltext hier ohne weitere
Erklärungen:

Beispiel 5.4.11 Formatierte Ausgabe mit benannten Parametern


#!/usr/bin/python
# -*- coding: utf-8 -*-

formatMuster = "{zahl:>4} {quadrat:>6} {kubus:>8}"

print()
for i in range(10):
print([Link](zahl=i, quadrat=i**2, kubus=i**3))

In der Spaltenformatierung kann der Bereich mit einem Füllzeichen ausgefüllt werden:

94
KAPITEL 5. TEXTE 5.4. FORMATIERUNG VON ZEICHENKETTEN

Beispiel 5.4.12 Formatierte Ausgabe mit Füllzeichen(Quelltext)


#!/usr/bin/python
# -*- coding: utf-8 -*-

formatKette = "Zahl: {zahl:.>4} Quadrat: {quadrat:_>6} Kubus: {kubus:*>8}"

print()
for i in range(11):
print([Link](zahl=i, quadrat=i**2, kubus=i**3))

Und so sieht es aus:

Beispiel 5.4.13 Formatierte Ausgabe mit Füllzeichen


Zahl: ...0 Quadrat: _____0 Kubus: *******0
Zahl: ...1 Quadrat: _____1 Kubus: *******1
Zahl: ...2 Quadrat: _____4 Kubus: *******8
Zahl: ...3 Quadrat: _____9 Kubus: ******27
Zahl: ...4 Quadrat: ____16 Kubus: ******64
Zahl: ...5 Quadrat: ____25 Kubus: *****125
Zahl: ...6 Quadrat: ____36 Kubus: *****216
Zahl: ...7 Quadrat: ____49 Kubus: *****343
Zahl: ...8 Quadrat: ____64 Kubus: *****512
Zahl: ...9 Quadrat: ____81 Kubus: *****729
Zahl: ..10 Quadrat: ___100 Kubus: ****1000

Außerdem kann jeder Spaltenformatierung noch ein Vortext vorangestellt werden:

Beispiel 5.4.14 Formatierte Ausgabe mit Vortext (Quelltext)


#!/usr/bin/python
# -*- coding: utf-8 -*-

formatKette = "Zahl: {zahl:>4} Quadrat: {quadrat:>6} Kubus: {kubus:>8}"

print()
for i in range(11):
print([Link](zahl=i, quadrat=i**2, kubus=i**3))

Und so sieht es aus:

95
KAPITEL 5. TEXTE 5.4. FORMATIERUNG VON ZEICHENKETTEN

Beispiel 5.4.15 Formatierte Ausgabe mit Vortext


Zahl: 0 Quadrat: 0 Kubus: 0
Zahl: 1 Quadrat: 1 Kubus: 1
Zahl: 2 Quadrat: 4 Kubus: 8
Zahl: 3 Quadrat: 9 Kubus: 27
Zahl: 4 Quadrat: 16 Kubus: 64
Zahl: 5 Quadrat: 25 Kubus: 125
Zahl: 6 Quadrat: 36 Kubus: 216
Zahl: 7 Quadrat: 49 Kubus: 343
Zahl: 8 Quadrat: 64 Kubus: 512
Zahl: 9 Quadrat: 81 Kubus: 729
Zahl: 10 Quadrat: 100 Kubus: 1000

Für Zahlen können verschiedene Darstellungen gewählt werden. Hier folgen ein paar Beispiele, die
aber anhand der untenstehenden Tabelle leicht verstanden werden!

Beispiel 5.4.16 Formatierte Ausgabe von Zahlen


>>> fs = "{:d} {:b} {:x}"
>>> print([Link](2,2,2))
2 10 2
>>> print([Link](18,18,18))
18 10010 12
>>> print([Link](31,31,31))
31 11111 1f

Zahlen werden mit dem Parameter d im Dezimalsystem, mit dem Parameter b im Dualsystem, mit
dem Parameter x im Hexadezimalsystem ausgegeben, wobei dann die abcdef“ in Kleinbuchstaben

geschrieben werden. Und hier kommt dann die ultimative Quizfrage: was bewirkt dann wohl der Para-
meter X?
In einer Tabelle folgen hier die wichtigsten Parameter für die format-Methode.

Tabelle 5.5. Parameter für die format-Methode


Ausrichtung
Zeichen Bedeutung / Erläuterung
> linksbündig
< rechtsbündig
ˆ zentriert
= rechtsbündig für Zahlen
Vorzeichen
+ bei allen Zahlen ein Vorzeichen
- nur bei negativen Zahlen ein Vorzeichen
# nur bei Zahlen: Zahlsystem(0b für Dualsys., 0x für Hexadezimalsys.)
Typ des Feldes
b schreibt eine Zahl im Dualsystem
c beliebige Zeichen (character)
d Ganzzahl (dezimal)
e Zahl in Exponential-Schreibweise
f Festkommazahl

96
KAPITEL 5. TEXTE 5.5. REGULÄRE AUSDRÜCKE

5.5. Reguläre Ausdrücke

Reguläre Ausdrücke, auf englisch regular expressions“, deswegen auch manchmal einfach mit re“
” ”
abgekürzt, sind Ausdrücke, die Regeln gehorchen! Reguläre Ausdrücke sind eigentlich eine Program-
miersprache in der Programmiersprache, oder wie ein Kollege formuliert hat: die einzig wichtige Pro-
grammiersprache sind Reguläre Ausdrücke. Angenommen, Du suchst in einem Text nach einem Herrn
Maier oder Herrn Meier oder Herrn Majer . . . also genau das, was täglich passiert: wie schreibt sich der
Herr bloß? Wenn Du jetzt nur suchen könntest nach einem Herrn, dessen Nachname mit einem M“

anfängt, worauf einer der Buchstaben a“ oder e“ folgt, darauf einer der Buchstaben i“, y“ oder j“,
” ” ” ” ”
und dessen Nachname mit er“ endet! Das kannst Du! Denn oben hast Du gerade eine Regel festgelegt,

nach der der Ausdruck Nachname“ aufgebaut sein soll. Versuchen wir es also:

Hier soll nur ein kurzer Anriss des Themas gemacht werden. Wer sich weiter informieren will, dem
sei das Buch von [Friedl] empfohlen.

5.5.1. Allgemeines zu regulären Ausdrücken

Reguläre Ausdrücke in Python beginnen sinnvollerweise mit einem r“, der Schreibweise für raw
” ”
strings“. Raw strings sind besondere Strings, die von Python so genommen werden, wie sie geschrieben
sind. In diesem Fall dient das dazu, dass Backslashes nicht als Steuerzeichen in Escape-Folgen interpre-
tiert werden. Der Raw string wird dann in Anführungsstriche eingeschlossen. Dieser raw string ist das
Muster, nach dem wir suchen, der reguläre Ausdruck.
Damit wir diesen Ausdruck aufbauen können, benötigen wir außer den Regeln, nach was wir suchen
die Vereinbarungen, was einzelne Zeichen in einem regulären Ausdruck für eine Bedeutung haben. Hier
folgen zuerst einmal die Regeln, die wir für unser Problem benötigen:

• ein beliebiges Zeichen des aktuellen Zeichensatzes bedeutet genau dieses Zeichen. M bedeutet M,
3 bedeutet 3.

• beliebige Zeichen in eckigen Klammern bedeuten, dass eines der Zeichen in der eckigen Klammer
genommen werden darf. [ae] bedeutet also, dass an dieser Stelle entweder ein a oder ein e stehen
darf.

Das reicht schon, um unser Problem zu lösen. Zuerst muss aber ein Modul eingebunden werden, das
sich mit regulären Ausdrücken befasst. Das geschieht mit der Anweisung import re“. Leider muss hier

vorgegriffen werden, denn Module werden erst in einem späteren Kapitel behandelt.

Beispiel 5.5.1 Reguläre Ausdrücke (Meier zum ersten)


>>> import re
>>> mText = "Unser Kandidat ist Herr Mayer.
Er ist nicht zu verwechseln mit Frau Meyer"
>>> [Link](r"M[ae][ijy]er",mText)
[’Mayer’, ’Meyer’]

Um die Meiers“ noch weiter zu bemühen: es gibt in manchen Gegenden auch noch den Famili-

ennamen Mair“. Als Regel formuliert heißt das, dass das e“ fakultativ ist. Dazu benötigen wir einen
8 ” ”
Quantor , der genau 0 oder 1 bestimmtes Zeichen bzw. 0 oder 1 Zeichen aus einer Auswahl erlaubt. Das
erledigt das Fragezeichen, das dem bestimmten Zeichen folgt.

8 siehe dazu die untenstehende Tabelle

97
KAPITEL 5. TEXTE 5.5. REGULÄRE AUSDRÜCKE

Beispiel 5.5.2 Reguläre Ausdrücke (Meier zum zweiten)


#!/usr/bin/python
import re

text = ’’’In diesem Text sind jede Menge "Maiers":


Herr Maier, Frau Meier, Herr Majer und Frau Mair’’’

gefunden = [Link](r’M[ae][ijy]e?r’, text)


for i in gefunden:
print([Link](0))

>>> Maier
Maier
Meier
Majer
Mair

Notwendig ist der Import des Moduls re

Tabelle 5.6. Reguläre Ausdrücke: Zeichen


Zeichen Bedeutung
Buchstabe, Zahl genau dieses Zeichen
[abc] eines der Zeichen in der eckigen Klammer
[a-z] eines der Zeichen zwischen a und z
. ein beliebiges Zeichen (außer Zeilenvorschub)
* 0 bis unendlich viele Wiederholungen des vorigen Zeichens / der vorigen RE
+ 1 bis unendlich viele Wiederholungen des vorigen Zeichens / der vorigen RE
? 0 bis 1 Wiederholungen des vorigen Zeichens / der vorigen RE
ˆ Anfang der Zeile
$ Ende der Zeile
\d [0-9]
\w [0-9a-zA-z ] (also ein Buchstabe, eine Ziffer oder ein Unterstrich)
\s Leerzeichen, Tabulator, Zeilenvorschub

Tabelle 5.7. Reguläre Ausdrücke: Methoden


Name Wirkung
[Link](Muster) gibt eine RE zurück
[Link](Muster, String) findet alle Vorkommen von Muster in String
[Link](Muster, Ersetzung, String) ersetzt alle Muster in String durch Ersetzung

5.5.2. Wortteile aus einem Text herausfiltern

Das Problem, das wir als erstes behandeln wollen, ist folgendes: aus einem beliebigen Text sollen alle
Wörter herausgefiltert werden, die mit einem h“ oder einem H“ anfangen. Die erste Lösung benutzt
” ”
fast die selben Python-Sprachmittel wie das vorige Beispiel:

98
KAPITEL 5. TEXTE 5.5. REGULÄRE AUSDRÜCKE

Beispiel 5.5.3 Wörter, die mit h“ oder H“anfangen


” ”
>>> text = ’Hier kommt ein lautes haha, weil Heiner und Harry heute lustig
sind.’
>>> muster2 = [Link](r"(H\w*|h\w*)")
>>> [Link](text)
[’Hier’, ’haha’, ’Heiner’, ’Harry’, ’heute’]

In der runden Klammer des regulären Ausdrucks stehen zwei Teile, die durch den senkrechten Strich
voneinander getrennt sind. Das bedeutet, dass alle Zeichenketten gefunden werden sollen, die entweder
auf den regulären Teilausdruck vor dem senkrechten Strich passen oder auf den danach. Das \w ist
eine Kurzschreibweise für [A-Za-z0-9 ], findet also einen beliebigen Buchstaben, eine Ziffer oder einen
Unterstrich. Die Methode findall macht genau das, was ihr Name sagt.
Als nächstes sollen aus einem Text bestimmte Teile herausgefiltert werden. Suchen wir also in einem
Text nach unanständigen Sachen.

Beispiel 5.5.4 Sex, Sex, Sex


#!/usr/bin/python
import re
text = ’An der Schule gibt es ein Jazz-Sextett\n
Ein Sextaner darf da nicht mitspielen\n
In Jazz-Stücken werden oft Sextakkorde verwendet’
saetze = [Link](’\n’)
unanstaendigeWoerter = list()

for satz in saetze:


wort = [Link](r"[-\s](Sex[a-z]*)",satz)
[Link]([Link](1))
print(unanstaendigeWoerter)

>>> [’Sextett’, ’Sextaner’, ’Sextakkorde’]

Der Text besteht aus 3 Zeilen, jede abgeschlossen durch einen Zeilenvorschub. Durch split wird der
Text in 3 Sätze aufgeteilt, die in einer Liste gespeichert werden. unanstaendeigeWoerter ist eine zu
Beginn leere Liste.
Mittels [Link]() wird nach einem regulären Ausdruck gesucht. Der reguläre Ausdruck setzt
sich so zusammen:

1. In eckigen Klammern steht eine Gruppe von Zeichen, aus denen genau eines ausgewählt werden
muss, in diesem Fall besteht die Liste aus dem Bindestrich und einem Leerzeichen. Die Variable
\s bezeichnet die Gruppe der white spaces“, also aller möglichen Leerzeichen.

2. Es folgt in runden Klammern die Zeichenkette Sex“.

3. Daran schließt sich wieder eine eckige Klammer an, in der die Menge aller Kleinbuchstaben steht.
Das bedeutet, dass von diesen Kleinbuchstaben wieder einer ausgewählt wird. Der Stern nach der
schließenden eckigen Klammer ist der Quantor, der besagt, dass null oder beliebig viele Klein-
buchstaben folgen dürfen.

4. Nach dem Stern steht die schließende runde Klammer. Dadurch wird das, was durch den in run-
den Klammern stehenden Teil des regulären Ausdrucks abgedeckt wird, als (Teil-)Gruppe eines
Fundes betrachtet.

5. Denn es soll ordentlich ausgegeben werden: das einleitende Leerzeichen oder der einleitende Bin-
destrich soll im Ergebnis nicht dargestellt werden, sondern nur das, was durch den in runden

99
KAPITEL 5. TEXTE 5.5. REGULÄRE AUSDRÜCKE

Klammern abgedeckten Teil gefunden wird. Darum wird an die Liste der unanständigen Wörter
nur der Teil der 1. Gruppe angehängt.

OK. Das Programm hat gefunden, was es sollte. Syntaktisch ist es korrekt, aber naja, das ist nicht das,
was wir finden wollten.

5.5.3. gpx-Datei eines Fitness-Trackers


Im nächsten Beispiel geht es darum, aus einer Datei, die von einem Fitness-Tracker erstellt wurde und
die eine schöne Rundfahrt mit dem Fahrrad enthält, die Zeilen, die die Herzfrequenz enthalten, zu
löschen, denn die Dateien sollen auf einem Blog veröffentlicht werden.9 Und so persönliche Daten
gehören nicht auf eine Internet-Seite. Das ist kein größeres Problem, denn es handelt sich um eine .gpx-
Datei.10 Das ganze wird hier einfach mittels eines regulären Ausdrucks gelöst, obwohl das auch über
einen XML-Parser ginge. (Und wenn ich mal Lust habe, schreibe ich auch noch ein Kapitel über .xml-
Dateien.)

Beispiel 5.5.5 Fitness ohne Herz


import re
...
pulsZeileRE = [Link](’’’ˆ(\s)*<gpxtpx:hr>\d{1,3}</gpxtpx:hr>(\s)*$’’’)
aDat = ...
with open(dateiname, ’r’) as eDat:
for eineZeile in eDat:
if [Link](eineZeile):
pass
else:
[Link](eineZeile)
[Link]()

Die ersten beiden Zeilen sollten jetzt verständlich sein; der Rest arbeitet mit einer Eingabe- und einer
Ausgabedatei. Das Original bleibt, wie es ist, die Ausgabedatei enthält nur Zeilen, in denen der reguläre
Ausdruck nicht gefunden wurde. Nach dem weiter hinten folgenden Kapitel über Dateien kannst Du
das Drumherum, das, was oben durch die 3 Pünktchen gekennzeichnet ist, leicht selbst schreiben.
Für eine einzelne Datei lohnt sich das Programm ja fast nicht, aber das Programm kann natürlich
weiter aufgebohrt werden, so dass es auf einen Schlag alle .gpx-Dateien eines Verzeichnisses bearbeitet.
Und dann lohnt es sich.

5.5.4. Beispiel für Zahlen


Im nächsten Beispiel soll eine Zahleingabe auf korrekte Schreibweise überprüft werden. Korrekt soll
in unserem Fall heißen, dass eine Zahl eine Ganzzahl wie 17 oder eine Dezimalzahl mit maximal 2
Nachkommastellen sein soll. Ferner soll erlaubt sein, dass vor der Zahl ein Plus- oder ein Minuszeichen
stehen darf. Nicht erlaubt ist das, was Mathematiker (vor allem aus dem englischsprachigen Raum)
gerne machen, nämlich eine Dezimalzahl zwischen 0 und 1 ohne die 0 vor dem Komma zu schreiben,
also zum Beispiel .75, so wie das ein Taschenrechner (oder auch Python) akzeptiert. Dazu ist zuerst die
Zahl, die man eingibt, in einen Text umzuwandeln, denn reguläre Ausdrücke untersuchen Texte. Der
reguläre Ausdruck wird Stück für Stück aufgebaut.
Für nicht triviale Suchmuster ist es gute Sitte, das Suchmuster als ein Objekt der Klasse regulärer

Ausdruck“ zu speichern. 11
korrekteZahl = [Link](”’[0-9]+”’) akzeptiert eine Ganzzahl, die aus den Ziffern 0 bis 9 besteht
([0-9]), von denen mindestens eine existieren muss (+).
9 Danke an Lisa, die genau das macht, und die natürlich auch findet, dass Herzensangelegenheiten Privatsache sind.
10 dieja eigentlich nur eine .xml-Datei ist
11 Objekte werden später eingeführt im Kapitel Klassen

100
KAPITEL 5. TEXTE 5.5. REGULÄRE AUSDRÜCKE

korrekteZahl = [Link](”’[0-9]+\.”’) akzeptiert eine Zahl, die aus den Ziffern 0 bis 9 besteht und
durch einen Dezimalpunkt abgeschlossen wird. Der Dezimalpunkt muss durch einen Backslash mas-
kiert werden.
korrekteZahl = [Link](”’([-+]?[0-9]+\.[0-9]{0,2})”’) akzeptiert eine Dezimalzahl, die aus den Zif-
fern 0 bis 9 besteht und nach dem Dezimalpunkt wenigstens 0 und höchstens zwei weitere Ziffern aus
der Menge 0 bis 9 enthält ([0-9]{0,2}). Aber das reicht noch nicht für eine gute Prüfung, denn es ist
noch erlaubt, dass ein Dezimalpunkt steht ohne Dezimalziffern danach.
Zusätzlich wird hier noch festgelegt, dass eine Zahl eine ganze Zeile ausfüllen muss. Das ˆ bedeutet,
dass re am Beginn der Zeile anfängt zu arbeiten, das $, dass re am Ende der Zeile aufhört.

korrekteZahl = [Link](r’’’(ˆ[-+]?[0-9]+(\.[0-9]{1,2})?$)’’’)

Der zweite Teil der Zahl, nämlich das, was hinter dem Dezimalpunkt stehen darf, ist hier durch runde
Klammern geblockt worden, so dass dieser Teil als ein Ausdruck aufgefasst wird ((\.[0-9]{0,2})?).
Für diesen Block wird dann wieder ein Quantor benutzt, nämlich das ?, das die Bedeutung hat: ent-
weder kein Mal oder ein Mal. In diesem Fall also darf eine mit einem Punkt beginnende und durch 2
Ziffern beendete Zeichenfolge kein Mal oder ein Mal auftreten.

5.5.5. Ein komplizierterer Text

Dri Chinisin mit dim Kintribiss

—Kinderlied

Ein klassisches und deswegen ganz wichtiges Beispiel (hör Dich mal im Kindergarten Deines Wohn-
ortes um!) ist der philosophische Text

Drei Chinesen mit dem Kontrabass


saßen auf der Strasse und erzählten sich etwas
kam ein Polizist ”ei was ist denn das?”
”Drei Chinesen mit dem Kontrabass”

in dem alle (unterschiedlichen) Vokale und Diphtonge durch ein und denselben Vokal ersetzt werden
sollen. Dieses uralte Menschheitsproblem wird locker gelöst mit dem Programm

Beispiel 5.5.6 Drei Chinesen . . . (reguläre Ausdrücke)


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4 # importiere das Modul "Reguläre Ausdrücke"
5 import re
6

7 vokalNeu = input(’Welcher Vokal soll es denn sein? ’)


8

9 text = ’’’Drei Chinesen mit dem Kontrabass


10 saßen auf der Strasse und erzählten sich etwas
11 kam ein Polizist "ei was ist denn das"
12 "Drei Chinesen mit dem Kontrabass" ’’’
13

14 # regulären Ausdruck aufbauen, das ist ein "raw string"


15 suchString = [Link](r"""(ei|au|ä|a|e|i|o|u)""")
16 neutext = [Link](vokalNeu,text)
17 print(neutext)
18

101
KAPITEL 5. TEXTE 5.5. REGULÄRE AUSDRÜCKE

Beachte dabei, dass die Diphtonge vor den Vokalen stehen müssen. Wenn die Diphtonge erst danach
stünden, würde etwa in ei“ zuerst das e“, dann das i“ ersetzt, wodurch aus dem ei“ ein oo“ würde
” ” ” ” ”
(wenn man als Ersetzungs-Vokal das o“ angibt).

Und das kommt dabei raus, wenn man als Ersetzungs-Vokal das o“ angibt:

Beispiel 5.5.7 Dro Chonoson


Dro Chonoson mot dom Kontroboss
soßon of dor Strosso ond orzohlton soch otwos
kom on Polozost "o wos ost donn dos"
"Dro Chonoson mot dom Kontroboss"

Mit [Link] wird ein regulärer Ausdruck aufgebaut, der hier alternativ alle Vokale und Diphtonge
enthält. Und der Rest ist wieder klar. (Hoffentlich!)

Eine Suche per [Link] gibt ein Match-Object zurück. Jetzt kann es vorkommen, dass man genau
mit diesem Objekt weiter arbeiten muss. Was nun? Hier kommt die Hilfe zur Selbsthilfe: man weist das
Ergebnis des match-Aufrufs einer Variablen (z.B. der Variablen ergMatch) zu und ruft die Hilfe für
dieses Objekt mit help(ergMatch) auf! Dann sieht man unter anderem, dass das Objekt ergMatch ein
Attribut string hat. Das kann man ja mal ausdrucken!

5.5.6. Eine etwas sinnvollere Anwendung: Wörter mit Doppelbuchstaben finden

Du sollst also in einem Text alle Wörter finden, die einen Doppelbuchstaben enthalten; Beispiele dafür
sind etwa See“, Meer“ und Leere“, die alle zwei aufeinanderfolgende e“ enthalten, oder Wall“,
” ” ” ” ”
Qualle“ und Welle“, die alle zwei aufeinanderfolgende l“ enthalten. Wie sieht die Regel aus?12
” ” ”
Die Regel sagt uns zuerst einmal, dass wir Wörter finden müssen. Wörter sind Zeichenketten, die von
Leerzeichen begrenzt werden. Auf sie passt also der reguläre Ausdruck \w*. Innerhalb dieses Wortes
soll also jetzt ein Buchstabe gefunden werden, der von dem selben Buchstaben gefolgt wird. Das ge-
schieht durch eine Gruppierung, auf die dann Bezug genommen wird. Eine Gruppierung wird durch
Einklammern erzeugt: (\w) ist eine Gruppe, die genau aus einem Element der Klasse \w besteht, also
aus einem Buchstaben, einer Ziffer oder einem Unterstrich.13 Diese Gruppe soll sich also jetzt wieder-
holen. Da es sich hier um die erste (und bis jetzt einzige) Gruppe handelt, beziehe ich mich auf diese
Gruppe durch den regulären Ausdruck \1“. Damit habe ich meine Regel beschrieben: gesucht sind

Wörter, die mit beliebig vielen Buchstaben beginnen, auf die ein Buchstabe folgt, der sofort noch einmal
folgt, gefolgt von beliebig vielen Buchstaben: \w*(\w)\1\w*“.

Der reguläre Ausdruck wird jetzt kompiliert, wodurch ein re-Objekt entsteht. Mit der Methode
finditer wird jetzt iterativ der Text durchsucht. Die eventuellen Ergebnisse stehen jetzt in dem Attri-
but group der einzelnen Objekte. Das Programm sieht so aus:

12 Ich gehe davon aus, dass der Text vorläufig in einer Variablen steht; die Bearbeitung von Text, der in einer Textdatei enthalten
ist, kann später jeder für sich programmieren, wenn der Zugriff auf Dateien bekannt ist.
13 Seien wir also mal kurzfristig großzügig (oder vielleicht schlampig?), und erlauben auch Ziffern in Wörtern, wodurch auch in

Ludwig 11. das Wort“ 11“ gefunden würde


” ”

102
KAPITEL 5. TEXTE 5.6. AUFGABEN ZU TEXTEN (STRINGS)

Beispiel 5.5.8 Doppelbuchstaben finden


#!/usr/bin/python
import re

text = ’’’In diesem Text sind mindestens zwee Wörter mit Doppelbuchstaben.
Findet er auch Meereswelle?’’’
wmdb = [Link](r"""\w*(\w)\1\w*""")
gefunden = [Link](text)
for i in gefunden:
print([Link](0))

>>> zwee
Doppelbuchstaben
Meereswelle

5.6. Aufgaben zu Texten (Strings)


1. Lass Dir mit

help(str)

den Hilfetext zu Strings anzeigen; probiere einige der dort angegebenen Methoden von Strings
aus. Notiere Dir Aktionen, die Dir interessant für Deien zukünftige Arbeit erscheinen, und spei-
chere die dazugehörigen Programmschnipsel in Python-Dateien.

2. a) Benutze die Methode translate, um ein Programm zur Caesar-Verschlüsselung zu schrei-


ben.
b) Entsprechend natürlich ein Programm zur Entschlüsselung eines mittels der Caesar-Verschlüs-
selung verschlüsselten Textes.

3. a) Zerlege einen beliebigen Text in eine Liste von Wörtern.


b) Sortiere diese Wörter alphabetisch.
c) Nach dem Sortieren erhältst Du (mit dem obigen Satz) die Liste:

[’Liste’, ’Text’, ’Wörtern’, ’Zerlege’, ’beliebigen’, ’eine’,


’einen’, ’in’, ’von’]

Diese Sortierung gefällt Dir nicht? Mir auch nicht. Beschreibe Dein Missfallen, überlege Dir,
wie Du diese Wörter gerne sortiert hättest und schreibe ein Programm, das es besser macht.

4. Es stehen am Fahrrad-Rikscha-Startplatz:
a) 30 Fahrrad-Rikschas mit je 2 Sitzplätzen für Passagiere
b) 18 gut durchtrainierte Fahrer
c) 57 potentielle Fahrgäste
Ausgegeben werden soll etwa:
• Wir haben ... Rikschas, können also theoretisch ... Personen transportieren.
• Da im Moment nur ... Fahrer zur Verfügung stehen, können ... Fahrgäste mitfahren und ...
Fahrgäste müssen in ca. 1 Stunde wiederkommen, wenn sie dann noch fahren wollen.

5. Ein Programm soll aus dem Buchstaben x ein Herz malen, etwa so:

103
KAPITEL 5. TEXTE 5.6. AUFGABEN ZU TEXTEN (STRINGS)

Beispiel 5.6.1 Herz aus x


xx xx
x x x
x x
x x
x

Es ist sinnvoll, sich vorher ein Muster auf ein kariertes Papier zu malen!
Jetzt lass jeweils ein neues Programm die anderen Symbole der Spielkartenfarben Kreuz, Pik und
Karo malen. (Es muss nicht jedesmal mit einem x“ sein.)

104
6. Strukturierte Daten
6.1. Überblick
An strukturierten Daten unterscheidet man:

1. Listen
2. Dictionaries
3. Tupel
4. Mengen

Der Unterschied zu einfachen Daten ist einfach: bei einfachen Daten hat eine Variable einen Namen
und einen einzelnen Wert als Inhalt. Dieser Wert kann eine Zahl oder ein Text sein (und später werden
wir sehen: noch mehr). Bei strukturierten Daten ist der Inhalt einer Variablen eine Menge von Werten.
Eine Liste etwa kann eine Liste von Zahlen, eine Liste von Vornamen, eine Liste von Pizza-Angeboten
Deines Lieblingsitalieners usw. sein. Ein Dictionary kann ein einsprachiges Wörterbuch sein, ein zwei-
sprachiges Wörterbuch, ein Telefonbuch usw.

6.2. Listen

Reg: [reading prepared statement]


”We, the People’s Front of Judea, brackets, official, end brackets,
do hereby convey our sincere fraternal and sisterly greetings to you, Brian”

—Monty Python 1

6.2.1. Definition von Listen und Listenelemente


Die einfachste Datenstruktur sind Listen. Listen sind geordnete Sammlungen von . . . irgendwas. Das
kann sogar wild durcheinander gehen: Zahlen, Texte, sogar wieder andere Listen. Das wichtigste daran
ist, dass Listen-Elemente durchnumeriert werden. Die Zahl, die die Hausnummern“ zählt, heißt Index

W ICHTIG

Beachte dabei: man fängt bei 0 an zu zählen!

Listen werden in eckige Klammern geschrieben, Listen-Elemente durch Kommata voneinander ge-
trennt. Wenn man ein einzelnes Element einer Liste bearbeiten (oder anzeigen oder ...) möchte, geschieht
das, indem man den Listennamen, gefolgt von der Hausnummer“ in eckigen Klammern, angibt.

W ICHTIG

Beachte dabei: Ein negativer Wert für den Index bedeutet, dass man von hinten
anfängt zu zählen.

1 in: Life of Brian

105
KAPITEL 6. STRUKTURIERTE DATEN 6.2. LISTEN

6.2.2. Erzeugung von Listen


[Link]. Durch Angabe der Elemente

Die einfachste Art, eine Liste zu erzeugen, ist durch die Angabe der Elemente der Liste. Dabei weisen
wir gleich einer Variablen diese Liste zu:

Beispiel 6.2.1 Eine Liste erzeugen


zahlenListe1 = [1,2,3,4,5,9,7]

[Link]. Als Objekt der Klasse list

Das kann man auch erledigen, indem man die Liste als ein Objekt der Klasse list“ erstellt und somit

den Konstruktor der Klasse aufruft.2

Beispiel 6.2.2 Eine Liste als Objekt erzeugen


zahlenListe2 = list([1,2,3,4,5,9,7])

[Link]. Mittels range

Bei Einführung von Schleifen lernst Du die Funktion range kennen. Diese Funktion liefert einen Bereich
von Zahlen. Dadurch ist sie auch gut geeignet, um Zahlenlisten herzustellen:

Beispiel 6.2.3 Eine Liste mit den ersten 20 natürlichen Zahlen erzeugen
zahlenListe3 = list(range(20))

Beispiel 6.2.4 Eine Liste von (überleg mal selber!!) Zahlen


zahlenListe3 = list(range(20,50,3))
zahlenListe3
>>> [20, 23, 26, 29, 32, 35, 38, 41, 44, 47]

A NMERKUNG
Hier ist ein Unterschied zwischen Python 2.x und Python 3.x! In Python 2.x hat
der Befehl range(20,50,3) bereits die oben angezeigte Liste erzeugt. In Python
3.x wird nur ein Generator für diese Liste erzeugt, die einzelnen Listenelemente
werden bei Bedarf erzeugt. Wenn man also in Python 3.x diese Liste erhalten
will, funktioniert das wie oben beschrieben durch list(range(20,50,3)).

2 DerSatz ist im Moment noch schwer zu verstehen; wenn Du weiter hinten in die Objektorientierte Programmierung eingestie-
gen bist, wird Dir der Sinn dieses Satzes hoffentlich klar.

106
KAPITEL 6. STRUKTURIERTE DATEN 6.2. LISTEN

A NMERKUNG
Wenn man jetzt auf die Idee kommt, dass man für eine Tabelle der x-Werte
(gewünscht ist dies für -5 <= x <= 5) einer Funktion in der Mathematik die-
se Tabelle durch x Werte = range(-5,6,0.1) erstellen kann, wird eine Fehler-
meldung bekommen: range erlaubt nur ganze Zahlen als Parameter. Aber das
gewünschte Ergebnis erhält man, wenn man das nächste Kapitel durchgelesen
hat.

[Link]. Mit Hilfe der list comprehension


(siehe auch weiter unten bei list comprehension)

Beispiel 6.2.5 Liste über list comprehension


>>> liste = [i*2 for i in range(3)]
>>> liste
[0, 2, 4]
>>>

A NMERKUNG

Klar jetzt, wie man die Wertetabelle aus dem vorigen Kapitel erzeugt? So:
defBereich = [x/10 for x in range(-50,51)]

[Link]. Mittels input

Beispiel 6.2.6 Liste über input(1. Version)


>>> l = list(input(’Liste: ’))
Liste: abcdef
>>> l
[’a’, ’b’, ’c’, ’d’, ’e’, ’f’]

oder so

Beispiel 6.2.7 Liste über input(2. Version)


>>> l = list(input(’Liste: ’).split())
Liste: 1 2 3 4
>>> l
[’1’, ’2’, ’3’, ’4’]

6.2.3. Beispiele von Listen


Hier folgen zwei Beispiele von Listen. Zuerst einmal eine typische Liste, nämlich eine Einkaufsliste:

107
KAPITEL 6. STRUKTURIERTE DATEN 6.2. LISTEN

Beispiel 6.2.8 Eine Einkaufsliste


einkaufsListe = [’Brot’, ’Butter’, ’Milch’, ’Salz’, ’Senf’]

Diese Liste kann man sich so vorstellen:

Tabelle 6.1. Liste mit Hausnummern und Einträgen


Hausnummer“ 0 1 2 3 4

Wert Brot Butter Milch Salz Senf

Listenelemente kann man einzeln ansprechen. Hier wird das erste Element der obigen Liste ausgege-
ben (denke daran: Python fängt bei 0 an zu zählen):

Beispiel 6.2.9 Listenelemente


>>> einkaufsListe[1]
’Butter’
>>> print(einkaufsListe[0])
Brot

Und dann eine Liste mit ganz verschiedenartigen Elementen:

Beispiel 6.2.10 Eine einfache Liste


meineListe = [’Martin’, 43, ’Mathematik’]

Diese Liste hat drei Elemente, zwei Texte und eine Zahl. Und auch hier kann man die Listenelemente
einzeln aufrufen:

Beispiel 6.2.11 Listenelemente


>>> meineListe[1]
43
>>> print(meineListe[0])
Martin

6.2.4. Operationen auf Listen


Mit Listen kann man zum Glück noch viel mehr anstellen. Man kann Listen verketten. Das geschieht
durch das Plus-Zeichen +

Beispiel 6.2.12 Verkettung von Listen


>>> meineListe = [’Martin’, 43, ’Mathematik’]
>>> kurzeListe = [’Karl’,’Egon’,’Uwe’,’Sepp’]
>>> meineListe + kurzeListe
[’Martin’, 43, ’Mathematik’,’Karl’,’Egon’,’Uwe’,’Sepp’]

Man kann auch eine Liste mit einer Zahl multiplizieren:

108
KAPITEL 6. STRUKTURIERTE DATEN 6.2. LISTEN

Beispiel 6.2.13 Rechnen mit Listen


>>> meineListe * 2
[’Martin’, 43, ’Mathematik’, ’Martin’, 43, ’Mathematik’]

Man kann die Länge einer Liste feststellen:

Beispiel 6.2.14 Länge einer Liste


>>> print(len(meineListe))
3

Immer wieder ist es aber auch wichtig, zu wissen, an welcher Stelle ein bestimmtes Element in einer
Liste steht. Dazu dient die Operation index gemacht.

Beispiel 6.2.15 Position eines Listenelements


>>> print([Link](’Mathematik’))
2

[Link]. Wie funktioniert das Enthaltensein“?



Wie also ist so eine Funktion programmiert? Das ist ein Standard-Problem der Programmierung, und
die Lösung (eine der Lösungen) heißt binäre Suche“.

Binäre Suche funktioniert bei geordneten Dingen, also insbesondere bei geordneten Listen. Das kann
eine Liste von Zahlen sein, die der Größe nach geordnet sind oder eine Liste von Begriffen, die ebenfalls
der Größe nach geordnet sind.

Abbildung 6.1. Struktogramm binäre Suche

Wenn weiter hinten bei der Zähl-Schleifen“ ein weiteres Element von Python zur Verfügung steht,

kann man den Zusammenhang zwischen der Länge einer Liste, ihren Elementen und den dazugehörigen
Hausnummern“ besser verstehen.

[Link]. Erzeugung einer Liste durch eine Filterfunktion

In Python gibt es eine eingebaute Funktion filter, die aus einer Liste mithilfe einer anderen Funktion,
die jedes Element einer Liste bearbeitet, eine gefilterte Liste erzeugt. Als Beispiel sollen hier einmal eine
Liste der Quadratzahlen kleiner als 650 erzeugt werden. Dazu wird eine Funktion geschrieben, die auf
Quadratzahl-sein“ überprüft.

109
KAPITEL 6. STRUKTURIERTE DATEN 6.2. LISTEN

Beispiel 6.2.16 Filtern von Listen


from math import sqrt
def qZahl(z):
if sqrt(z) == int(sqrt(z)):
return z
else:
return ’’
qs = filter(qZahl,range(650))
for z in qs:
print(z,end=’, ’)
1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289,
324, 361, 400, 441, 484, 529, 576, 625,

6.2.5. Veränderung von Listen


[Link]. Ein Element anhängen
Etwas an eine bestehende Liste anzuhängen ist auch nicht schwer (aber es sieht prinzipiell anders aus
als das Feststellen der Länge. Mehr dazu bei Klassen):

Beispiel 6.2.17 Verlängerung einer Liste


>>> [Link](’Lehrer’)
>>> meineListe
[’Martin’, 43, ’Mathematik’, ’Lehrer’]

Eine andere Möglichkeit, etwas an eine Liste anzuhängen, ist, zwei Listen zu einer zu vereinigen. Das
sieht so aus:

Beispiel 6.2.18 Verlängerung einer Liste durch Zusammenkopieren


>>> bierListe = []
>>> bier = ’Weizen’
>>> bierListe += [bier]
>>> bier = ’Pils’
>>> bierListe += [bier]
>>> print(bierListe)
[’Weizen’, ’Pils’]

Man kann Listen auch verlängern, indem man einen Shortcut-Operator benutzt. Aber Vorsicht: das
funktioniert nicht so, wie man es sich vielleicht naiv vorstellt.

Beispiel 6.2.19 Verlängerung einer Liste durch Shortcut (falsch)


>>> bierListe = [’Weizen’,’Pils’]
>>> bier += ’Kölsch’
>>> bierListe += ’Kölsch’
>>> bierListe
[’Weizen’, ’Pils’, ’K’, ’ö’, ’l’, ’s’, ’c’, ’h’]

Python fasst den Text Kölsch als eine Liste von Buchstaben auf, die einzeln angehängt werden. Richtig
wird es so:

110
KAPITEL 6. STRUKTURIERTE DATEN 6.2. LISTEN

Beispiel 6.2.20 Verlängerung einer Liste durch Shortcut (richtig)


>>> bierListe = [’Weizen’,’Pils’]
>>> bier += ’Kölsch’
>>> bierListe += [’Kölsch’]
>>> bierListe
[’Weizen’, ’Pils’, ’Kölsch’]

[Link]. Ein gern gemachter Fehler

Wenn l eine Liste ist und man eine Methode von Listen auf l anwendet, wird l verändert, die Methode
gibt eine Erfolgs- oder Mißerfolgsmeldung zurück. Der Satz hört sich kompliziert an. Darum gibt es
gleich ein Beispiel:

Beispiel 6.2.21 Fehler bei Methoden von Listen


1

2 >>> l = [1,2,3,4,5]
3 >>> print(l)
4 [1, 2, 3, 4, 5]
5 >>> [Link](6)
6 >>> print(l)
7 [1, 2, 3, 4, 5, 6]
8

9 >>> l2 = l
10 >>> print(l)
11 [1, 2, 3, 4, 5, 6]
12 >>> print(l2)
13 [1, 2, 3, 4, 5, 6]
14

15 >>> l2 = [Link](7)
16 >>> print(l)
17 [1, 2, 3, 4, 5, 6, 7]
18 >>> print(l2)
19 None
20

Hast Du gesehen, was passiert? Der Befehl in Zeile 13 hängt die Zahl 7 an die bestehende Liste l an.
Die Erfolgsmeldung dieser Operation wird der Variablen l2 zugewiesen.

[Link]. Mehrere Elemente anhängen

Während man mit append nur ein einzelnes Element an eine Liste anhängen kann, ist es möglich, mit
extend mehr anzuhängen. Genau gesagt: an eine Liste kann mit extend alles Mögliche angehängt
werden, sofern es iterierbar ist. Dieser Satz ist aus 2 Gründen gemein:

1. erst im nächsten Kapitel, dem über Strukturierte Programmierung“, taucht der Begriff Iteration“
” ”
auf

2. da taucht ganz heimlich eine Art Rekursion auf: iterierbar bedeutet, dass etwas strukturiert ist,
und dass das etwas abzählbar ist, in der Form, dass man sagen kann, welches das erste Element
ist, und was dann das darauffolgende usw.
Also was? Na klar, eine Liste!!! Auf eine Liste trifft genau das zu, was im vorigen Satz steht. Also
kann ich eine Liste mit extend um eine Liste erweitern.

Hier kommt das Beispiel dazu:

111
KAPITEL 6. STRUKTURIERTE DATEN 6.2. LISTEN

Beispiel 6.2.22 Verlängerung einer Liste um eine Liste


>>> liste1 = [’a’,’b’,’c’]
>>> print(liste1)
[’a’,’b’,’c’]
>>> [Link]([’x’,’y’,’z’])
>>> print(liste1)
[’a’,’b’,’c’,’x’,’y’,’z’]

Wenn ich hingegen mit append eine Liste anhänge, wird die Liste als ein Element genommen und
angehängt.

Beispiel 6.2.23 Verlängerung einer Liste um eine Liste geht schief


>>> liste1 = [’a’,’b’,’c’]
>>> print(liste1)
[’a’,’b’,’c’]
>>> [Link]([’x’,’y’,’z’])
>>> print(liste1)
[’a’,’b’,’c’,[’x’,’y’,’z’]]

Und um nochmals vorzugreifen: das funktioniert auch mit einem XrefId[?Tupel?].

Beispiel 6.2.24 Verlängerung einer Liste um ein Tupel


>>> liste1 = [’a’,’b’,’c’]
>>> print(liste1)
[’a’,’b’,’c’]
>>> [Link]((’x’,’y’,’z’))
>>> print(liste1)
[’a’,’b’,’c’,’x’,’y’,’z’]

Es ist zwar nicht möglich, an eine Liste, die 4 Elemente enthält (also die Elemente 0 bis 3) ein weiteres
mit liste[4] = ’bla blub’ anzuhängen. Aber es gibt eine Möglichkeit, die so ähnlich aussieht:

Beispiel 6.2.25 Elemente an eine Liste anhängen


1

2 >>> vn = [’Martin’, ’Hannah’, ’Theresa’]


3 >>> vn += [’Heiko’]
4 >>> vn
5 [’Martin’, ’Hannah’, ’Theresa’, ’Heiko’]
6 >>> vn[len(vn):] = [’Anne’, ’Maria’]
7 >>> vn
8 [’Martin’, ’Hannah’, ’Theresa’, ’Heiko’, ’Anne’, ’Maria’]
9 >>> [Link](’Lorenz’)
10 >>> vn
11 [’Martin’, ’Hannah’, ’Theresa’, ’Heiko’, ’Anne’, ’Maria’, ’Lorenz’]
12

Die Verlängerung in Zeile 6 ist gemeint: hier wird gesagt, dass die Listenelemente ab dem Element
mit der Hausnummer Länge der Liste“ die Namen Anne“ und Maria“ sein sollen.
” ” ”

112
KAPITEL 6. STRUKTURIERTE DATEN 6.2. LISTEN

Für das Erweitern einer Liste um eine Liste gibt es allerdings noch eine Kurzschreibweise“; aber

vielleicht wärst Du da selber drauf gekommen, jetzt, nachdem Du Dich schon ein bißchen mit Python
beschäftigt hast:

Beispiel 6.2.26 Verlängerung einer Liste um eine Liste (Kurzform)


>>> liste1 = [’a’,’b’,’c’]
>>> print(liste1)
[’a’,’b’,’c’]
>>> liste1 += [’x’,’y’,’z’]
>>> print(liste1)
[’a’,’b’,’c’,’x’,’y’,’z’]

Python verhält sich so, wie man es von einer vernünftigen Programmiersprache erwartet.

[Link]. Ein Element einfügen

Hier geht es darum, an einer bestimmten Stelle ein Element einzufügen, also nicht mehr nur einfach an
das Ende der Liste etwas hinzuzufügen. Das Beispiel erklärt sich selbst (finde ich):

Beispiel 6.2.27 Einfügen eines Elements in eine Liste


>>> liste2 = [1,2,4]
>>> liste2
[1, 2, 4]
>>> [Link](2,’DREI’)
>>> liste2
[1, 2, ’DREI’, 4]

[Link]. Ein bestimmtes Element entfernen (nicht so schön)

Entsprechend kann man auch etwas aus einer Liste entfernen, vorausgesetzt, man weiß, wo das gesuch-
te Element in der Liste steht.

Beispiel 6.2.28 Löschen eines Elements aus einer Liste


>>> meineListe
[’Martin’, 43, ’Mathematik’, ’Lehrer’]
>>> del meineListe[1]
>>> meineListe
[’Martin’, ’Mathematik’, ’Lehrer’]

[Link]. Ein bestimmtes Element bearbeiten und entfernen

Im vorigen Abschnitt habe ich die Art des Entfernens eines Elementes aus einer Liste als nicht so schön
bezeichnet. Das versteht man, wenn man weiter fortgeschritten ist und sich mit Objektorientierung be-
fasst hat. Schöner ist es, wenn man eine Methode der Klasse Listen“ benutzt. Die Methode pop()

holt ein einzelnes Element aus der Liste und löscht es darin. Wenn in der Klammer kein Parameter-
wert angegeben ist, also mit [Link]() wird automatisch das letzte Element entfernt. Will man
etwa das nullte Element (denke daran: Python fängt bei 0 an zu zählen) entfernen, geschieht das mit
[Link](0).

113
KAPITEL 6. STRUKTURIERTE DATEN 6.2. LISTEN

[Link]. Eine Teilmenge der Liste bearbeiten

Oben bei Zeichenketten als Feld haben wir schon den Begriff slicing“ kennengelernt. Das funktioniert

natürlich auch bei Listen.

Beispiel 6.2.29 Teile einer Liste


>>> langeListe = [’Martin’, 43, ’Mathematik’, ’Lehrer’,
’Banane’, 1954, ’Senf’]
>>> langeListe[2:5]
[’Mathematik’, ’Lehrer’, ’Banane’]

Und etwas, was oft sehr hilfreich ist:

Beispiel 6.2.30 Umkehrung einer Liste


>>> [Link]()
>>> print(langeListe)
[’Senf’, 1954, ’Banane’, ’Lehrer’, ’Mathematik’, 43, ’Martin’]

Man kann eine Liste umkehren und anzeigen und dabei die Liste aber im Originalzustand lassen;
man kann aber auch die Liste umkehren und umgekehrt speichern.

Beispiel 6.2.31 Umkehrung (2 Arten)


>>> l = [1,2,3,4,5]
# hier wird die Liste umgekehrt angezeigt, aber belassen
>>> l[::-1]
[5, 4, 3, 2, 1]
>>> print(l)
[1, 2, 3, 4, 5]
# hier wird die Liste umgekehrt und geändert
>>> [Link]()
>>> print(l)
[5, 4, 3, 2, 1]

Von Texten her bekannt ist schon das Slicing. Das funktioniert auch bei Listen. Hier wird mit 3 Para-
metern gearbeitet, um aus der Liste der ersten 10 natürlichen Zahlen die geraden Zahlen herauszufiltern.

Beispiel 6.2.32 Eine Liste slicen


>>> zahlenListe = [0,1,2,3,4,5,6,7,8,9]
>>> print(zahlenListe[0:9:2])
[0, 2, 4, 6, 8]

[Link]. Eine Liste sortieren

Das ist wahrscheinlich eine der häufigsten Aufgaben, die bei einer Liste entstehen: sie soll sortiert wer-
den. Zum Glück hat Python für Listen die Methode sort. Sie sortiert die Elemente nach einer lexikali-
schen Ordnung:

114
KAPITEL 6. STRUKTURIERTE DATEN 6.2. LISTEN

Beispiel 6.2.33 Sortierung einer Liste


>>> liste2 = [’x’,’B’,’S’,’P’,’A’,’n’,’m’]
>>> [Link]()
>>> liste2
[’A’, ’B’, ’P’, ’S’, ’m’, ’n’, ’x’]

Dabei heißt lexikalisch“, dass im Sinne der ASCII-Ordnung sortiert wird, und da kommen alle Groß-

buchstaben AB..XYZ vor den Kleinbuchstaben ab..xyz. Beachte dabei: die Liste wird an Ort und Stelle
sortiert, das heißt, dass die Liste nach dem Sortieren nur noch in der sortierten Form existiert.
Da eine Liste beim Sortieren an Ort und Stelle verändert wird, ist es nicht ganz trivial zu überprüfen,
ob eine Liste sortiert ist. Durch die Funktion sorted wird eine neue Liste erzeugt, in die die Elemente
der gegebenen Liste in sortierter Reihenfolge eingefügt werden:

Beispiel 6.2.34 Ist eine Liste sortiert?


>>> liste12 = [3,5,7,6,4,2]
>>> print(liste12 == sorted(liste12))
False

Die Funktion sorted erlaubt es also auch, eine sortierte Kopie einer gegebenen Liste zu erzeugen
und die ursprüngliche Liste unangetastet zu lassen:

Beispiel 6.2.35 Sortierte Kopie einer Liste


>>> l = [1,6,3,9,2,8]
>>> l2 = sorted(l)
>>> l2
[1, 2, 3, 6, 8, 9]
>>> l
[1, 6, 3, 9, 2, 8]

Es ist natürlich auch möglich, ohne Ansehen der Groß-/Kleinschreibung zu sortieren:

Beispiel 6.2.36 Sortierung einer Liste ohne Unterscheidung von Groß-/Kleinschreibung


>>> liste2 = [’x’,’B’,’S’,’P’,’A’,’n’,’m’]
>>> [Link](key=[Link])
>>> liste2
[’A’, ’B’, ’m’, ’n’, ’P’, ’S’, ’x’]

Durch die Angabe des Sortierschlüssels key=[Link] werden alle Elemente aufgefasst, als wären
sie klein geschrieben. Merke: sie werden so aufgefasst, aber keineswegs geändert!!
Das kann man auch noch in anderer Form anwenden. Nach dem Schlüsselwort key kann nicht nur
ein Ausdruck stehen, sondern auch der Name einer Funktion, die etwas Sortierbares zurückgibt:

115
KAPITEL 6. STRUKTURIERTE DATEN 6.2. LISTEN

Beispiel 6.2.37 Sortierung einer Liste nach eigenen Kriterien (Programm)


def sortiere_nach_wortlaenge(wort):
return len(wort)

woerter = [’Martin’, ’ist’, ’doof’]

[Link](key=sortiere_nach_wortlaenge)

print(woerter)

def sortiere_nach_zweitem_Buchstaben(wort):
return wort[1]

[Link](key=sortiere_nach_zweitem_Buchstaben)
print(woerter)

liste = [’Andreas Mueller-Morgenschoen’,’Brigitte Maier’,’Carlo Carlowitsch’,


’Daniela Deppele’]
def nachnameExtrahieren(name):
lz = [Link](’ ’)
return name[lz+1:]

[Link](key = nachnameExtrahieren)

Das Programm liefert die folgenden Ausgaben:

Beispiel 6.2.38 Ergebnis der Sortierung einer Liste nach eigenartigen Kriterien
[’ist’, ’doof’, ’Martin’]
[’Martin’, ’doof’, ’ist’]
[’Carlo Carlowitsch’, ’Daniela Deppele’, ’Brigitte Maier’,
’Andreas Mueller-Morgenschoen’]

6.2.6. Tricks mit ListenMehrere Listen auf einmal bearbeiten


[Link]. Matrizen

Ganz zu Anfang dieses Kapitels habe ich erwähnt, dass die Elemente einer Liste etwas beliebiges sein
können. Darauf warten natürlich die Mathematiker schon lange: eine Matrix ist einfach eine Liste von
Listen!

Beispiel 6.2.39 Matrix


>>> m1 = [[1, 0, 1],[-1,2,0],[0,-2,1]]

Allerdings ist die Darstellung bisher noch nicht so schön, damit müssen wir uns leider gedulden bis
zum Kapitel über die (Wer spickeln möchte: )Schleifen.
Jetzt kann man natürlich auf die Idee kommen zum Beispiel die 5x5-Nullmatrix über mit den oben
genannten Mitteln zu erstellen.

116
KAPITEL 6. STRUKTURIERTE DATEN 6.2. LISTEN

Beispiel 6.2.40 Nullmatrix


>>> nullzeile =[0,0,0,0,0]
>>> nullmatrix = [[nullzeile]*5]
>>> nullmatrix
[[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]]]

Das sieht doch ganz gut aus!


Es geht aber noch kürzer:

Beispiel 6.2.41 Nullmatrix (ganz kurz)


>>> nm = [[0 for i in range(5)]]*5
>>> nm
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]]

Und auch das scheint korrekt zu sein.


Jetzt spreche ich die einzelnen Elemente der Matrix zuerst lesend an

Beispiel 6.2.42 Nullmatrix, [Link], 1. Spalte


>>> nm[3][1]
0

Alles in Ordnung! Dann schreibe ich doch mal in die 3. Zeile 1. Spalte einen neuen Wert:

Beispiel 6.2.43 Nullmatrix, [Link], 1. Spalte ändern


>>> nm[3][1] = 99
>>> nm[3][1]
99

Das scheint auch gut funktioniert zu haben. Schaue ich mir also nochmal die gesamte Liste an:

Beispiel 6.2.44 geänderte Nullmatrix


>>> nm
[[0, 99, 0, 0, 0], [0, 99, 0, 0, 0], [0, 99, 0, 0, 0], [0, 99, 0, 0, 0],
[0, 99, 0, 0, 0]]

Es scheint nur gut funktioniert zu haben! Beim Erzeugen der Matrix habe ich nämlich nur eine 5-
fache Kopie einer Nullzeile gemacht. Konkret: es existiert nur eine einzige Zeile, die 5 mal kopiert die
Matrix ergibt. Wenn ich jetzt also ein Element der Matrix ändere, ändere ich effektiv das angegebene
Spaltenelement jeder Zeile
Da hilft wieder nur, eine Kopie einer Nullzeile (vom ersten bis zum letzten Element) an eine leere
Liste anzuhängen:

117
KAPITEL 6. STRUKTURIERTE DATEN 6.2. LISTEN

Beispiel 6.2.45 Erzeugung und Änderung einer Matrix


>>> nullzeile = [0 for i in range(5)]
>>> nullzeile
[0, 0, 0, 0, 0]
>>> nullmatrix = []
>>> for i in range(5):
[Link](nullzeile[:])
>>> nullmatrix
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]]
>>> nullmatrix[1][1] = 77
>>> nullmatrix
[[0, 0, 0, 0, 0], [0, 77, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]]

[Link]. Listenelemente mit Namen ansprechen

Es ist oft sehr hilfreich, dass die Elemente einer Liste durchnumeriert werden, manchmal ist es aber
auch lästig. Nehmen wir einmal an, dass wir in einer Liste Daten zu einer Person, sagen wir Vornamen,
Nachnamen und Schuhgröße speichern. So zum Beispiel:

Beispiel 6.2.46 Drei Listen


ich = [’Martin’, ’Schimmels’, 43]
hannah = [’Hannah’, ’Schimmels’, 40]
leni = [’Leni’, ’Rein’, 39]

Und nehmen wir weiter an, dass wir diese 3 Personen in einer weiteren Liste speichern wollen:

Beispiel 6.2.47 Eine Liste von Listen


allePersonen = [ich, hannah, leni]

Dann kann man den Vornamen der zweiten Person (denke daran: man fängt bei 0 an zu zählen! Die
2. Person in der Liste hat den Index 1!!) natürlich so holen:

Beispiel 6.2.48 Ein Element einer Liste von Listen (eigentlich ein Matrix-Element)
allePersonen[1][0]

Das ist aber gegen alle Gebote der Schönheit, Nachvollziehbarkeit, Transparenz. Besser wird das da-
durch, dass man genau hinschaut und analysiert, wo was steht. Denn in der Liste jeder der Personen
steht der Vorname immer an erster Stelle, hat also den Index 0. Also baut man sich ein Tupel, das als
Inhalt die Begriffe Vorname, Nachname und Schuhgröße hat, und damit kann man jetzt viel eleganter
auf die Vornamen zugreifen. Hier kommt ein kleiner Programmausschnitt:

118
KAPITEL 6. STRUKTURIERTE DATEN 6.2. LISTEN

Beispiel 6.2.49 Ein Trick bei der Listen-Bearbeitung


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4

5 ich = [’Martin’, ’Schimmels’, 43]


6 hannah = [’Hannah’, ’Schimmels’, 40]
7 leni = [’Leni’, ’Rein’, 39]
8

9 allePersonen = [ich, hannah, leni]


10

11 vorname, nachname, schuhgroesse = range(3)


12

13 print(allePersonen[0][vorname])
14

15 for einer in allePersonen:


16 print(einer[vorname]+’ ’+einer[nachname])
17

Hier wird also in Zeile 11 ein Tupel mit den Zahlen 0,1,2 (Der Begriff range(3) tauchte bisher noch
nicht auf. Der kommt erst im Kapitel über Schleifen; er bedeutet: alle ganzen Zahlen von 0 (inclusive) bis
3 (exclusive) ) aufgebaut, das den Variablen Vorname, Nachname und Schuhgroesse zugeordnet wird.
Zeile 11 bedeutet aufgeschlüsselt, dass der Variablen vorname der Wert 0“, der Variablen nachname

der Wert 1“ und der Variablen schuhgroesse der Wert 2“ zugewiesen wird. Damit kann man auf
” ”
die Teile der Liste, die eine Person beschreibt, über diese Begriffe zugreifen. Das ist doch viel besser zu
lesen!

[Link]. Richtige Datentypen aus einer Zeichenkette


Eigenartiger Titel, aber hier kommt die Erklärung. Angenommen, ich habe eine Liste, in der die Listen-
elemente Textzeilen sind, zum Beispiel eine csv-Liste (comma seperated values). Jede Zeile ist auf die
selbe Art und Weise aufgebaut: der erste Eintrag ist eine Zeichenkette, der zweite eine Dezimalzahl und
der dritte eine Ganzzahl. Es ist jetzt kein Kunststück, diese Einträge einer Zeile aufzusplitten:

Beispiel 6.2.50 Liste von Texten, diese sollen gesplittet werden


1

2 #!/usr/bin/python
3

4 zeilen = ["Martin, 1.91, 75", "Klaus, 1.72, 55", "Hannes, 1.82, 66"]
5

6 for eineZeile in zeilen:


7 felderOF = [Link](’,’)
8 print(felderOF)
9

Die Ausgabe sieht halbwegs gut aus:

Beispiel 6.2.51 Ausgabe: halbwegs gutes Splitten


1

2 [’Martin’, ’ 1.91’, ’ 75’]


3 [’Klaus’, ’ 1.72’, ’ 55’]
4 [’Hannes’, ’ 1.82’, ’ 66’]
5

Das ist wirklich nur halbwegs gut, denn auch die Zahlen werden als Strings wiedergegeben.

119
KAPITEL 6. STRUKTURIERTE DATEN 6.2. LISTEN

Die Verbesserung ist jetzt, dass ich eine Musterzeile erstelle, diese mit der Datenzeile zippe“ und erst

dann ausgebe:

Beispiel 6.2.52 Liste von Texten, diese sollen gesplittet werden, jetzt richtig
1

2 muster = [str, float, int]


3 for eineZeile in zeilen:
4 felderFormat = [typ(wert) for typ, wert in zip(muster, [Link](’,’))]
5 print(felderFormat, end=’\t’)
6 for feld in felderFormat:
7 print(type(feld), end=’, ’)
8 print()
9

Und das wird jetzt besser. Zur Kontrolle gebe ich noch den Typ der Daten aus.

Beispiel 6.2.53 Ausgabe: gutes Splitten


1

2 [’Martin’, 1.91, 75] class ’str’, class ’float’, class ’int’,


3 [’Klaus’, 1.72, 55] class ’str’, class ’float’, class ’int’,
4 [’Hannes’, 1.82, 66] class ’str’, class ’float’, class ’int’,
5

Das Problem soll gelöst werden, dass in mehreren Listen jeweils die ersten, zweiten ... Elemente zu-
sammengefügt werden sollen. Dazu benutzt man die Funktion zip.

Beispiel 6.2.54 Listen vermischen


>>> festtage = [’Ostern’,’Nikolaus’,’Weihnachten’]
>>> figuren = [’Osterhasi’,’Nikolausi’, ’Christkind’]
>>> geschenke = [’Nest mit Ostereiern’, ’Stiefel mit Nüssen’,’viele Bücher’]
>>> for tag,figur,geschenk in zip(festtage,figuren,geschenke):
print(’An ’,tag, ’bringt ’, figur, ’als Geschenk ’, geschenk )

An Ostern bringt Osterhasi als Geschenk Nest mit Ostereiern


An Nikolaus bringt Nikolausi als Geschenk Stiefel mit Nüssen
An Weihnachten bringt Christkind als Geschenk viele Bücher

6.2.7. Kopie einer Liste


Immer wieder benötigt man von einer Liste eine Kopie. Was liegt näher, als folgendes zu versuchen:

Beispiel 6.2.55 Kopie einer Liste (so klappt es nicht!)


>>> meineListe = [’Apfel’,’Birne’, ’Kohl’, ’Gurke’]
>>> kopie = meineListe
>>> print(’meine Liste = ’, meineListe)
>>> print(’Kopie = ’, kopie)

Das ergibt

120
KAPITEL 6. STRUKTURIERTE DATEN 6.2. LISTEN

Beispiel 6.2.56 Kopie einer Liste


meine Liste = [’Apfel’,’Birne’, ’Kohl’, ’Gurke’]
Kopie = [’Apfel’,’Birne’, ’Kohl’, ’Gurke’]

Und so wollten wir das doch . . . könnte man meinen!!! Aber Vorsicht! Hier wurde gar keine Kopie
angelegt, wie man bei den nächsten Anweisungen sieht:

Beispiel 6.2.57 Kopie einer Liste (erster Versuch):


>>> meineListe[2] = ’Sauerkraut’
>>> print(’meine Liste = ’, meineListe)
>>> print(’Kopie = ’, kopie)

Und man liest

Beispiel 6.2.58 Kopie einer Liste: so wollte ich es nicht!


meine Liste = [’Apfel’, ’Birne’, ’Sauerkraut’, ’Gurke’]
Kopie = [’Apfel’, ’Birne’, ’Sauerkraut’, ’Gurke’]

also etwas, was man gar nicht wollte. Was ist passiert? Durch die Einführung der Variablen kopie
wurde dem Speicherbereich, der bisher den Namen meineListe hatte ein zweiter Name gegeben,
aber tatsächlich keine Kopie erstellt. Das wird als flache Kopie“ bezeichnet. Wenn ich wirklich eine

Kopie erstellen will, dann muss ich das per Slicing machen: alle Elemente der ursprünglichen Liste in
eine neue Liste kopieren. Aber das ist zum Glück nicht so schwer. Wir erinnern uns: liste1[1:3]
bedeutete alle Elemente der Liste vom ersten (inclusive) bis zum dritten (exclusive)“. Entsprechend

bedeutet liste1[2:] alle Elemente vom zweiten bis zum letzten“, liste1[:3] alle Elemente vom
” ”
Anfang bis zum dritten“, folglich liste1[:] alle Elemente vom ersten bis zum letzten“.

Beispiel 6.2.59 Kopie einer Liste: aber jetzt!!
>>> meineListe = [’Apfel’,’Birne’, ’Kohl’, ’Gurke’]
>>> kopie = meineListe[:]

Damit erstellt man ein neues Objekt, in das vom ersten bis zum letzten Element alles aus dem alten
Objekt reinkopiert wird. Das kann man jetzt sehen, wenn man wieder aus dem Kohl in der einen Liste
ein Sauerkraut macht.

Beispiel 6.2.60 Kopie einer Liste: na endlich hat es geklappt!


>>> meineListe[2] = ’Sauerkraut’
>>> print(’meine Liste = ’, meineListe)
>>> print(’Kopie = ’, kopie)
meine Liste = [’Apfel’, ’Birne’, ’Sauerkraut’, ’Gurke’]
Kopie = [’Apfel’, ’Birne’, ’Kohl’, ’Gurke’]

6.2.8. Nicht mehr ganz so wilde Listen


Zu Beginn des Kapitels über Listen habe ich das als eine schöne Eigenschaft herausgestellt, dass Lis-
ten beliebige Elemente enthalten können. Manchmal ist das aber nicht wünschenswert. Um Listen zu

121
KAPITEL 6. STRUKTURIERTE DATEN 6.2. LISTEN

erzeugen, die nur einen bestimmten Typ Daten enthalten dürfen, benutzen wir den Modul array.
Ein Array-Objekt erhält beim Erzeugen als ersten Parameter ein Kürzel für die Klasse von Objekten,
die es enthalten darf.

Beispiel 6.2.61 Ein Zahlen-Array ... und was damit nicht geht
>>> import array
>>> meinArray = [Link](’i’,[i for i in range(20)])
>>> print(meinArray)
array(’i’, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])

>>> meinArray. append(’a’)


Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: an integer is required (got type str)

>> meinArray. append(1.2)


Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: integer argument expected, got float

Erzeugt wurde das Array mittels einer Comprehension. Und Zeichenketten oder Dezimalzahlen können
nicht angehängt werden, weil der erste Parameter beim Erzeugen, das ’i’, für integer steht, also für
Ganzzahlen.

122
KAPITEL 6. STRUKTURIERTE DATEN 6.3. DICTIONARIES

Die Hilfe zu [Link] liefert unter anderem folgendes:

Beispiel 6.2.62 Hilfe zu [Link]


>>> help([Link])

Help on class array in module array:

class array([Link])
| array(typecode [, initializer]) -> array
|
| Return a new array whose items are restricted by typecode, and
| initialized from the optional initializer value, which must be a list,
| string or iterable over elements of the appropriate type.
|
| Arrays represent basic values and behave very much like lists, except
| the type of objects stored in them is constrained. The type is specified
| at object creation time by using a type code, which is a single character.
| The following type codes are defined:
|
| Type code C Type Minimum size in bytes
| ’b’ signed integer 1
| ’B’ unsigned integer 1
| ’u’ Unicode character 2 (see note)
| ’h’ signed integer 2
| ’H’ unsigned integer 2
| ’i’ signed integer 2
| ’I’ unsigned integer 2
| ’l’ signed integer 4
| ’L’ unsigned integer 4
| ’q’ signed integer 8 (see note)
| ’Q’ unsigned integer 8 (see note)
| ’f’ floating point 4
| ’d’ floating point 8

6.3. Dictionaries
A cat’s meow and a cow’s moo
You know I could recite them all
(Bob Dylan3 )
Dictionaries gibt es in vielen Programmiersprachen (nur heißen sie dort anders, nämlich hashes“

oder assoziative Arrays“). Das charakteristische für Dictionaries ist, dass hier die Elemente nicht mehr

durchnumeriert werden wie in Listen, sondern Werte unter einem Schlüssel abgelegt werden. Jeder
Dictionary-Eintrag ist also ein Paar von Informationen, wobei die erste Information Schlüssel“ (engl.

key), die zweite Information Wert“ (engl. value) genannt wird. Dictionaries werden in geschweifte

Klammern geschrieben. Im ersten Dictionary soll tatsächlich ein Wörterbuch abgelegt werden.

Beispiel 6.3.1 Ein Dictionary (sogar ein Wörterbuch!)


englDeutsch = {’dog’:’Hund’, ’cat’:’Katze’, ’cow’:’Kuh’, ’sheep’:’Schaf’}

Der Schlüssel eines der Paare ist also hier das englische Wort für ein bestimmtes Tier, der Wert ist
die deutsche Übersetzung dafür. Ein Element eines Dictionary wird also nicht mehr durch eine Haus-
3 Quinn the eskimo auf: Basement Tapes

123
KAPITEL 6. STRUKTURIERTE DATEN 6.3. DICTIONARIES

nummer gefunden, sondern über den Schlüsselbegriff. Wichtig ist es manchmal, alle Schlüssel oder alle
Werte eines Dictionary zu bekommen, manchmal auch beides:

Beispiel 6.3.2 Schlüssel und Werte eines Dictionary


>>> [Link]()
[’sheep’, ’dog’, ’cow’, ’cat’]
>>> [Link]()
[’Schaf’, ’Hund’, ’Kuh’, ’Katze’]
>>> [Link]()
dict_items([(’sheep’, ’Schaf’), (’cat’, ’Katze’),
(’dog’, ’Hund’), (’cow’, ’Kuh’)])

Eine kleine Anwendung von Dictionaries folgt, wenn Schleifen behandelt worden sind.

6.3.1. Zugriff auf Dictionary-Elemente


[Link]. Dictionary lesen

Beispiel 6.3.3 Zugriff auf das obige Wörterbuch


englDeutsch = {’dog’:’Hund’, ’cat’:’Katze’, ’cow’:’Kuh’, ’sheep’:’Schaf’}
>>> englDeutsch[’dog’]
’Hund’
>>> englDeutsch[’cow’]
’Kuh’

Der Versuch des Zugriffs auf ein Dictionary über einen Schlüssel, der nicht existiert, führt aber zu
einem sehr unerwünschten Abbruch des Programms:

Beispiel 6.3.4 erfolgloser Zugriff auf ein Dictionary

>>> englDeutsch = {’dog’:’Hund’, ’cat’:’Katze’, ’cow’:’Kuh’, ’sheep’:’Schaf’}


>>> englDeutsch[’bird’]
Traceback (innermost last):
File "<stdin>", line 1, in <module>
KeyError: ’bird’

Die Fehlermeldung ist hier deutlich: Zugriff mit einem Schlüssel, der nicht existiert.
Dictionaries haben aber die Zugriffsmethode get, der man einen Defaultwert mitgeben kann:

Beispiel 6.3.5 Abfangen eines erfolglosen Zugriffs auf ein Dictionary


>>> englDeutsch = {’dog’:’Hund’, ’cat’:’Katze’, ’cow’:’Kuh’, ’sheep’:’Schaf’}
>>> [Link](’bird’,’bird ist nicht im Dictionary’)
’bird ist nicht im Dictionary’

124
KAPITEL 6. STRUKTURIERTE DATEN 6.3. DICTIONARIES

Eine weitere Methode, setdefault, leistet noch mehr. Während get nur einen Default-Wert ausgibt,
kann man mit setdefault einen Neueintrag in das Dictionary machen:

Beispiel 6.3.6 Was fehlt, wird ergänzt


>>> englDeutsch = {’dog’:’Hund’, ’cat’:’Katze’, ’cow’:’Kuh’, ’sheep’:’Schaf’}
>>> [Link](’bird’,’bird ist nicht im Dictionary’)
’bird ist nicht im Dictionary’
>>> [Link](’bird’,’Vogel’)
’Vogel’
>>> [Link](’bird’,’bird ist nicht im Dictionary’)
’Vogel’

Man sieht: beim ersten Aufruf von get wird nur das Fehlen angezeigt, beim zweiten Aufruf ist der
Wert vorhanden. Man muss auch keine Sorge haben, dass ein bereits bestehender Wert überschrieben
wird:

Beispiel 6.3.7 Kein Überschreiben durch falschen Wert


>>> englDeutsch = {’dog’:’Hund’, ’cat’:’Katze’, ’cow’:’Kuh’, ’sheep’:’Schaf’}
>>> [Link](’bird’,’bird ist nicht im Dictionary’)
’bird ist nicht im Dictionary’
>>> [Link](’bird’,’Vogel’)
’Vogel’
>>> [Link](’bird’,’bird ist nicht im Dictionary’)
’Vogel’
>>> [Link](’bird’,’Nashorn’)
’Vogel’
>>> [Link](’bird’,’bird ist nicht im Dictionary’)
’Vogel’

Das letzte get wäre sogar überflüssig gewesen: setdefault setzt einen neuen Wert, falls der Eintrag
im Dictionary noch nicht existiert; falls er existiert, wird der Wert zurückgegeben.
Mit Hilfe dieser Methode ist es elegant möglich, etwa die Buchstaben häufigkeit eines Textes zu
zählen. Man legt ein leeres Dictionary an und addiert 1 dazu bei jedem Auftreten eines Buchstaben.
Falls in dem Dictionary noch kein Eintrag zu einem Buchstaben existiert, wird mit get“ der Wert 0

eingetragen. Für die Ausgabe dieses und der beiden nächsten Schnipsel benötigen wir eine Schleife, die
aber erst später im Text bei Einführung von Schleifen kommt.

Beispiel 6.3.8 Buchstabenhäufigkeit bestimmen mit Dictionary und get


>>> bs = ’Dies ist ein wirklich doofer Satz mit vielen Buchstaben’
>>> anzB = {}
>>> for b in bs:
... anzB[b] = [Link](b,0) + 1
...
>>> anzB
{’D’: 1, ’i’: 7, ’e’: 6, ’s’: 3, ’ ’: 8, ’t’: 4, ’n’: 3, ’w’: 1,
’r’: 2, ’k’: 1, ’l’: 2, ’c’: 2, ’h’: 2, ’d’: 1, ’o’: 2, ’f’: 1,
’S’: 1, ’a’: 2, ’z’: 1, ’m’: 1, ’v’: 1, ’B’: 1, ’u’: 1, ’b’: 1}

Das ist nicht schlecht, aber bei der Häufigkeit von Buchstaben interessiert Groß-/Kleinschreibung
nicht. Besser wäre also:

125
KAPITEL 6. STRUKTURIERTE DATEN 6.3. DICTIONARIES

Beispiel 6.3.9 Buchstabenhäufigkeit bestimmen mit Dictionary und get(verbessert)


>>> bs = ’Dies ist ein wirklich doofer Satz mit vielen Buchstaben’
>>> anzB = {}
>>> for b in bs:
... anzB[[Link]()] = [Link]([Link](),0) + 1
...
>>> print(anzB)
{’d’: 2, ’i’: 7, ’e’: 6, ’s’: 4, ’ ’: 8, ’t’: 4, ’n’: 3, ’w’: 1,
’r’: 2, ’k’: 1, ’l’: 2, ’c’: 2, ’h’: 2, ’o’: 2, ’f’: 1, ’a’: 2,
’z’: 1, ’m’: 1, ’v’: 1, ’b’: 2, ’u’: 1}

Und jetzt folgt die Komfort-Version, nämlich die alphabetische Ausgabe der Häufigkeiten. Die Schlüssel
werden dazu in einer Liste gespeichert, sortiert, und über diese sortierte Liste wird geschleift:

Beispiel 6.3.10 Buchstabenhäufigkeit bestimmen und alphabetisch ausgebn


>>> bs = ’Dies ist ein wirklich doofer Satz mit vielen Buchstaben’
>>> anzB = {}
>>> for b in bs:
... anzB[[Link]()] = [Link]([Link](),0) + 1
...
>>> schluessel = list([Link]())
>>> [Link]()
>>> for einSchl in schluessel:
... print(einSchl,’:’,anzB[einSchl])
...
: 8
a : 2
b : 2
c : 2
d : 2
e : 6
f : 1
etc.

(In der ersten Zeile der Ausgabe steht das Leerzeichen, das 8 mal auftaucht!!!)

[Link]. Dictionary schreiben


Dictionaries sind veränderbar. Den bird“ kann man also locker einfügen durch

>>> englDeutsch = {’dog’:’Hund’, ’cat’:’Katze’, ’cow’:’Kuh’, ’sheep’:’Schaf’}


>>> [Link](’bird’,’bird ist nicht im Dictionary’)
’bird ist nicht im Dictionary’
>>> englDeutsch[’bird’] = ’Vogel’
>>> [Link](’bird’,’bird ist nicht im Dictionary’)
’Vogel’
>>>

Der Modul collections enthält verschiedene Erweiterungen zu strukturierten Daten, so zum Bei-
spiel das defaultdict. Das ist ein Dictonary, dem ein Defaultwert beim Anlegen zugeteilt werden
kann. Das soll an einem einfachen Beispiel gezeigt werden, bei dem die Vornamen einer Person der

126
KAPITEL 6. STRUKTURIERTE DATEN 6.3. DICTIONARIES

Schlüssel, der Wohnort dieser Person der Wert sein soll. Leider wohnen die meisten betreffenden Perso-
nen nicht in München, Gilching oder Starnberg, sondern in Oberpfaffenhofen; aber diesen langen Orts-
namen will niemand öfter als nötig schreiben. Also schreibe ich eine Funktion oph zurueckgeben, die
diesen Namen zurückgibt.

Beispiel 6.3.11 defaultdic: langer Ortsname


>>> from collections import defaultdict
>>> def oph_zurueckgeben():
... return ’Oberpfaffenhofen’
...
>>> wohnorte = defaultdict(oph_zurueckgeben)
>>> wohnorte[’Paul’]
’Oberpfaffenhofen’
>>> wohnorte[’Jens’] = ’Gilching’
>>> wohnorte[’Leni’] = ’Pasing’
>>> wohnorte[’Lea’]
’Oberpfaffenhofen’
>>> for eintrag in wohnorte:
... print(eintrag,’wohnt in’,wohnorte[eintrag])
...
Paul wohnt in Oberpfaffenhofen
Jens wohnt in Gilching
Leni wohnt in Pasing
Lea wohnt in Oberpfaffenhofen

So kann man sich schon viel Schreibarbeit sparen!

6.3.2. Dictionaries sortiert ausgeben

Beispiel 6.3.12 so geht es


>>> di2 = {’Orangensaft’:1.30,’Apfelsaft’:0.80,’Mangosaft’:2.25,
’Birnensaft’:1.85,’Kirschsaft’:2.14}
>>> for k in sorted([Link]()):
print(k, di2[k])

Apfelsaft 0.8
Birnensaft 1.85
Kirschsaft 2.14
Mangosaft 2.25
Orangensaft 1.3

127
KAPITEL 6. STRUKTURIERTE DATEN 6.3. DICTIONARIES

6.3.3. Was ist denn das irgendwas“, das in einer Liste oder einem Dictionary

stehen kann?

Alles!

Beispiel 6.3.13 Das alles (und noch viel mehr)


#!/usr/bin/python

import math

print(’Arbeit mit der "wildenListe"’)


wildeListe = [169, [Link], math, [Link]]

print(wildeListe[1](wildeListe[0]))
print(wildeListe[2].sin(wildeListe[3]/2))

print(’Arbeit mit dem "wildenDictionary"’)


wildesDic = {’zahl1’: 37, ’mm’:math, ’wurzel’:[Link], ’pi’:[Link]}

print(wildesDic[’wurzel’](wildesDic[’zahl1’]))
print(wildesDic[’mm’].sin(wildesDic[’pi’]/2))

Da steht also in der wilden Liste an Position 0 eine Ganzzahl, an Position 1 aus dem Modul math die
Wurzel-Funktion sqrt, an Position 2 der gesamte Modul math und an Position 3 die aus dem Modul
math importierte Konstante pi. Das wilde Dictionary ist sehr ähnlich aufgebaut, nur im Verhältnis zur
Liste wurden der gesamte Modul und die Wurzel vertauscht.

Beispiel 6.3.14 Das alles funktioniert


Arbeit mit der "wildenListe"
13.0
1.0
Arbeit mit dem "wildenDictionary"
6.082762530298219
1.0

6.3.4. Tricks mit Dictionaries

[Link]. Verschlüsselung durch Erzeugung eines Dictionaries mit zip

Ein anderes nettes Beispiel ist die Caesar-Verschlüsselung. Dazu baue ich ein Dictionary mittels zip
auf, dessen Schlüssel die Kleinbuchstaben und dessen Werte die Zahlen 0 bis 25 sind. Dieses Dictionary
drehe ich um, so dass Schlüssel zu Werten und Werte zu Schlüsseln werden, um den Geheimbuchstaben
herauszufinden.

128
KAPITEL 6. STRUKTURIERTE DATEN 6.3. DICTIONARIES

Beispiel 6.3.15 Caesar-Verschlüsselung


1

2 #!/usr/bin/python
3

4 import string
5

6 klartext = ’Caesar ist doof’


7

8 caesar = dict(zip(string.ascii_lowercase,range(len(string.ascii_lowercase))))
9 caesar_invers = dict(zip([Link](),[Link]()))
10 verschiebung = 3
11

12 geheimtext = ’’
13 for b in klartext:
14 if [Link]() in caesar:
15 index = caesar[[Link]()] + verschiebung
16 geheimtext += caesar_invers[index % len(string.ascii_lowercase)]
17 else:
18 geheimtext += b
19

20 print()
21 print(’Klartext: \t\t%s\nGeheimtext: %s’ % (klartext, geheimtext))
22

Die Ausgabe ist:

Beispiel 6.3.16 Ausgabe der Caesar-Verschlüsselung


1

2 Klartext: Caesar ist doof


3 Geheimtext: fdhvdu lvw grri
4

[Link]. Dictionary Comprehension


Wie bei Listen können auch Dictionaries über eine Comprehension erzeugt werden. Hier wird das de-
monstriert für ein Dictionary, das als Schlüssel die Zahl, als Wert ihre Quadratzahl enthält.

Beispiel 6.3.17 Erzeugung eines Dictionaries Zahl / Quadratzahl


qDic = dict((x, x*x) for x in range(1,21))
for z in qDic:
print(z, qDic[z])

Das kann auch dadurch geschehen, dass man für die Berechnung des Wertes eine Funktion aufruft:

Beispiel 6.3.18 Erzeugung eines Dictionaries Zahl / Quadratzahl über eine Funktion
def qZahlBerechnen(x):
return x*x

qDic = dict((x, qZahlBerechnen(x)) for x in range(1,21))


for z in qDic:
print(z, qDic[z])

129
KAPITEL 6. STRUKTURIERTE DATEN 6.4. TUPEL

Beispiel 6.3.19 Erzeugung eines Dictionaries über Funktion und zip


def qZahlBerechnen(x):
return x*x

r = range(1, 21)
qDic = dict(zip(r, map(qZahlBerechnen, r)))

for z in qDic:
print(z, qDic[z])

6.4. Tupel

6.4.1. Allgemeines zu Tupeln

Tupel? Warum gibt es die? Denn Tupel sind eigentlich nur Listen, allerdings sind sie unveränderlich.
Tupel werden in runde Klammern geschrieben. Und außerdem haben Tupel keine Methoden. Aber das
sind schon die relevanten Unterschiede. Meistens wird man sich für Listen entscheiden, wenn man
Objekte in einer Struktur ablegen will.
Eine ganz schöne Anwendung, und für Programmierer, die mit anderen Programmiersprachen groß
geworden sind, ungewöhnlich, ist das Vertauschen von 2 Objekten. Der Pseudocode für eine solche
Vertauschung sieht so aus (und so muss das auch in fast allen Programmiersprachen codiert werden):

temporaeresDing = ding1
ding1 = ding2
ding2 = temporaeresDing

In Python sieht der Programm-Code so aus, wie sich das der naive Programmierer vorstellt. Dabei wird
benutzt, dass Python bei Zuweisungen die runden Klammern von Tupeln nicht benötigt:

ding1, ding2 = ding2, ding1

Wenn doch alles auf der (Programmierer-)Welt so einfach wäre!!

6.4.2. Benannte Tupel

Eine interessante Anwendung für Tupel sind die benannten Tupel. Mit ihnen kann man komplexe Da-
tenstrukturen abbilden. Okay, das macht man in einer objektorientierten Sprache wie Python über Klas-
sen, aber manchmal ist ein benanntes Tupel auch ganz effektiv, etwa wenn man weiß, dass das ähnliche
Objekte ähnliche Eigenschaften haben, aber das Verhalten dieser Objekte uninteressant ist.
Als Beispiel dienen hier Fahrzeuge. Die namedtuple gehören nicht zum Python-Kern, müssen also
importiert werden. Ein benanntes Tupel wird angelegt, indem man ihm einen Namen und eine Liste von
Eigenschaften gibt. Dann legt man ein Exemplar an, indem man den Eigenschaften einen Wert zuweist.
Jetzt kann man die Eigenschaften über ihren Namen abrufen:

130
KAPITEL 6. STRUKTURIERTE DATEN 6.5. ZUSAMMENFASSUNG

Beispiel 6.4.1 Ein benanntes Tupel namens Auto


>>> Auto = namedtuple(’Auto’, ’modell leistung farbe’)
>>> meinSchrotti = Auto(’Peugeot’, ’60 PS’, ’blau’)
>>> [Link]
’Peugeot’
>>> [Link]
’60 PS’
>>> [Link]
’blau’
>>>

6.5. Zusammenfassung
Hier folgen noch mal die wichtigsten Eigenschaften der strukturierten Daten in einer Tabelle.

Tabelle 6.2. Überblick Strukturierte Daten


Name andere Schreibweise Daran erkennt man’s! veränderbar?
Bezeich-
nung
Liste Array L = [’Hans’, ’Eva’,’Paul’, eckige Klammern ja
’Pia’]
Dictionary Hash D = {’vorname’:’Martin’,’ geschweifte Klammern ja
nachname’:’Schimmels’,
’schuhgroesse’:43, ’au-
to’:’ja’,}
Tupel t = (12, ’Monate’, 3, ’Jahre’) runde Klammern nein

6.6. Mengen (sets)


Mengen (englisch: sets) sind wie Dictionaries ohne Wert, also ein Dictionary mit ausschließlich Schlüsseln.
Sie sehen in Python auch so aus:

>>> zahlenMenge = {1, 5, 3, 2, 8}


>>> print(zahlenMenge)
{8, 1, 2, 3, 5}
>>> zahlenMenge = {1, 5, 3, 2, 8, 3, 3}
>>> print(zahlenMenge)
{8, 1, 2, 3, 5}

Man sieht aber auch hier zwei Dinge:

1. Python speichert eine Menge nicht unbedingt in der Reihenfolge, in der sie eingegeben wurde,
genau wie bei Dictionaries.
2. Die Mathematiker wissen es: in einer Menge ist ein bestimmtes Element höchstens einmal enthal-
ten. Deswegen ist in der gespeicherten Menge nur eine 3“.

6.6.1. Mengenoperationen mit Rechenzeichen


Mengen haben aber besondere Eigenschaften. Man kann den Durchschnitt und die Vereinigungsmenge
von zwei Mengen bilden. Der Operator für den Durchschnitt ist das &, denn die Durchschnittsmenge ist

131
KAPITEL 6. STRUKTURIERTE DATEN 6.6. MENGEN (SETS)

die Menge aller Elemente, die in der einen und auch in der anderen Menge enthalten sind. Der Operator
für die Vereinigung ist das | (der senkrechte Strich), denn die Vereinigungsmenge ist die Menge aller
Elemente, die in der einen oder in der anderen Menge enthalten sind (oder in beiden; der Mathematiker
nennt das ein nicht ausschließliches ODER“ im Gegensatz zum ausschließlichen ODER“, das in der
” ”
deutschen Sprache mit ENTWEDER ... ODER“ gesprochen wird).

Beispiel 6.6.1 Durchschnitt und Vereinigung


>>> zahlenMenge = {1, 5, 3, 2, 8}
>>> zahlenMenge2 = {2, 5, 8, 11}
>>> zahlenMenge & zahlenMenge2
{8, 2, 5}
>>> zahlenMenge | zahlenMenge2
{1, 2, 3, 5, 8, 11}

Auch die Differnzmenge kann erzeugt werden, selbstverständlich durch das Minuszeichen. Aber Vor-
sicht: die Differenz ist nicht symmetrisch:

Beispiel 6.6.2 Differenzmenge


>>> zahlenMenge = {1, 5, 3, 2, 8}
>>> zahlenMenge2 = {2, 5, 8, 11}
>>> zahlenMenge - zahlenMenge2
{1, 3}
>>> zahlenMenge2 - zahlenMenge
{11}

In der Differenz menge1 - menge2“ sind alle Elemente von Menge1, die nicht in Menge2 sind. Die

symmetrische Differenz, also die Elemente von Menge1, die nicht in Menge2 sind zusammen mit den
Elementen von Menge2, die nicht in Menge1 sind, wird durch den Operator ˆ gebildet:

Beispiel 6.6.3 Symmetrische Differenz


>>> zahlenMenge2 ˆ zahlenMenge
{1, 3, 11}
>>> zahlenMenge ˆ zahlenMenge2
{1, 3, 11}

Teilmenge ist eine Menge, die einen Teil der Elemente der ursprünglichen Menge enthält. Der Opera-
tor ist das <=-Zeichen, für die echte Teilmenge das <-Zeichen

132
KAPITEL 6. STRUKTURIERTE DATEN 6.6. MENGEN (SETS)

Beispiel 6.6.4 Teilmenge


>>> menge = {1,4,7,11,8}
>>> unechte = {1,8,4,7,11}
>>> teilMenge = {1,11,4}
>>> keineTeilmenge = {1,2,3}
>>> teilMenge <= menge
True
>>> keineTeilmenge <= menge
False
>>> unechte <= menge
True

Entsprechend werden für die Obermenge die Operatoren > bzw. >= verwendet.

6.6.2. Mengenoperationen als Methoden der Klasse Menge


Eine Menge ist ein Objekt der Klasse set. 4 Das bedeutet insbesondere, dass man eine Menge auch über
den folgenden Befehl erzeugen kann:

Beispiel 6.6.5 Menge als Objekt der Klasse set


>>> ungerade = set([1,3,5,7,9])
>>> ungerade
{9, 1, 3, 5, 7}
>>> type(ungerade)
<class ’set’>

Das ist also tatsächlich ein Objekt der Klasse set.


Damit können die Mengenoperationen auch als Methoden der Klasse beschrieben werden.

Beispiel 6.6.6 Mengenoperationen als Methoden


>>> menge = set([1,4,7,8,11])
>>> unechte = set([1,8,4,7,11])
>>> teilMenge = set([1,11,4])
>>> keineTeilmenge = set([1,2,3])
>>> [Link](menge)
True
>>> [Link](teilMenge)
True
>>> [Link](menge)
{1}
>>> [Link](menge)
{1, 2, 3, 4, 7, 8, 11}

Für Mathematiker ist das klar, aber auch für Andere ist das verständlich.
Hier kommen noch einige Mengenoperationen, realisiert durch Methoden der Klasse set:

4 Objekte und Klassen werden weiter hinten besprochen.

133
KAPITEL 6. STRUKTURIERTE DATEN 6.7. AUFGABEN ZU LISTEN, DICTIONARIES . . .

Beispiel 6.6.7 Mengenoperationen als Methoden (Forts.)


>>> a = {1,2,3,4}
>>> b = {2,4,6,8}
>>> sm = [Link](b)
>>> sm
{2, 4}
>>> vm = [Link](b)
>>> vm
{1, 2, 3, 4, 6, 8}
>>> dab = [Link](b)
>>> dab
{1, 3}
>>> dba = [Link](a)
>>> dba
{8, 6}
>>> dsym = a.symmetric_difference(b)
>>> dsym
{1, 3, 6, 8}
>>> dsym2 = b.symmetric_difference(a)
>>> dsym2
{1, 3, 6, 8}

6.7. Aufgaben zu Listen, Dictionaries . . .


1. Schreibe ein Python-Programm, das eine Eiskarte darstellt. Die verschiedenen Angebote Deiner
Eisdiele sollen in einem Dictionary abgelegt werden, das als Schlüssel den Namen des Eisbechers
und als Wert den Preis enthält.
2. Eine Liste von Staaten soll erstellt werden, in der die Listenelemente wieder Listen sind. Gespei-
chert werden sollen der Ländername, die Hauptstadt und die Landessprache. Wie speichert man
es sinnvoll ab, wenn ein Land wie z.B. die Schweiz mehrere Landessprachen hat?
3. Ein Adressbuch soll angelegt werden. Mit Adressen ist nicht etwas wie martin@[Link]“ gemeint,

sondern so etwas Altmodisches, was man auf Briefumschläge geschrieben hat, wie zum Beispiel:

Frau
Mathilde Weber
Primus-Truber-Straße 123
72072 Tübingen
Deutschland

Das bietet sich an als ein Dictionary von Dictionaries. Überlege Dir sinnvolle Ausgaben dieser
Datenstruktur.

6.8. Veränderbarkeit von Daten


Die Frage, ob Daten eines bestimmten Typs (genauer: Daten, die Objekte einer bestimmten Klasse sind)
verändert werden können, ist sowohl im Kapitel über Zeichenketten als auch im Kapitel über struktu-
rierte Daten aufgetaucht. Hier soll nochmals kurz zusammengefasst werden, was bisher bekannt ist.
Zeichenketten können nicht verändert werden. Es ist zwar möglich, ein bestimmtes Element einer
Zeichenkette (also genau ein Zeichen) auszulesen, aber es kann nicht verändert werden. Schau:

134
KAPITEL 6. STRUKTURIERTE DATEN 6.8. VERÄNDERBARKEIT VON DATEN

Beispiel 6.8.1 Versuch, einen Buchstaben in einer Zeichenkette zu ändern


>>> name = ’Sandra’
>>> name[5]
’a’
>>> name[5] = ’o’

Traceback (most recent call last):


File "<pyshell#19>", line 1, in <module>
name[5] = ’o’
TypeError: ’str’ object does not support item assignment

Wie gesagt: es ist nicht so einfach, aus Sandra einen Sandro zu machen; die Fehlermeldung sagt uns
genau das, dass nämlich ein Element eines str-Objects keine Zuweisung erlaubt.
Bei einer Liste sieht das ganz anders aus.

Beispiel 6.8.2 Versuch, ein Element einer Liste zu ändern


>>> bListe = [’S’,’a’,’n’,’d’,’r’,’a’]
>>> bListe[5] = ’o’
>>> bListe
[’S’, ’a’, ’n’, ’d’, ’r’, ’o’]

Das klappt.
Die Unveränderlichkeit von Zeichenketten hat auch eine Bedeutung für die Speicherung von Varia-
blen. Schauen wir, was passiert, wenn man zwei verschiedenen Variablen die selbe Zeichenkette zu-
weist. Nach diesen zwei Zuweisungen schauen wir uns mit Hilfe von id an, an welchem Speicherplatz
der Text gespeichert ist.

Beispiel 6.8.3 2 Variable mit dem selben (Text-)Inhalt


>>> a = ’Martin’
>>> b = ’Martin’
>>> id(a)
3055883200L
>>> id(b)
3055883200L

Beide Variable haben die selbe Adresse!! Um Speicherplatz zu sparen, wird der Text nur einmal ge-
speichert, da Python ja weiß, dass dieser unveränderlich ist. Also werden die Variable a und die Va-
riable b ihren (gemeinsamen) Wert immer an der richtigen Stelle finden. Der Speicherplatz, an dem die
Information Martin“ steht, hat zuerst den Namen a bekommen, später noch ein Pseudonym, einen

Alias-Namen, nämlich b.
Wenn man die selbe Aktion mit zwei Listen durchführt, geschieht etwas völlig anderes.

135
KAPITEL 6. STRUKTURIERTE DATEN 6.8. VERÄNDERBARKEIT VON DATEN

Beispiel 6.8.4 2 Listen mit dem selben Inhalt


>>> liste1 = [’M’,’a’,’r’,’t’,’i’,’n’]
>>> liste2 = [’M’,’a’,’r’,’t’,’i’,’n’]
>>> id(liste1)
3055883276L
>>> id(liste2)
3055840108L

Tatsächlich: zwei verschiedene Adressen. Das muss so sein, denn jede Liste könnte verändert werden,
also müssen die beiden Variablen auf verschiedene Speicherplätze zugreifen.
Weiter unten bei den Funktionen werden wir sehen, dass das unter Umständen Probleme bereiten
kann.

136
Teil IV.

Strukturen

137
7. Programmstrukturen
Don’t think twice, it’s alright
(Bob Dylan1 )

7.1. Gute Programme, schlechte Programme


Bevor wir jetzt beginnen, richtige Programme zu schreiben, die eine gewisse Struktur haben, sollten
wir uns zurücklehnen und uns vornehmen: wir schreiben nicht nur richtige Programme, sondern gute
Programme. Wenn man ja nur wüßte, was ein gutes Programm ist!! Dass ein Programm die Aufgabe
erfüllt, zu der man es geschrieben hat, ist eine Selbstverständlichkeit: ein solches Programm ist noch
nicht gut, es funktioniert.
Damit es gut wird, muss es anpassbar sein, vielseitig verwendbar, gut lesbar, leicht änderbar, schön.
Das alles wollen wir schaffen? Klar, und zwar gleich von Anfang an!
Deswegen kommt hier zuerst eine Regel, die uns etwas verbietet, richtig knallhart verbietet, denn
so etwas geht gar nicht: Ein Programm ist schlecht, wenn sich eine Zeile wiederholt. Das soll auch
positiv formuliert werden: Damit ein Programm gut ist, darf eine Anweisung nur einmal auftauchen.
Das hört sich brutal an, aber es ist wirklich so: eine Anweisung darf nur einmal auftauchen! Wenn auch
nur eine Anweisung mehrmals auftaucht, hat man bei der Konzeption, der Denkarbeit, bevor man sich
an den Computer setzt und etwas eintippt, einen Fehler gemacht: einen Denkfehler.
Die Python-Programmierer haben dazu auch etwas veröffentlicht: The Zen of Python“. Das kann

man nachlesen, indem man in der Python-Shell den Befehl import this eingibt. Do it!

7.1.1. Kontrollfluß
Darum haben wir uns bis jetzt noch nicht gekümmert! Bis jetzt wurde ein einzelner Befehl ausgeführt,
bestenfalls ein paar Befehle hintereinander; und es gab keine Möglichkeit, von dieser Reihenfolge abzu-
weichen. Der Fluß des Programms war linear und von uns eindeutig vorgegeben.
Das soll sich jetzt ändern, wir werden in den Kontrollfluß eingreifen. Das geht grundsätzlich auf zwei
Arten: durch Wiederholungsanweisungen und durch das Treffen von Entscheidungen. Also stürzen wir
uns rein ins Vergnügen! Aber damit alles seine Ordnung hat, wird das Thema des linearen Programms
gleich als erstes aufgegriffen.

7.2. Eins nach dem anderen: Die Sequenz


Bisher war Programmieren eher langweilig. Wir haben einzelne Befehle aufgeschrieben, und jeden die-
ser Befehle ausführen lassen. Eine solche Folge von Befehlen wird in der Programmierung als Sequenz
bezeichnet. Trotzdem ist dies natürlich schon richtiges Programmieren. Ausreichend viele Programme
tun schon etwas sehr vernünftiges, nur indem sequentiell Anweisungen abgearbeitet werden
Wenn jetzt die Programmstrukturen eingeführt werden, ist es Zeit, wieder einmal den Begriff des Al-
gorithmus hervorzuholen. Ein Algorithmus ist, einfach gesagt, nichts anderes als ein Kochrezept. Einen
solchen Algorithmus beschreibt man oft in einem Mittelding zwischen natürlicher Sprache, für uns also
Deutsch, und Programmiersprache. Die natürliche Sprache wird dazu leicht formalisiert, um Strukturen
hervorzuheben. Das klassische Mittel dafür ist das Einrücken von zusammengehörigen Anweisungen,
die von einer Bedingung abhängig sind.
Bei Sequenzen ist ein Algorithmus natürlich einfach: hier ist nichts abhängig von etwas anderem, und
alles wird der Reihe nach aufgeschrieben:
1 Don’t think twice, it’s alright auf: The Freewheeling Bob Dylan

139
KAPITEL 7. PROGRAMMSTRUKTUREN 7.2. EINS NACH DEM ANDEREN: DIE . . .

Beispiel 7.2.1 Sequenz


Kerngehäuse aus Paprika entfernen
Paprika mit Tomaten, Zwiebeln und Knoblauch zu einem Mus mixen
saure Sahne schaumig rühren
Mus mit der Sahne vermischen
mit Salz und Paprikapulver abschmecken
ziehen lassen

Das ist nachzuvollziehen. Und lecker!!!


Fazit zum Thema sequentielle Programme: Besser als nichts, aber nicht viel besser! Trotzdem könnte
man dazu ein bißchen üben!

7.2.1. Aufgaben zu Sequenz


1. Falls Du es nicht mehr auswendig weißt, weil die Fahrschule schon zu lange hinter Dir liegt:
informiere Dich, wie man den Anhalteweg eines Autos berechnet. Schreibe dann ein Programm,
in das eine Geschwindigkeit eingegeben wird. Das Programm soll dann den Reaktionsweg, den
Bremsweg und den Anhalteweg ausgeben.
2. Informiere Dich über die Herzfrequenz beim Training für eine optimale Fettverbrennung und für
einen maximalen Konditionsaufbau. Schreibe dann ein Programm, in das man sein Alter eingibt.
Das Programm soll den maximalen Puls für einen Menschen Deines Alters sowie die optimalen
Frequenzen für Konditionsaufbau und Fettabbau ausgeben.
3. Der Body-Mass-Index soll durch ein Programm berechnet werden. Die Eingabe soll über variable

= input . . .“ erfolgen. Der BMI errechnet sich als Gewicht in kg geteilt durch das Quadrat der
Größe in Metern.
4. Ein Umrechnungsprogramm soll geschrieben werden, das Meter in Fuß umrechnet. (1 Fuß = 30,48
cm)
5. Ein Umrechnungsprogramm Liter in Pint soll geschrieben werden.
6. Ein Programm soll sechs Zahlen einlesen und den Mittelwert dieser sechs Zahlen ausgeben.
7. Aus dem Stundenlohn und der Anzahl der gearbeiteten Stunden soll der Verdienst berechnet wer-
den.
8. In ein Programm soll der Radius eines Kreises eingegeben werden. Das Programm soll den Um-
fang und die Fläche des Kreises ausgeben.
9. Länge und Breite eines Rechtecks sollen eingegeben werden. Das Programm soll den Umfang, die
Fläche und die Länge der Diagonalen des Rechtecks ausgeben.
10. Kosten einer Klassenfahrt:
• Eingabe:
– Kosten für den Bus
– Übernachtungskosten pro Person und Nacht
– Anzahl Nächte
– Anzahl Schüler
– Anzahl Lehrer
– Gesamtkosten für Denkmäler, Museeen, Konzerte etc.

• Ausgabe:
– Gesamtkosten für die Fahrt
– Kosten je Person

11. Quader:
• Eingabe:
– Länge des Quaders

140
KAPITEL 7. PROGRAMMSTRUKTUREN 7.3. WENN . . . DANN: DIE ALTERNATIVE

– Breite des Quaders


– Höhe des Quaders
• Ausgabe:
– Volumen des Quaders
– Oberfläche des Quaders
– Benötigte Menge Draht für ein Kantenmodell des Quaders

7.3. Wenn . . . dann: Die Alternative


Die Sequenz gehört zu den Elementen der Strukturierten Programmierung“. Weitere Elemente sind

• die Auswahl (auch Alternative“)

• die Wiederholung (auch Iteration“)

7.3.1. Wahrheit
Hier muss ein kleines Kapitel eingeschoben werden, das sich mit Wahrheit befasst. Dazu gilt es, ein paar
Fragen zu stellen und zu beantworten.
1. Welche Wahrheitswerte gibt es?
2. Welche Arten von Termen gibt es?
3. Bei welchen dieser Terme kann man sinnvoll die Frage nach einem Wahrheitswert dieses Terms
stellen?
4. Wenn ich mehrere solcher Terme habe:
a) Wie kann ich sie sinnvoll verknüpfen?
b) Wie sieht es bei einer solchen Verknüfpung mit der Wahrheit aus?
Die erste Frage ist einfach zu beantworten: eine Aussage kann wahr oder falsch sein. Da Program-
miersprachen sich an der englischen Sprache orientieren: sie kann true“ oder false“ sein. In Python
” ”
entspricht das den Werten True und False. Diese Werte werden Boole’sche Werte“ genannt, eine

Variable, die nur diese Werte annehmen kann, heißt entsprechend Boole’sche Variable“ 2

Hier folgen verschiedene Arten von Termen: Ziffern, Zahlen, Buchstaben, Texte, Gleichungen, Bedin-
gungen ...
Zur dritten Frage: jetzt sollten wir die Arten von Termen auf einen möglichen Wahrheitswert unter-
suchen. Python hilft uns dabei, denn Python enthält die Funktion bool, die den Wahrheitswert eines
Termes zurückgibt.
1. Kann eine Ziffer wahr oder falsch sein?

>> bool(9)
True
>>> bool(5)
True
>>> bool(1)
True
>>> bool(0)
False
>>> bool(-1)
True
>>> bool(-9)
True

2 nach dem englischen Mathematiker George Boole. Siehe hierzu: <[Link]

141
KAPITEL 7. PROGRAMMSTRUKTUREN 7.3. WENN . . . DANN: DIE ALTERNATIVE

Fazit: Jede Ziffer ausser der Null ist wahr.

2. Kann ein Buchstabe oder ein Text wahr oder falsch sein?

>>> bool(’a’)
True
>>> bool(’Z’)
True
>>> bool(’ä’)
True
>>> bool(’Python’)
True
>>> bool(’Python ist klasse!’)
True
>>> bool(’ ’)
True
>>> bool(’’)
False

Fazit: Jeder Text der Länge 1 bis unendlich ist wahr. Nur der Text, der aus nichts besteht, ist falsch.

3. So, das reicht! Selbst probieren macht schlau!

Bedingungen sind die interessanteste Art von Termen. Eine Bedingung ist normalerweise der Ver-
gleich von zwei Dingen, meistens einem konstanten Wert und dem Wert einer Variablen. Beispiele (in
natürlicher Sprache), wobei die Variablen, mit denen verglichen werden soll, explizit in Klammern an-
gesprochen werden, sind:

1. (Wert der Variablen) n größer als 17


2. (Wert der Variablen) nachname gleich Meier“

3. Pfeffer“ in (der Variablen, die die) Liste der Gewürze (enthält)

4. (Lesezeiger hat das) Ende der Datei (erreicht)

Hier ist klar: alle diese Bedingungen können, als Frage gestellt, mit Ja“ oder mit Nein“ beantwortet
” ”
werden, in der Sprache der Informatik mit True“ oder mit False“.
” ”
Zwischen den Werten, die in einer Bedingung miteinander verglichen werden, steht ein Vergleichs-
operator. Zu den elementaren“ Vergleichsoperatoren siehe weiter vorne im Buch.

Die ersten drei dieser Beispiele sollen jetzt in Python formuliert werden.

1. Ist n größer als 17?

Beispiel 7.3.1
>>> n = 18
>>> n > 17
True
>>> n = 5
False
>>> n > 17

2. Ist der Nachame Meier“?


142
KAPITEL 7. PROGRAMMSTRUKTUREN 7.3. WENN . . . DANN: DIE ALTERNATIVE

Beispiel 7.3.2
>>> nachname = ’Schimmels’
>>> nachname == ’Meier’
False
>>> nachname = ’Meier’
>>> nachname == ’Meier’
True

Beachte hierbei: der Vergleich auf Gleichheit geschieht durch zwei aufeinanderfolgende Gleich-
heitszeichen. Siehe oben bei Vergleichsoperatoren
3. Ist Pfeffer“ ein Gewürz?

Beispiel 7.3.3
>>> listeGewuerze = [’Salz’,’Curry’,’Paprika’]
>>> ’Pfeffer’ in listeGewuerze
False
>>> listeGewuerze = [’Salz’,’Curry’,’Pfeffer’,’Paprika’]
>>> ’Pfeffer’ in listeGewuerze
True

Eine Bedingung kann immer den Wahrheitswert wahr“ oder den Wahrheitswert falsch“ haben.
” ”

Beispiel 7.3.4 True und False


>>> False
False
>>> True
True
>>> not False
True
>>> not True
False

Dieses Beispiel zeigt eigentlich nur, dass True“ das Gegenteil von False“ ist (und umgekehrt). Aber
” ”
Vorsicht: das sind Variable, und deswegen dürfen diese Wörter keineswegs in Anführungsstrichen ge-
schrieben werden.

Beispiel 7.3.5 True und False (ganz falsch)


>>> not "True"
False
>>> not "False"
False

Oft sind Bedingungen zusammengesetzt, und aus diesem Grunde muss man sich Gedanken darüber
machen, was eine Aussage wie WAHR und FALSCH“ oder wie WAHR oder FALSCH“ bedeutet. Das
” ”
macht man meistens in sogenannten Wahrheitstafeln“. Zum Glück ist das, was man in der Programmie-

rung benötigt, überschaubar. Jetzt soll die Frage der Verknüpfung von Bool’schen Termen angegangen
werden. Es gibt 3 elementare Verknüpfungen:

143
KAPITEL 7. PROGRAMMSTRUKTUREN 7.3. WENN . . . DANN: DIE ALTERNATIVE

1. mit und“

2. mit oder“

3. mit nicht“

Die reservierten Wörter in Python dazu sind and, or und not


Die Verknüpfungstafeln lasse ich durch ein Python-Programm schreiben. Das sieht so aus:

Beispiel 7.3.6 Logische Verknüpfungen


#!/usr/bin/python

print(’UND-Verknüpfung’)

formatString = "{:<8} {:<8} {:<6} "


print([Link](’1. Wert’, ’[Link]’, ’Ergebnis’))
for wert1 in (True, False):
for wert2 in (True, False):
print([Link](str(wert1), str(wert2), str(wert1 and wert2)))

print(’\n\nODER-Verknüpfung’)

formatString = "{:<8} {:<8} {:<6} "


print([Link](’1. Wert’, ’[Link]’, ’Ergebnis’))
for wert1 in (True, False):
for wert2 in (True, False):
print([Link](str(wert1), str(wert2), str(wert1 or wert2)))

print(’\n\nNICHT-Verknüpfung’)

formatString = " {:<8} {:<6} "


print([Link](’1. Wert’, ’Ergebnis’))
for wert1 in (True, False):
print([Link](str(wert1), str(not wert1)))

Die Ausgabe des Programms sind die 3 Verknüpfungstafeln, und das sieht so aus:

Tabelle 7.1. UND-Verknüpfung


1. Wert 2. Wert Ergebnis
True True True
True False False
False True False
False False False

Tabelle 7.2. ODER-Verknüpfung


1. Wert [Link] Ergebnis
True True True
True False True
False True True
False False False

144
KAPITEL 7. PROGRAMMSTRUKTUREN 7.3. WENN . . . DANN: DIE ALTERNATIVE

Tabelle 7.3. NICHT-Verknüpfung


1. Wert Ergebnis
True False
False True

Die logischen Verknüpfungen und“ und oder“ werden im Kurz-Verfahren ausgewertet. Was das be-
” ”
deutet, sieht man mit einem Zwischenblick auf die obigen Verknüpfungstafeln. Eine und“-Verknüpfung

hat den Wert falsch“, wenn die erste Aussage falsch ist; eine oder“-Verknüpfung hat den Wert wahr“,
” ” ”
wenn die erste Aussage wahr ist. In diesen beiden Fällen wird die Auswertung abgebrochen, weil das
Ergebnis jetzt schon fest steht.
Aber Vorsicht: wenn man zwei Aussagen mit oder“ verknüpft und die erste Aussage ist falsch, wird

die zweite Aussage zurückgegeben. Das liefert unter Umständen nicht das gewünschte Ergebnis:

Beispiel 7.3.7 Kurzschluß beim logischen ODER


>>> 3+5 == 8 or "Heute ist der 31. Mai"
True
>>> 3+5 == 7 or "Heute ist der 31. Mai"
’Heute ist der 31. Mai’

Ich glaube, Du willst jetzt mal testen, ob Du das alles verstanden hast. Also kommt hier eine Entschei-
dungstabelle, in die Du in die letzte Spalte den korrekten Wahrheitswert eintragen sollst.

Tabelle 7.4. Übung zu Wahrheitswerten


x y z Verknüpfung(en) Wahrheitswert
5 12 x<y
15 12 x<y
3 8 x>y
3 3 x <= y
17 18 x >= y
3 5 7 y > x and z > y
3 5 7 y > x and y >= z
3 5 7 y > x or y <= z
sonnig“ heiss“ bewölkt“ x == sonnig“ and z == heiß“
” ” ” ” ”
sonnig“ heiß“ bewölkt“ x == sonnig“ and y == heiß“
” ” ” ” ”
sonnig“ heiß“ bewölkt“ x == sonnig“ or z == bewölkt“
” ” ” ” ”
sonnig“ heiß“ bewölkt“ x == sonnig“ or not (y == heiß“)
” ” ” ” ”
sonnig“ heiß“ bewölkt“ x == sonnig“ and y == not heiß“
” ” ” ” ”
sonnig“ heiß“ bewölkt“ x == sonnig“ or not (z == bewölkt“)
” ” ” ” ”
sonnig“ heiß“ bewölkt“ x == sonnig“ or y == heiß“
” ” ” ” ”

Wenn Du merkst, dass das noch nicht so ganz locker klappt, denk Dir noch mehr solche Übungen
aus!

[Link]. Sprachliche Ungenauigkeiten und Fallen

Als erstes kommt hier ein Beispiel, das ich letzthin bei einem Programmieranfänger gesehen habe. Die
Aufgabe war, ein Programm zu schreiben, das bei einer Schulnote von 5 oder 6 den Text nicht versetzt“

ausgibt. In Pseudocode (s. Glossar) geschrieben:

145
KAPITEL 7. PROGRAMMSTRUKTUREN 7.3. WENN . . . DANN: DIE ALTERNATIVE

Beispiel 7.3.8 Entscheidung mit einem oder“ in Pseudocode



WENN die Note gleich 5 ODER 6 ist:
gib aus NICHT VERSETZT

Also kommt man in Versuchung, in Python zu schreiben:

Beispiel 7.3.9 Das selbe in Python, aber mit einem Denkfehler


note = 4
if note == 5 or 6:
print(’NICHT VERSETZT’)

Die Umgangssprache hat uns hier auflaufen lassen! Schauen wir den Term hinter dem if an:
1. Der Inhalt der Variablen note soll auf Gleichheit mittels == verglichen werden
2. mit dem, was hinter dem Vergleichsoperator steht,
3. also mit dem Term 5 or 6
4. Jetzt schauen wir weiter oben noch mal nach:
a) 5 ist eine Zahl ungleich 0, hat also den Wahrheitswert True
b) 6 ist eine Zahl ungleich 0, hat also den Wahrheitswert True
c) True mit or verknüpft mit True ist True
d) Ergebnis: Wenn die Note von 0 verschieden ist, ist der Vergleich immer True, also wird außer
bei der Note 0 immer NICHT VERSETZT ausgegeben.
Korrekt muss das Programm so aussehen:

Beispiel 7.3.10 Richtiges Oder


note = 4
if note == 5 or note == 6:
print(’NICHT VERSETZT’)

Hier werden tatsächlich 2 Bedingungen mit einem oder“ verknüpft.



Die umgangssprachliche Formulierung Wenn die Note 5 oder 6 ist, ...“ muss korrekt heißen Wenn
” ”
die Note 5 ist oder die Note 6 ist, ...“

7.3.2. Wahrheit angewandt: die Alternative


Alternative bedeutet, dass hier in eine Sequenz eingegriffen wird und von zwei Möglichkeiten eine
ausgewählt wird.3 Die Auswahl wird getroffen anhand einer oder mehrerer Bedingungen.
Das soll in dem folgenden Beispiel (das nicht in einer Programmiersprache formuliert ist, sondern
umgangssprachlich) demonstriert werden:

Beispiel 7.3.11 Entscheidung (if - then)


WENN die Person mit dem Namen Müller männlich ist:
begrüße sie mit Herr Müller
SONST:
begrüße sie mit Frau Müller

3 Alternative bedeutet tatsächlich nur eine Auswahl aus zwei Möglichkeiten; in der Umgangssprache (aber leider oft auch in der
Fachsprache) wird Alternative oft als Auswahl unter mehreren Möglichkeiten“ beschrieben.

146
KAPITEL 7. PROGRAMMSTRUKTUREN 7.3. WENN . . . DANN: DIE ALTERNATIVE

Die Bedingung fragt hier das Geschlecht der Person ab. Die Auswahl wird getroffen zwischen der
Anrede Herr“ und Frau“.
” ”
Üblicherweise wird eine Bedingung formuliert, indem
• zwei Werte miteinander verglichen werden
• der Wert einer Variablen mit einem Wert verglichen wird
• der Wert einer Variablen mit dem Wert einer anderen verglichen wird
Es gibt dabei verschiedene Möglichkeiten, einen Vergleich zu formulieren:
• es wird auf Gleichheit untersucht
• es wird auf Ungleichheit untersucht
• es wird auf Größe mit Hilfe von größer“, kleiner“ größer oder gleich“, kleiner oder gleich“
” ” ” ”
untersucht
Die Zeile, die mit dem Schlüsselwort WENN“ beginnt, heißt Kopf der Alternative, das was gemacht

werden soll, wenn die Bedingung erfüllt wird (oder auch nicht), ist der Körper. Die Begriffe Kopf und
Körper werden auch später bei der Iteration und bei Unterprogrammen wieder auftauchen.
Eine solche Schreibweise, bei der Wörter der Alltagssprache benutzt werden, aber eine Syntax, die
sich an die Logik wird Pseudocode“ (s. Glossar) genannt. Und zum Verhältnis von Pseudocode einer

Programmiersprache anlehnt, zu Programmen in der Programmiersprache Python sagt Lutz 4 : Because

Python’s syntax resembles executable pseudocode, it yields programs that are easy to understand, change,
and use long after they have been written“ Es gibt also wenig Gründe, in einem Skript über Python
Pseudocode zu verwenden, denn Python-Code sieht wie Pseudocode aus. Wenn ich es mache, dann
meistens nur, um etwas auf deutsch (und nicht auf englisch) zu schreiben.
Der Code in Python sieht dann so aus:

Beispiel 7.3.12 Entscheidung (if - then) (Python)


if geschlecht == ’m’:
print(’Guten Tag, Herr Müller’)
else:
print(’Guten Tag, Frau Müller’)

Man sieht sofort die Parallelen zwischen Pseudocode und Python-Code!

7.3.3. Blöcke und Einrückungen


Wenn mehrere Anweisungen auf der selben logischen Stufe stehen, spricht man von einem Block, oft
genau von einem Anweisungsblock. Eine Sequenz, so wie sie in den bisherigen Beispielen geschrieben
wurde, ist ein Block auf der höchsten logischen Ebene. Im Folgenden werden Blöcke auf einer tieferen
Ebene behandelt, nämlich Blöcke, die von einer Bedingung abhängen.
An der Schreibweise des obigen Beispiels können wir aber gleich eine wesentliche Eigenschaft von
Python lernen. Die Bedingung (also hier die Frage, ob das Geschlecht der Person männlich ist) wird
auf ihren Wahrheitsgehalt geprüft. Die Bedingung kann erfüllt sein, das heißt, die Frage wird mit ja“

beantwortet oder anders gesagt, die Bedingung bekommt den Wert wahr“, oder die Bedingung ist

nicht erfüllt, das heißt, die Frage wird mit nein“ beantwortet oder anders gesagt, die Bedingung be-

kommt den Wert falsch“. Die Aktion (oder die Aktionen), die in dem einen beziehungsweise im an-

deren Fall ausgeführt wird, ist von dem Wert der Bedingung abhängig. Man spricht von den DANN-

Anweisungen“ bzw. von den SONST-Anweisungen“

Solche Abhängigkeiten müssen dem Programm, das wir schreiben wollen, mitgeteilt werden. Eine in
vielen Programmiersprachen verwendete Methode ist es, den abhängigen Teil in besondere Zeichen, oft
in Klammern, einzufassen. Python geht einen anderen Weg: In Python wird alles, was von etwas ande-
rem abhängig ist, eingerückt. Dabei muss man beachten, dass alles, was von dem selben Programmteil
abhängig ist, um die selbe Länge eingerückt wird. Noch dazu muss man aufpassen, dass man nicht Ta-
bulatoren und Leerzeichen vermischt. Das soll hier durch eine Erweiterung des obigen Beispiels deutlich
gemacht werden (und das Beispiel erklärt sich selber):
4 [Programming Python], Seite 5

147
KAPITEL 7. PROGRAMMSTRUKTUREN 7.3. WENN . . . DANN: DIE ALTERNATIVE

Beispiel 7.3.13 Verschachtelte Entscheidungen (Pseudocode)


WENN die Person männlich ist:
WENN es vor 12 Uhr ist:
begrüße sie mit ’Guten Morgen, Herr Müller’
SONST:
begrüße sie mit ’Guten Tag, Herr Müller’
SONST:
WENN es vor 12 Uhr ist:
begrüße sie mit ’Guten Morgen, Frau Müller’
SONST:
begrüße sie mit ’Guten Tag, Frau Müller’

In Python sieht das so aus:

Beispiel 7.3.14 Verschachtelte Entscheidungen (Python-Code)


if geschlecht == ’m’:
if std < 12:
print(’Guten Morgen, Herr Müller’)
else:
print(’Guten Tag, Herr Müller’)
else:
if std < 12:
print(’Guten Morgen, Frau Müller’)
else:
print(’Guten Tag, Frau Müller’)

Und auch hier sollte man noch mal einen genießerischen Blick auf die Ähnlichkeit des Pseudocodes
und des Python-Codes werfen!
Auch wenn es einigen Lesern überflüssig erscheint, muss hier kurz auf den Begriff Bedingung“ ein-

gegangen werden. Eine Bedingung ist eine Aussageform, die entweder den Wert WAHR“ oder den

Wert FALSCH“ annehmen kann. In Python wird durch True der Wert WAHR“, durch False der
” ”
Wert FALSCH“ angegeben. Beachte hierbei die Groß-/Kleinschreibung der Wahrheitswerte in Python!

148
KAPITEL 7. PROGRAMMSTRUKTUREN 7.3. WENN . . . DANN: DIE ALTERNATIVE

7.3.4. Beispiele zu Bedingungen


Trotzdem kommen hier noch einige Code-Beispiele zu Bedingungen. Dabei formuliere ich immer die
Bedingung, gebe in Abhängigkeit von dem Wahrheitswert der Bedingung einen beschreibenden Satz
aus und zusätzlich noch den Wahrheitswert.

Beispiel 7.3.15 Beispiele für Vergleiche auf Gleichheit


>>> z1 = 3
>>> z2 = 5
>>> z3 = 7 - 4
>>> if z1 == z2:
... print(z1, ’ = ’, z2)
... print(z1 == z2)
... else:
... print(z1, ’ != ’, z2)
... print(z1 != z2)
...
3 != 5
True

>>> if z1 == z3:
... print(z1, ’ = ’, z3)
... print(z1 == z3)
... else:
... print(z1, ’ != ’, z3)
... print(z1 != z3)
...
3 = 3
True

>>> t1 = ’gut’
>>> t2 = ’schoen’
>>> if t1 == t2:
... print(t1, ’ = ’, t2)
... print(t1 == t2)
... else:
... print(t1, ’ != ’, t2)
... print(t1 != t2)
...
gut != schoen
False

Das ist vermutlich leicht nachzuvollziehen. Also kommen hier entsprechende Vergleiche auf größer“

und kleiner“

149
KAPITEL 7. PROGRAMMSTRUKTUREN 7.3. WENN . . . DANN: DIE ALTERNATIVE

Beispiel 7.3.16 Beispiele für Vergleiche auf größer und kleiner


>>> z1 = 3
>>> z2 = 5
>>> if z1 > z2:
... print(z1, ’ größer als ’, z2)
... print(z1 == z2)
... else:
... print(z1, ’ nicht größer als ’, z2)
... print(z1 > z3)
...
3 nicht größer als 3
False
>>> if z1 < z2:
... print(z1, ’ < ’, z2)
... z1 < z2
... else:
... print(z1, ’ nicht kleiner als ’, z2)
... print(z1 < z2)
...
3 < 5
True

Nachdem man das gelesen und verstanden hat, sollte man auf der Python-Shell oder in Idle ähnliche
Dinge probieren.
Nur eine kleine Selbstverständlichkeit sollte hier am Rande erwähnt werden: das Gegenteil von größer“

ist NICHT kleiner“!! Das Gegenteil von größer“ ist nicht größer“, oder anders gesagt: das Gegenteil
” ” ”
von größer“ ist kleiner oder gleich“!!
” ”

[Link]. Kurzschlüsse

Kurzschlüsse in der Elektrik sind schlecht. In der Programmierung sind Kurzschlüsse oft erlaubt, manch-
mal sinnvoll, sie machen Programmcode kürzer ... aber sie machen Programmcode nicht immer verständlicher.
Auch bei der Alternative gibt es die Möglichkeit des Kurzschlusses. Dazu kommt hier zuerst das
ausführliche Beispiel. Inzwischen verstehst Du dieses Beispiel ohne weitere Kommentare:

Beispiel 7.3.17 Vergleich und Bewertung ausführlich


>>> schuhgroesse = 48
>>> if schuhgroesse > 45:
... print(’Das sind keine Schuhe, sondern kleine Boote’)
... else:
... print(’Das sind keine Boote!!’)
...
Das sind keine Schuhe, sondern kleine Boote
>>> schuhgroesse = 43
>>> if schuhgroesse > 45:
... print(’Das sind keine Schuhe, sondern kleine Boote’)
... else:
... print(’Das sind keine Boote!!’)
...
Das sind keine Boote!!

Verständlich, ordentlich, aber ein bißchen viel Schreibarbeit. Kurzschlüsse machen es kürzer!

150
KAPITEL 7. PROGRAMMSTRUKTUREN 7.3. WENN . . . DANN: DIE ALTERNATIVE

Beispiel 7.3.18 Vergleich und Bewertung mit Kurzschluss


>>> sg = 48
>>> print(’Das sind keine ’,(sg > 45 and ’Schuhe, sondern Boote’) or ’ Boote!!’)
Das sind keine Boote!!
>>> sg = 48
>>> print(’Das sind keine ’,(sg > 45 and ’Schuhe, sondern Boote’) or ’ Boote!!’)
Das sind keine Schuhe, sondern Boote

Die beiden Texte ’Schuhe, sondern kleine Boote’ und ’Boote!!’ haben jeweils den boole’schen Wert
True. Der Ausdruck in der Klammer ist also dann wahr, wenn sg größer als 45 ist, und dann wird der
erste Text (der vor dem or) ausgegeben, falls sg nicht größer als 45 ist, ist der Ausdruck in der Klammer
falsch und der zweite Text (der nach dem or) wird ausgegeben.

7.3.5. Beispiel für eine Mehrfach-Entscheidung

Da sich Programmiersprachen an die englische Sprache anlehnen, sind die Schlüsselwörter der engli-
schen Sprache entnommen. Das obige umgangssprachliche Beispiel ließe sich in Python so formulieren.
Beachte dabei, dass als Abschluss der Bedingung so wie im umgangssprachlichen Text ein Doppelpunkt
steht.
Wie sieht es aber aus, wenn ich mehrere Möglichkeiten zur Auswahl habe? Guten Morgen, guten Tag,
guten Abend, gute Nacht!

Beispiel 7.3.19 Mehrere Möglichkeiten


if stunde < 10:
print(’Guten Morgen’)
else:
if stunde < 18:
print(’Guten Tag’)
else:
if stunde < 21:
print(’Guten Abend’)
else:
if stunde <24:
print(’Gute Nacht ’)
else:
print(’Wie bitte? Was sagt man denn nach Mitternacht? ’)

Wenn man eine solche Mehrfachentscheidung treffen muss, gibt es eine Faustregel: arbeite entweder
von groß“ nach klein“ oder von klein“ nach groß“, aber vermische nie die Vorgehensweisen. Das
” ” ” ”
führt zu logischen Fehlern, die man im Moment des Schreibens (vor allem, wenn man noch nicht so viel
Erfahrung mit dem Schreiben solcher Anweisungen hat) aber gar nicht merkt. Als Gegenbeispiel mische
ich das obige Beispiel nur ein wenig durch:

151
KAPITEL 7. PROGRAMMSTRUKTUREN 7.3. WENN . . . DANN: DIE ALTERNATIVE

Beispiel 7.3.20 Mehrere Möglichkeiten, die schief gehen


if stunde < 10:
print(’Guten Morgen’)
else:
if stunde < 18:
print(’Guten Tag’)
else:
if stunde <24:
print(’Gute Nacht ’)
else:
if stunde < 21:
print(’Guten Abend’)
else:
print(’Wie bitte? Was sagt man denn nach Mitternacht? ’)

Gehen wir das also mal in Handarbeit durch, für den Fall, dass die Variable stunde den Wert 19 hat:

1. beim ersten if stellt Python fest, dass der Wert größer als 10 ist, also wird nicht in das erste print
(den Guten Morgen“) verzweigt, es wird also nichts ausgegeben

2. beim zweiten if stellt Python fest, dass der Wert größer als 18 ist, also wird nicht in das zweite
print (den Guten Tag“) verzweigt, es wird also nichts ausgegeben

3. beim dritten if stellt Python fest, dass der Wert kleiner als 24 ist, also wird in das dritte print (die
Gute Nacht“) verzweigt, es wird also Gute Nacht“ ausgegeben, obwohl hier der Guten Abend“
” ” ”
angebracht wäre
Außer bei der Programmierung gibt das vor allen Dingen bei unseren Kindern richtig Ärger: Es

ist doch noch gar nicht so spät, und ich will doch noch den Tatort im Fernsehen schauen und
überhaupt ist das unfair!“

4. das vierte if wird nämlich gar nicht mehr überprüft, weil das Programm ja schon eine korrekte
Entscheidung getroffen hat. Dann hört es auf zu vergleichen!

Du siehst: durch ein Nichteinhalten einer natürlichen Reihenfolge wird hier eine Bedingung bejaht, die
eigentlich verneint werden müsste.

7.3.6. So sehen Mehrfachentscheidungen schöner aus!


Das oben stehende Beispiel sieht aber nicht schön aus5 . Die in zwei aufeinanderfolgenden Zeilen ste-
henden

else:
if

geben ja eine logische Ebene an. Der else-Zweig hat als erstes Konstrukt eine weitere Bedingung. Die
auf dieses else folgende Anweisung ist, zusammen mit der oben drüber stehenden Anweisung und
den darunter stehenden im Prinzip eine Auswahl unter mehreren Möglichkeiten. Deswegen gibt es in
Python ein zusammengezogenes else if, nämlich das elif. Das obige Beispiel sieht besser so aus:

5 Wie oft habe ich das wohl schon geschrieben? Aber es ist wirklich so: wenn etwas nicht schön aussieht, dann ist es auch
meistens nicht schön programmiert, und dann kann man das Programm (auf jeden Fall in Python!) ästhetischer schreiben,
damit besser lesbar. Und das ist auch meistens die bessere Lösung.

152
KAPITEL 7. PROGRAMMSTRUKTUREN 7.3. WENN . . . DANN: DIE ALTERNATIVE

Beispiel 7.3.21 Verschachtelte Entscheidungen mit elif


if stunde < 10:
print(’Guten Morgen’)
elif stunde < 18:
print(’Guten Tag’)
elif stunde < 21:
print(’Guten Abend’)
elif stunde <24:
print()’Gute Nacht ’)
else:
print(’Wie bitte? Was sagt man denn nach Mitternacht? ’)

Es ist im Übrigen guter Stil, und man ist damit auch auf der sicheren Seite, wenn man eine solche
Mehrfachauswahl mit einem else abschließt, damit auch alle vorher nicht ausdrücklich aufgelisteten
Fälle behandelt werden. Meistens ist der Programmierer nämlich froh, wenn das Programm mit den Da-
ten, die er sich vorstellt, korrekt funktioniert, und er denkt nicht an alle unmöglichen“ Möglichkeiten,

auf die ein Anwender kommt.

7.3.7. Ein Trick für verschachtelte Entscheidungen


Und auch das ist noch nicht die elegante Variante. Leider steht aber in Python keine switch- oder case-
Anweisung zur Verfügung wie in vielen anderen Programmiersprachen. Dafür gibt es aber Dictionaries.
Das soll eine Mehrfach-Auswahl ersetzen? Doch, das geht wirklich!

Beispiel 7.3.22 Verschachtelte Entscheidungen getrickst mit Dictionary


preise = {’Milch’:1.20, ’Apfelsaft’:1.50, ’Orangensaft’:1.60, ’Cola’:2.20}

getraenk = input(’Bitte Getränk eingeben (Milch/Apfelsaft/


Orangensaft/Cola)’
print(preise[getraenk])

ist gleichwertig zu

Beispiel 7.3.23 Verschachtelte Entscheidungen zu Fuß


getraenk = input(’Bitte Getränk eingeben (Milch/Apfelsaft/
Orangensaft/Cola)’
if getraenk == ’Milch’:
print(1.20)
elif getraenk == ’Apfelsaft’:
print(1.50)
elif getraenk == ’Orangensaft’:
print(1.60)
elif getraenk == ’Cola’:
print(2.20)

Die erste der beiden oben stehenden Varianten besticht durch ihre Kürze. Die zweite Variante ist dafür
einfacher auf eine fehlerhafte Eingabe zu erweitern:

153
KAPITEL 7. PROGRAMMSTRUKTUREN 7.3. WENN . . . DANN: DIE ALTERNATIVE

Beispiel 7.3.24 Verschachtelte Entscheidungen zu Fuß mit Fehlerbehandlung


getraenk = input(’Bitte Getränk eingeben (Milch/Apfelsaft/
Orangensaft/Cola)’
if getraenk == ’Milch’:
print(1.20)
elif getraenk == ’Apfelsaft’:
print(1.50)
elif getraenk == ’Orangensaft’:
print(1.60)
elif getraenk == ’Cola’:
print(2.20)
else:
print(’fehlerhafte Eingabe’)

Um das mit Hilfe eines Dictionary zu erledigen, muss man die get“-Methode von strukturierten

Daten benutzen.

Beispiel 7.3.25 das selbe mit Dictionary


preise = {’Milch’:1.20, ’Apfelsaft’:1.50, ’Orangensaft’:1.60, ’Cola’:2.20}

getraenk = input(’Bitte Getränk eingeben (Milch/Apfelsaft/


Orangensaft/Cola)’
print([Link](getraenk, ’falsche Eingabe’))

Die get-Methode erlaubt als zweiten Parameter einen Default-Wert, der hier auf falsche Eingabe“

gesetzt wurde.

7.3.8. Aufgaben zu Auswahl


1. In ein Programm soll der Umsatz eines Mitarbeiters eingegeben werden. Wenn der Umsatz über 30
000 e liegt, wird dem Mitarbeiter eine Prämie von 1 Prozent des Umsatzes gewährt. Diese Prämie
soll ausgegeben werden.
2. Der Eintrittspreis für die Minigolf-Anlage beträgt
• 2,50 e für Kinder und Jugendliche unter 18 Jahren
• 4,00 e für Erwachsene
Das Alter eines Spielers soll eingegeben werden, und der zu zahlende Preis soll ausgegeben wer-
den.
3. Die vorige Aufgabe wird schwerer: Der Eintrittspreis für die Minigolf-Anlage beträgt
• 2,50 e für Kinder und Jugendliche unter 18 Jahren
• 4,00 e für Erwachsene
• 3,00 e für Senioren über 65 Jahre
Das Alter eines Spielers soll eingegeben werden, und der zu zahlende Preis soll ausgegeben wer-
den.
4. Punktprobe: In ein Programm sollen Werte für die Steigung m und den y-Achsenabschnitt b einer
Geraden sowie die x-Koordinate und die y-Koordinate eines Punktes eingegeben werden. Das
Programm soll dann überprüfen, ob der Punkt auf der Geraden liegt und eine entsprechende
Meldung ausgeben.
5. Zwei-Punkte-Form der Geradengleichung: In ein Programm sollen vom Benutzer die x-Koordinaten
und y-Koordinaten von 2 Punkten eingegeben werden. Das Programm soll die Geradengleichung
in der Form y = mx + b ausgeben.

154
KAPITEL 7. PROGRAMMSTRUKTUREN 7.3. WENN . . . DANN: DIE ALTERNATIVE

6. Die Signum-Funktion gibt den Wert 1 zurück, wenn die eingegebene Zahl positiv ist, den Wert 0,
wenn die eingegebene Zahl 0 ist und den Wert -1, wenn die eingegebene Zahl negativ ist. Schreibe
ein Programm!

7. Eine einfache Prüfziffer für 7-bit-Zeichen (den Standard-ASCII) könnte so funktionieren: wenn die
Anzahl der Einsen ungerade ist, setze das 8. bit auf 1, wenn die Anzahl der Einsen gerade ist, auf
0.

8. Mitternachtsformel (oder für Nordlichter: die allgemeine Lösungsformel für quadratische Glei-
chungen) ist zu programmieren. Eingabe der Koeffizienten a, b, c der quadratischen Gleichung
ax2 + bx + c = 0 in das Programm mit Hilfe von variable = input . . .“. Ausgabe von Diskriminan-

te, Anzahl der Lösungen und gegebenenfalls der Lösungen.

9. Das Programm zur Berechnung des Body-Mass-Index aus Kapitel 4 soll dahingehend verbessert
werden, dass es eine Bewertung ausgibt. Dabei gilt, dass Frauen mit einem BMI kleiner oder gleich
19 und Männer mit einem BMI kleiner oder gleich 20 untergewichtig sind, Frauen mit einem BMI
größer oder gleich 24 und Männer mit einem BMI größer oder gleich 25 übergewichtig sind.

10. Ein Programm soll ausgeben, ob ein Jahr ein Schaltjahr ist. Beachte dabei, dass die durch 100
teilbaren Jahre keine Schaltjahre sind, außer wenn sie durch 400 teilbar sind.

11. Für die Berechnung des Wochentages hat C.F. Gauss folgende Formel aufgestellt (dabei ist die
seltsame eckige Klammer, bei der der obere Haken fehlt, das Symbol für die Gauss’sche Klam-
merfunktion, die bedeutet: größte ganze Zahl
 kleiner oder gleich als das, was in dieser Klammer
steht): w = (d + b2, 6 · m − 0, 2c + y + y4 + 4c − 2c) mod 7


Die Variablen haben folgende Bedeutung:

• d: Tagesdatum (1 bis 31)

• m: (Monatsnummer (1 bis 12) - 2 ) mod 12

• y: Die beiden letzten Stellen der Jahreszahl (für 2007 wäre diese 07 also 7)

• c: Die beiden ersten Stellen der Jahreszahl (für 2007 wäre diese 20)

• w: Wochentag gemäß unten angeführter Tabelle

7.3.9. Verknüpfte Logik-Operatoren und Reihenfolge

Fast selbstverständlich ist, dass verknüpfte logische Operationen von links nach rechts abgearbeitet
werden. Wenn ein Ausdruck wie x > 3 or x < -2 auftaucht, wird zuerst geprüft ob x > 3 ist.
Jetzt aber!!! Jetzt verhält sich Python ausgesprochen vernünftig. Weiter oben bei der XrefId[?oder-
Verknüpfung?] haben wir gesehen, dass eine ver-oderte“ Verknüpfung wahr ist, wenn ein Teil wahr

ist. Wenn x also den Wert 7 hat, dann ist der erste Teil, nämlich x > 3 wahr. Also ist es völlig egal, ob der
zweite Teil, nämlich x < -2 wahr oder falsch ist, der gesamte Ausdruck ist wahr.
Dann braucht man also nicht weiterzulesen, was mit dem zweiten Teil passiert, denn der gesamte
Ausdruck wird wahr sein. Also liest Python nicht weiter.
Das ist gut so, denn das Programm spart dadurch Zeit. Es läuft schneller! Na gut, bei einem einzel-
nen Ausdruck ist die Zeitersprarnis nicht der Rede wert, aber wenn ein Programm Hunderte solcher
Vergleiche enthält, dann merkt man das vielleicht doch. Viel wichtiger ist, dass man damit aber eine
elegante Methode hat, mögliche Fehler abzufangen.
Nehmen wir uns als Anwendung dafür die Mitternachtsformel vor. Dazu benötigt man die (Quadrat-
)Wurzel-Funktion, auf englisch die square root, als Funktion sqrt. Die steckt im Modul für Mathematik,
der import werden muss mit import math. Das Programm könnte in seiner schlichtesten Form so aus-
sehen:

155
KAPITEL 7. PROGRAMMSTRUKTUREN 7.3. WENN . . . DANN: DIE ALTERNATIVE

Beispiel 7.3.26 Mitternachtsformel


import math

print("\t\tMitternachtsformel\n\t(Lösung von quadratischen Gleichungen)")

a = float(input("Koeffizient a des quadratischen Gliedes eingeben: \t"))


b = float(input("Koeffizient b des linearen Gliedes eingeben: \t"))
c = float(input("Koeffizient c des absoluten Gliedes eingeben: \t"))

diskr = b*b - 4*a*c


print(’Die quadratische Gleichung lautet’, a, ’xˆ2 +’, b, ’x +’,c, ’= 0’)
print(’Die Diskriminante der quadratischen Gleichung: D =’, diskr)
if diskr > 0:
print("\t2 Lösungen")
print("x1 = ",)
print( (-b + [Link](diskr))/(2*a) )
print("x2 = ",)
print( (-b - [Link](diskr))/(2*a) )
elif diskr == 0:
print("1 Lösung")
print("x1/2 = ",)
print( (-b)/(2*a) )
else:
print("keine Lösung")

Das scheint zu funktionieren:

Beispiel 7.3.27 Test 1 zu Mitternachtsformel


Mitternachtsformel
(Lösung von quadratischen Gleichungen)
Koeffizient a des quadratischen Gliedes eingeben: 1
Koeffizient b des linearen Gliedes eingeben: -5
Koeffizient c des absoluten Gliedes eingeben: 6
Die quadratische Gleichung lautet 1 xˆ2 + -5 x + 6 = 0
Die Diskriminante der quadratischen Gleichung: D = 1
2 Lösungen
x1 = 3.0
x2 = 2.0

Beispiel 7.3.28 Test 2 zu Mitternachtsformel


Mitternachtsformel
(Lösung von quadratischen Gleichungen)
Koeffizient a des quadratischen Gliedes eingeben: 1
Koeffizient b des linearen Gliedes eingeben: 1
Koeffizient c des absoluten Gliedes eingeben: 1
Die quadratische Gleichung lautet 1 xˆ2 + 1 x + 1 = 0
Die Diskriminante der quadratischen Gleichung: D = -3
keine Lösung

Es scheint alles in Ordnung zu sein!

156
KAPITEL 7. PROGRAMMSTRUKTUREN 7.3. WENN . . . DANN: DIE ALTERNATIVE

Beispiel 7.3.29 Test 3 zu Mitternachtsformel


Mitternachtsformel
(Lösung von quadratischen Gleichungen)
Koeffizient a des quadratischen Gliedes eingeben: 0
Koeffizient b des linearen Gliedes eingeben: 2
Koeffizient c des absoluten Gliedes eingeben: 5
Die quadratische Gleichung lautet 0 xˆ2 + 2 x + 5 = 0
Die Diskriminante der quadratischen Gleichung: D = 4
2 Lösungen
x1 =
Traceback (most recent call last):
File "./[Link]", line 18, in <module>
print( (-b + [Link](diskr))/(2*a) )
ZeroDivisionError: float division by zero

Da wollte jemand also den absoluten Härtetest machen, und ausprobieren, ob unser tolles Programm
auch die Nullstelle einer linearen Funktion berechnen kann, also hat er einfach für den Koeffizienten
a eine 0 eingegeben. Wenn man sich den Quelltext weiter oben nochmal anschaut (oder noch besser:
wenn man weiß, dass in der Mitternachtsformel durch 2 * a geteilt werden muss), dann ist klar, dass
ein Fehler auftaucht.
Es ist aber relativ einfach, diesen Fehler abzufangen, d.h. zu verhindern, dass eine fehlerhafte Eingabe
wie oben das Programm abbrechen lässt, wenn man das oben gesagte über vernüpfte Logik-Operatoren
nochmals liest und sich dann erinnert, dass ein mit und“ verknüpfter logischer Ausdruck nur dann

wahr ist, wenn beide Teile wahr sind. Also fragt man einfach an den kritischen Stellen nicht nur den Wert
der Diskriminante ab, sondern zuerst den Wert des Parameters a. Ich nenne das Vorgehen Aufpasser“,

weil diese zusätzliche Abfrage aufpasst, dass die kritische Variable einen sinnvollen Wert enthält. Also
sieht das so aus:

Beispiel 7.3.30 Mitternachtsformel mit Aufpasser“



import math

print("\t\tMitternachtsformel\n\t(Lösung von quadratischen Gleichungen)")

a = float(input("Koeffizient a des quadratischen Gliedes eingeben: \t"))


b = float(input("Koeffizient b des linearen Gliedes eingeben: \t"))
c = float(input("Koeffizient c des absoluten Gliedes eingeben: \t"))

diskr = b*b - 4*a*c


print(’Die quadratische Gleichung lautet’, a, ’xˆ2 +’, b, ’x +’,c, ’= 0’)
print(’Die Diskriminante der quadratischen Gleichung: D =’, diskr)
if a != 0 and diskr > 0:
print("\t2 Lösungen")
print("x1 = ",)
print( (-b + [Link](diskr))/(2*a) )
print("x2 = ",)
print( (-b - [Link](diskr))/(2*a) )
elif a != 0 and diskr == 0:
print("1 Lösung")
print("x1/2 = ",)
print( (-b)/(2*a) )
else:
print("keine Lösung")

157
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

In den beiden Zeile mit den Bedingungen, also den Zeilen die mit if bzw. mit elif beginnen, steht
jetzt also vorne die Abfrage, ob a ungleich 0 ist. Und jetzt passiert nichts schlimmes mehr:

Beispiel 7.3.31 Test 3 zu Mitternachtsformel


>>> Mitternachtsformel
(Lösung von quadratischen Gleichungen)
Koeffizient a des quadratischen Gliedes eingeben: 0
Koeffizient b des linearen Gliedes eingeben: 1
Koeffizient c des absoluten Gliedes eingeben: 4
Die quadratische Gleichung lautet 0 xˆ2 + 1 x + 4 = 0
Die Diskriminante der quadratischen Gleichung: D = 1
keine Lösung

Klar? Wenn a den Wert 0 hat, ist der erste Teil des mit und“ verknüpften Ausdrucks falsch, damit ist

der ganze Ausdruck falsch, und damit wird dieser Ausdruck nicht weiter untersucht. Also wird auch
gar nicht versucht, durch 0 zu dividieren, und alles ist in bester Ordnung. Zugegeben, das ist noch nicht
die absolut anwenderfreundliche Kommunikation des Programms, aber schon ein ganzes Stück besser,
als mit einer Fehlermeldung abzubrechen.

7.4. Schleifen
God knows when
But you’re doin’ it again
(Bob Dylan 6 )
Lies noch einmal nach, was weiter oben über gute Programme geschrieben wurde. Ein Programm der
Art (das ist kein Python-Programm, sondern nur Pseudocode!)

Beispiel 7.4.1 so nicht!


programmieranweisung_fuer_den_wert_1
programmieranweisung_fuer_den_wert_2
programmieranweisung_fuer_den_wert_3

geht also gar nicht. Mehrmals die selbe Anweisung, nur mit verschiedenen Werten: das muss zu
vereinfachen sein.
Jetzt geht es also um die Wiederholung von einer Anweisung oder einer ganzen Gruppe von An-
weisungen. Endlich lohnt sich das Programmieren! Ganz allgemein kann man das Problem auch so
umschreiben: hier ist eine Menge von Dingen; mach für jedes von ihnen das selbe (oder etwas sehr
ähnliches).
Eine solche Wiederholung, Schleife genannt, kann prinzipiell auf zwei Arten realisiert werden:

• Man gibt die Anzahl der Wiederholungen an. In diesem Fall spricht man von einer Zählschleife.
In der Programmierung nennt man das eine for-Schleife“.

• Man weiß nicht genau, wie oft etwas wiederholt werden soll, sondern man kann nur angeben,
wann man mit der Wiederholung aufhören soll. Anders gesagt, man kennt die Abbruchbedingung
für die Wiederholung. Dies wird als while-Schleife“ programmiert.

Diese beiden Arten sollen noch an einem Beispiel verdeutlicht werden: es sollen alle Zahlen von 1 bis
100 ausgedruckt werden. Hier folgt die Realisierung, so wie wir sie mit den bisherigen Mitteln erreichen
könnten:
6 Subterranean Homesick Blues auf: Bringing It All Back Home

158
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

Beispiel 7.4.2 Die (umgangssprachlich) ersten 100 natürlichen Zahlen ausgeben


print(1)
print(2)
print(3)
...
print(99)
print(100)

(Im Titel des Beispiels steht umgangssprachlich, weil für den Mathematiker die ersten 100 natürlichen
die Zahlen von 0 bis 99 sind.) Das funktioniert. Aber das ist nicht schön, kein Mensch wollte so etwas
schreiben, es ist fehleranfällig, kurz: so nicht! Die erste oben beschriebene Art, dieses Problem zu lösen,
nämlich in einer Zählschleife, sieht in Pseudocode so aus:

Beispiel 7.4.3 Zählschleife im Pseudocode


für jede Zahl i aus der Menge (1 ... 100)
drucke i

Nicht schlecht: statt 100 Zeilen Programmcode sind das 2 Zeilen Pseudocode. Und wir werden sehen:
daraus werden nach der Übersetzung einiger Schlüsselwörter auch genau 2 Zeilen Python-Code.

Beispiel 7.4.4 Die selbe Zählschleife in Python


for i in range(1,101):
print(i)

Die zweite oben beschriebene Art, dieses Problem zu lösen, nämlich in einer Schleife mit Abbruchbe-
dingung, sieht in Pseudocode so aus:

Beispiel 7.4.5 Schleife mit Abbruchbedingung im Pseudocode


i = 1
solange zahl <= 100
drucke i
i = i + 1

Auch nicht schlecht: die 100 Zeilen Programmcode von oben sind zu 4 Zeilen Pseudocode geschrumpft.
Das wird auch wieder zu 4 Zeilen Python-Code, und zwar genauso einfach wie bei der Zählschleife.
Allerdings kann man hier schon eine Faustregel festhalten, wenn man die Faust aufmacht und die
Finger nachzählt: 4 ist doppelt so viel wie 2! Die Faustregel lautet: wenn Du etwas in einer Zählschleife
oder in einer Schleife mit Abbruchbedingung erledigen kannst, dann nimm die Zählschleife. Die ist
kürzer und besser verständlich!

159
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

7.4.1. Zähl-Schleifen

5,4,3,2,1
Cassius Clay you’d better run
99, 100, 101, 102
Your mother won’t even recognize you

—Bob Dylan 7

Behandeln wir also zuerst die Zählschleife. In Python stellt man sich diese Art von Schleifen so vor:
hier bekommst Du (die Schleife) eine Menge von Dingen, und mit jedem dieser Dinge mach etwas. Das
kann eine Menge von Zahlen, eine Menge von Namen, eine Menge von irgendwelchen Objekten sein.
Bei einer Zählschleife gibt es eine Variable, die Buch darüber führt, wie oft etwas gemacht werden
soll und wo man denn schon steht. Wenn die Menge von Dingen Zahlen sind, wird eine solche Variable
Zähler“ genannt. Einem solchen Zähler muss man mitteilen,

1. was der Anfangswert der Zählung sein soll,
2. was der Endwert sein soll und
3. mit welcher Schrittweite gezählt werden soll.
Eine Möglichkeit, über eine Menge von Zahlen zu schleifen, ist mittels des range-Objekts.8 Ein
range-Objekt ist eine Konstruktionsvorschrift, die beim Aufruf jeweils das nächste Element erzeugt.
Das range-Objekt wird erzeugt, indem ihm
1. entweder der Endwert als Parameter
2. oder der Anfangswert und der Endwert
3. oder der Anfangswert, der Endwert und die Schrittweite
übergeben werden.
Das englische Wort range“ bedeutet Bereich. Wenn nur ein Wert angegeben ist, wird als Standard-

Startwert die 0“ angenommen. Das freut den Mathematiker, denn die natürlichen Zahlen fangen bei

0“ an. Ebenso wird angenommen, dass der dritte Wert, die Schrittweite, wenn er nicht angegeben ist,

1“ ist. Außerdem sieht man im unten stehenden Beispiel, dass der bereichx (mit x ∈ {1; 2; 3} ) ein

Objekt ist, das eine Konstruktionsbeschreibung für eine Liste enthält. Mit print wird diese Konstruk-
tionsbeschreibung ausgeben, mit list wird die Liste erzeugt.

Beispiel 7.4.6 range (Bereich)


>>> bereich1 = range(16)
>>> print(bereich1)
range(0, 16)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
>>> list(bereich1)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
>>> bereich2 = range(3,12)
>>> list(bereich2)
[3, 4, 5, 6, 7, 8, 9, 10, 11]
>>> bereich3 = range(1,25,2)
>>> print(bereich3)
range(1, 25, 2)
>>> list(bereich3)
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23]

Der einfachste Fall in Python ist


7I shall be free No. 10 auf: Another Side of
8 In Python 2.x war range eine Funktion und erzeugte eine Liste. Das war ungünstig, wenn range einen großen Bereich um-
fasste: die Liste wurde sehr lang und belegte folglich viel Speicherplatz.

160
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

Beispiel 7.4.7 Zählschleife


>>> for zahl in range(4):
print(zahl)

In der folgenden Tabelle wird gegenübergestellt, wie sich ein einfacher Algorithmus, der in der lin-
ken Spalte in Pseudocode“ beschrieben ist, fast eins zu eins in Python übertragen lässt. Das ist das

Beispiel vom Anfang des Kapitels. Auch hier gilt wieder: wer das Problem richtig durchdenkt und klar
formuliert, der schreibt das dazugehörige Python-Programm sehr schnell.

Tabelle 7.5. Pseudocode und Python-Code


Pseudocode Python-Code
für jede Zahl i aus der Menge (1 ... 100) for i in range(1,101):
drucke i print(i)

Hier finden wir wieder die Einrückung, die wir aus dem Kapitel über die Alternative kennen. Der
Aufruf der print-Funktion ist abhängig von der Zählung; also muss er eingerückt werden und das,
wovon abhängig ist, wird durch einen Doppelpunkt abgeschlossen. Das sollte man jetzt, sofern man
vor seinem Rechner sitzt, selber probieren.

Beispiel 7.4.8 Einfache Zählschleife


>>> for zahl in range(4):
print(zahl)
0
1
2
3

W ICHTIG
Zwei Sachen muss man hier beachten. Zum einen startet die Zählung bei 0. Aber
das sind wir ja schon fast gewohnt. Zum anderen gilt hier wie beim Slicing von
Zeichenketten, dass der Anfangswert mit ausgegeben wird, der Endwert jedoch
nicht.

Jetzt probieren wir gleich etwas mehr aus, indem wir der range 2 Werte mitgeben. Werte werden
durch Kommata voneinander getrennt, wohingegen das deutsche Dezimalkomma in englischsprachi-
gen Ländern zum Dezimalpunkt wird.

Beispiel 7.4.9 Zählschleife mit Anfang und Ende


>>> for zahl in range(5,8):
print(zahl)
5
6
7

Man sieht: der erste Wert gibt den Anfang der Zählung, der zweite das Ende der Zählung an.

161
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

Nur Mut: range bekommt jetzt 3 Werte beigefügt

Beispiel 7.4.10 Zählschleife mit Anfang, Ende und Schrittweite


>>> for zahl in range(3,20,4):
print(zahl)
3
7
11
15
19

Der dritte Wert gibt also die Schrittweite an. Also können wir endlich der NASA behilflich sein, und
das Countdown-Programm schreiben:

Beispiel 7.4.11 Countdown


>>> for zahl in range(10,0,-1):
print(zahl)
10
9
8
7
6
5
4
3
2
1

Da nicht nur Zahlen gezählt werden können, wie wir inzwischen wissen, sondern auch Listen(-
Elemente), kann man auch über Listen schleifen:

Beispiel 7.4.12 Schleifen über Listen


>>> kurzeListe = [’Karl’,’Egon’,’Uwe’,’Sepp’]
>>> for wort in kurzeListe:
print(wort)
Karl
Egon
Uwe
Sepp

Mit den beiden Sprachelementen aus den letzten beiden Absätzen kann man sich nochmal veran-
schaulichen, wie die Hausnummern mit den Elementen zusammenhängen. Im folgenden Code-Segment
wird die Hausnummer und das Element jeweils ausgegeben:

162
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

Beispiel 7.4.13 Länge einer Liste


>>> zliste = [1,2,3,4,5,6]
>>> for index in range(len(zliste)):
print(index, zliste[index])

0 1
1 2
2 3
3 4
4 5
5 6

Alles klar? Die Länge der Liste ist 6, die range, geht also genau von 0 bis 5, und das sind die Haus-
nummern der Elemente der Liste. Jetzt hat wahrscheinlich jeder verstanden, warum es

1. sinnvoll ist, von 0 ab zu zählen

2. dass das Endelement einer range nicht mehr mit bearbeitet wird

Zählschleifen können aber auch benutzt werden bei Strukturen wie Zeichenketten, denn eine Zeichen-
kette ist (siehe oben bei String als Feld) im Prinzip nichts anderes als ein Feld, das durchnummeriert ist,
und das man deswegen abzählen kann.

Beispiel 7.4.14 Schleifen über Zeichenketten


>>> name = "Martin"
>>> for buchstabe in name:
print(buchstabe)
M
a
r
t
i
n

Das ist gut, aber noch besser wäre es, wenn alles in einer Zeile stünde. Auch das ist einfach zu rea-
lisieren, denn ich muss Python nur mitteilen, dass es nach einem Aufruf von print keinen Zeilenvor-
schub machen soll. Dies geschieht dadurch, dass man der den print-Funktion als zusätzlichen Parameter
end=’ ’ mitgibt.

Beispiel 7.4.15 Schleifen über Zeichenketten


>>> name = "Martin"
>>> for buchstabe in name:
print(buchstabe, end=’’)
M a r t i n

Und hier noch ein Beispiel von der Ostalb:

163
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

Beispiel 7.4.16 Schleife mit 2 Variablen


>>> rest = "bele"
>>> anf = "ABCD"
>>> for buchst in anf:
print(buchst+rest)

Abele
Bbele
Cbele
Dbele

Als letztes Beispiel soll hier, wieder in einer Gegenüberstellung von Pseudocode und Python-Code,
der (Noten-)Durchschnitt einer Klasse berechnet werden. Der Lehrer weiß zwar, dass in der Klasse 25
Schüler sind, aber aus allgemein bekannten Gründen sind bei einer Klassenarbeit nicht zwingend alle
Schüler anwesend. Trotzdem ist das kein Problem. Seien also ganz einfach alle Noten dieser Klassenar-
beit in einer Liste gespeichert notenL = [2.5, 3.6, 1.7, 4.2, 5.5, 5.2, 1.6] (ok, da fehlen
aber heute viele!!! Egal, ich bin zu faul, da mehr reinzuschreiben, und das Programm soll auch funktio-
nieren, gleich wieviele Elemente in der Liste sind).

Tabelle 7.6. Notendurchschnitt: Pseudocode und Python-Code


Pseudocode Python-Code
setze Anzahl der Schueler 0 anzSchueler = 0
setze Summe der Noten 0 notenSumme = 0
Noten sind in Listen-Variable notenL notenL = [2.5,3.6,1.7,4.2,5.5,5.2,1.6]
für jede Note aus der Notenliste for note in notenL:
zähle Anzahl Schüler hoch anzSchueler += 1
addiere Note zur Notensumme notenSumme += note
Durchschn. = Noten-Summe / Anz. Schüler durchschn = notenSumme / anzSchueler
drucke Durchschnitt aus print(’Durchschnitt = ’, durchschn)

Das Programm ist gut! Mit einer überschaubaren (sogar endlichen) Anzahl von Programmzeilen kann
ich eine nicht mehr so gut überschaubare Anzahl von Daten bearbeiten. Umgangssprachlich würde man
wohl behaupten, dass die Notenliste unendlich viele Noten enthalten könnte, als Mathematiker muss
man natürlich genau sein und sagen, dass die Notenliste beliebig lang sein kann. Ich habe sogar mehr
erreicht, als ich ursprünglich vorhatte. Die erste Idee war, dass in der Notenliste immer die Noten aller
Schüler stehen, dass die Länge der Liste also fest ist. Python ist aber in der Lage, mit einfachen Mitteln
eine Liste beliebiger Länge abzuarbeiten.

Weil das Mitzählen, oben durch den Zähler anzSchueler erledigt, einfach ist, aber immer wieder
benötigt wird, ist so etwas natürlich in Python integriert. Man könnte das Programm vereinfachen,
indem man die Methode len(liste) aufruft. Diese gibt die Anzahl der Elemente der Liste, hier also
die Anzahl der Schüler, die die Klassenarbeit mitgeschrieben haben, zurück.

Es fehlt aus dem Kapitel über strukturierte Daten noch das Beispiel, wie man eine Matrix schön dar-
stellt.

164
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

Beispiel 7.4.17 Darstellung einer Matrix


#!/usr/bin/python

def matrixDarst(m):
print(’ ’)
for zeile in m:
spTupel = ()
anzSpalten = len(zeile)
for spalte in zeile:
spTupel = spTupel + (spalte, )
print("%+6.4f\t"*anzSpalten % spTupel)

m = [[1, 0, 1], [-1, 2, 0], [0, -2, 1]]


matrixDarst(m)

Der Trick dabei ist, die Liste in ein Tupel zu verwandeln, das man an einen Formatstring übergibt.
Dabei wird der Formatierungsbefehl genau so oft wiederholt, wie es Anzahl Spalten gibt.
Auch Dictionaries können in einer Zähl-Schleife abgearbeitet werden, allerdings ist hierbei nicht klar,
in welcher Reihenfolge. Das kann aber manchmal ganz geschickt sein, zum Beispiel, wenn man ein
Ratespiel programmiert. Dieses Spiel hier hilft vielleicht beim Vokabellernen. Es gibt den englischen
Begriff aus und fragt die deutsche Übersetzung ab:

Beispiel 7.4.18 Ein kleines Quiz


#!/usr/bin/python
# -*- coding: utf-8 -*-
englDeutsch = {’dog’:’Hund’, ’cat’:’Katze’, ’cow’:’Kuh’, ’sheep’:’Schaf’}
punkte = 0
for tier in englDeutsch:
eingAufforderung = "Wie heisst ", tier, " auf deutsch?"
dTier = input(eingAufforderung)
if englDeutsch[tier] == dTier:
punkte = punkte + 1
print("Gut!!")
else:
print("so nicht")

print("Du hast ", punkte, " richtige Antworten")

Das Spiel könnte noch dadurch erweitert werden, dass es hinzulernt, etwa dadurch, dass ein Begriff,
der noch nicht im Dictionary enthalten ist, weil eine falsche Antwort gegeben wurde, eingefügt wird.
Eine nette Übungsaufgabe!

[Link]. Mitzählen in einer Zählschleife

Manchmal ist es wünschenswert, dass Python sein Wissen, bei dem wievielten Element innerhalb einer
Zählschleife es sich gerade befindet, nicht für sich behält, sondern ausgibt. Dazu dient die Funktion
enumerate. Als Beispiel wird hier eine Liste von Namen genommen, bei der durch eine Zählschleife
nicht nur der Name, sondern auch die Position des Namens in der Liste ausgegeben werden soll.

165
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

Beispiel 7.4.19 Zählschleife mit Zähler


#!/usr/bin/python

namensListe = [’Eva’, ’Klaus’,’Bernd’, ’Mia’, ’Anna’, ’Paulo’, ’Pia’]


for zaehler, name in enumerate(namensListe):
print(’%d. Person: %s’ % (zaehler+1, name))
>>> 1. Person: Eva
2. Person: Klaus
3. Person: Bernd
4. Person: Mia
5. Person: Anna
6. Person: Paulo
7. Person: Pia

Ein ähnliches Problem ist, dass ich in einer Schleife zwei Sachen machen will: rechnen und zählen.
Ein Beispiel: ich habe eine Liste mit Zahlen und ich will zum einen wissen, wie lang die Liste ist, und
zum anderen, wie groß die Summe der Zahlen in der Liste ist.

Beispiel 7.4.20 Zählen und rechnen


>>> liste = [1,2,3,4]
>>> anz = 0
>>> sum = 0
>>> for i in liste:
... (anz,sum) = (anz+1, sum+i)
...
>>> print(anz, sum)
4 10

Hier benutze ich, dass Python in einer Anweisung mehrere Wertzuweisungen machen kann.

7.4.2. While-Schleifen
Oft soll aber nicht gezählt geschleift“ werden, sondern man soll einen Block von Anweisungen solange

wiederholen, bis eine bestimmte Bedingung erreicht ist. Um wieder den Vergleich eines Algorithmus
mit einem Kochrezept hervorzuholen: da gibt es so etwas sehr häufig:

Beispiel 7.4.21 Solange-Schleife im Kochrezept


so lange die Fruchtmasse noch nicht sprudelnd kocht
weiter köcheln
weiter umrühren

Der Programm-Code für solche Schleifen sieht wie folgt aus:

Beispiel 7.4.22 While-Schleife


>>> while (eingabe != ’Ende’):
machWas

166
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

Auch hier wird in einer Tabelle gegenübergestellt, wie das einfache Beispiel vom Anfang des Kapitels
in Pseudocode und in Python ausgedrückt wird. Der Algorithmus, der in der linken Spalte in Pseudo-

code“ beschrieben ist, kann fast eins zu eins nach Python übertragen werden.

Tabelle 7.7. Pseudocode und Python-Code


Pseudocode Python-Code
i = 1 i = 1
solange zahl <= 100 while i < 100:
drucke i print(i)
i=i+1 i=i+1

Das hier beschriebene Programm-Segment ist ein typischer Fall für eine While-Schleife. Einen Pro-
grammablauf kann man so steuern:

Beispiel 7.4.23 Menu-Auswahl


while eingabe != ’e’:
eingabe = input(’Was willst Du? m für mehr, w für weniger, e für Ende’)
if eingabe == ’m’:
machmehr
elif eingabe == ’w’:
machweniger
elif eingabe == ’e’:
pass # für e muss man gar nichts machen; wenn das Programm zum
# nächsten Mal zur Überprüfung der While-Bedingung kommt,
# wird die Schleife einfach nicht mehr durchlaufen
else:
print(’fehlerhafte Eingabe; nur m, w, e sind erlaubt’)

pass ist eine Anweisung, die Python auffordert, nichts zu machen. Das ist manchmal sehr sinn-
voll, denn wie in dem obigen Beispiel will (oder soll) man alle möglichen Eingaben in ein Programm
berücksichtigen, aber in diesem einen Fall einer korrekten Eingabe nichts machen. Eine andere Anwen-
dung für die pass-Anweisung ist, dass man bei einem längeren Projekt einen möglichen Programm-
zweig noch nicht programmiert hat. Die Alternative zu der Anweisung pass ist die Anweisung ....
Eine gute Vereinbarung mit sich selbst könnte lauten:
• pass verwende ich, wenn hier wirklich nichts passieren soll. Nie!!!
• ... verwende ich, wenn ich im Laufe der Entwicklung hier noch etwas schreiben werde
Man zeigt an, dass hier etwas passieren wird, indem man die Möglichkeit öffnet, aber man schreibt die
leere Anweisung hin, weil man noch nicht weiß, was passieren wird.
Ein anderer klassischer Fall für eine While-Schleife ist das Lesen einer Datei. Da bisher noch keine
Datei-Behandlung besprochen wurde, wird der Programmcode nicht in Python, sondern in Pseudocode
wiedergegeben:

while nochEtwasVorhanden:
liesEinZeichen
if keinZeichenMehr:
dannHoerHaltAufMitLesen

7.4.3. Verschiedene Probleme und ihre Lösung mittels Schleifen


Bei vielen dieser Probleme ist eine Menge von Dingen gegeben, die mit Hilfe einer Schleife durchsucht
werden muss, wobei aus dieser Menge bei einigen dieser Probleme etwas herausgefiltert werden soll.
Die Menge ist oft als eine Liste, manchmal als ein Dictionary gegeben.

167
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

[Link]. Listen oder Dictionaries durch eine Art Liste erzeugen (list comprehensions)
List comprehensions sind Ausdrücke, die aus einer Kombination von Listen und Schleifen bestehen, um
daraus eine neue Liste zu machen. Als einfaches Beispiel soll eine Liste aller Quadratzahlen zwischen 0
und 100 erstellt werden, das Ergebnis unserer Arbeit soll also q = [0,1,4,9,16,25,36,49,64,81]
sein. Natürlich könnte man für eine solch einfache Liste seinen Editor nehmen und sie von Hand erstel-
len. Aber das ist nicht schön!
Eleganter ist es, eine Liste zu schreiben, die einen Ausdruck enthält. Und diese Eleganz ist in Python
unübertroffen:

Beispiel 7.4.24 Liste von Quadratzahlen (list comprehension)


>>> q = [x**2 for x in range(10)]
>>> q
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

q ist unsere neue Liste, die dadurch entsteht, dass das Quadrat jeder Zahl zwischen 0 und 10 gebildet
wird. Man kann sich die obige erste Programmzeile auch laut vorlesen: q ist die Liste aller Zahlen,
die dadurch gebildet werden, dass man nacheinander die Quadrate aller Zahlen zwischen 0 und 10
berechnet. Python ist wirklich eine schöne weil einfache Sprache.

168
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

Ein nächstes Beispiel: die Wertetabelle der natürlichen Exponentialfunktion für den Bereich von -2 bis
1:

Beispiel 7.4.25 Wertetabelle der natürlichen Exponentialfunktion


>>> from math import exp
>>> wtab = [(x/10, exp(x/10)) for x in range(-20,11)]
>>> for eintrag in wtab:
... print(eintrag[0],’\t’, eintrag[1])
...
-2.0 0.1353352832366127
-1.9 0.14956861922263506
-1.8 0.16529888822158653
-1.7 0.18268352405273466
-1.6 0.20189651799465538
-1.5 0.22313016014842982
-1.4 0.2465969639416065
-1.3 0.2725317930340126
-1.2 0.30119421191220214
-1.1 0.33287108369807955
-1.0 0.36787944117144233
-0.9 0.4065696597405991
-0.8 0.44932896411722156
-0.7 0.4965853037914095
-0.6 0.5488116360940264
-0.5 0.6065306597126334
-0.4 0.6703200460356393
-0.3 0.7408182206817179
-0.2 0.8187307530779818
-0.1 0.9048374180359595
0.0 1.0
0.1 1.1051709180756477
0.2 1.2214027581601699
0.3 1.3498588075760032
0.4 1.4918246976412703
0.5 1.6487212707001282
0.6 1.8221188003905089
0.7 2.0137527074704766
0.8 2.225540928492468
0.9 2.45960311115695
1.0 2.718281828459045

Das geht noch umfangreicher! Ich brauch jetzt eine Liste der Punkte im cartesischen Koordinatensys-
tem, deren Koordinaten ganze Zahlen sind. Also muss ich Paare erstellen, auch über die y-Koordinate
geschleift werden muss (der Mathematiker würde das kurz als cartesisches Produkt bezeichnen, wobei
sowohl über die x-Koordinate als auch über die y-Koordinate geschleift wird).

Beispiel 7.4.26 Liste von Punkten mit ganzzahligen Koordinaten


>>> xyKoord = [(x,y) for x in range(3) for y in range(3)]
>>> xyKoord
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

Wenn ich eine Matrix, also eine Liste von Listen, erzeugen will, ist das auch über eine list comprehen-
sion in einer Zeile zu erreichen:

169
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

Beispiel 7.4.27 Matrix durch list comprehension erzeugen


qm = [[[zeile,spalte] for spalte in range(3)] for zeile in range(3)]
>>> qm
[[[0, 0], [0, 1], [0, 2]], [[1, 0], [1, 1], [1, 2]], [[2, 0], [2, 1], [2, 2]]]

Das Problem stellt sich auch für Eheanbahnungsinstitute:

Beispiel 7.4.28 Paare bilden


>>> m = [’Max’, ’Tim’, ’Kai’]
>>> w = [’Isa’, ’Lea’, ’Jana’]
>>> paare = [(junge, maedchen) for junge in m for maedchen in w]
>>> paare
[(’Max’, ’Isa’), (’Max’, ’Lea’), (’Max’, ’Jana’), (’Tim’, ’Isa’),
(’Tim’, ’Lea’), (’Tim’, ’Jana’), (’Kai’, ’Isa’), (’Kai’, ’Lea’), (’Kai’, ’Jana’)]

Da es tatsächlich funktioniert, Listen durch list comprehensions, die eine geschachtelte Schleife ent-
halten, zu erzeugen, sollte es auch möglich sein, ein Dictionary auf diese Art zu erstellen. Die Buchstaben
eines Textes auf ihre Häufigkeit zu untersuchen ist eine Anwendung dieses Problems. Der Programm-
code sollte selbstredend sein.

Beispiel 7.4.29 Häufigkeitsverteilung der Buchstaben eines Textes


>>> satz = ’Wie sieht es aus mit der Häufigkeit der Buchstaben in diesem Satz?’
>>> haeufigkeitsDic = {buchst: [Link](buchst) for buchst in satz}
>>> haeufigkeitsDic
{’m’: 2, ’n’: 2, ’d’: 3, ’e’: 9, ’u’: 3, ’t’: 5,
’ ’: 11, ’r’: 2, ’W’: 1, ’g’: 1, ’B’: 1, ’s’: 5,
’c’: 1, ’H’: 1, ’f’: 1, ’z’: 1, ’a’: 3, ’ä’: 1,
’h’: 2, ’S’: 1, ’k’: 1, ’b’: 1, ’?’: 1, ’i’: 7}

Und jetzt soll noch aus einem Text ein Dictionary erzeugt werden. Ein Datum ist als Zeichenkette
gegeben (in der üblichen deutschen Schreibweise), daraus soll ein Dictionary gebaut werden.

Beispiel 7.4.30 Text zu Dictionary machen


>>> datum = ’15.04.2019’
>>> datVar = ’Tag Monat Jahr’

>>> datDic = {[Link]()[i]:[Link](’.’)[i] for i in range(3)}


>>> datDic
{’Tag’: ’15’, ’Monat’: ’04’, ’Jahr’: ’2019’}

Alles klar?

[Link]. Die Anzahl der Elemente einer Liste bestimmen


Nein, ich will hier niemanden ver. . . kackeiern. Natürlich ist in Python eine Funktion eingebaut, die
genau die Länge einer Liste zurückgibt, denn das ist ja gerade das, was man unter der Anzahl der
Elemente einer Liste versteht. Diese Funktion wird in dem unten stehenden Progrämmchen ganz am

170
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

Anfang aufgerufen; schaun wir mal, ob wir das mittels einer Schleife auch rauskriegen. Diese Schleife
zu programmieren hilft aber, viele ähnliche Probleme zu verstehen und zu lösen.

Beispiel 7.4.31 Länge einer Liste - zu Fuß berechnet


#!/usr/bin/python

liste = [7,12,5,23,1,14,18,33,4]
print(len(liste))

zaehler = 0
for i in liste:
zaehler += 1

print(zaehler)

Das ist wohl nicht so schwer zu verstehen! Vor Beginn der Schleife wird eine Variable Zähler deklariert
und auf 0 gesetzt. Dann wird die Schleife Element für Element gelesen; bei jedem Schleifen-Durchlauf
wird der Zähler um 1 hochgezählt.

[Link]. Anzahl der Elemente einer Liste mit einer bestimmten Eigenschaft

Bei diesem Problem hilft die len-Funktion nicht mehr! Aber es ändert sich gar nicht so viel an dem
vorigen Programm. Einzig innerhalb der Schleife wird gefragt, ob das aktuelle Element die Bedingung
erfüllt, und nur wenn es das tut, wird der Zähler erhöht.

Beispiel 7.4.32 Anzahl der durch 3 teilbaren Zahlen in der Liste


#!/usr/bin/python

liste = [7,12,5,23,1,14,18,33,4]

zaehler = 0
for i in liste:
if i % 3 == 0:
zaehler += 1

print(zaehler)

Alles klar? Wenn nicht, lies noch mal die Einführung zu diesem Beispiel und die Erklärung zum
vorigen Beispiel.

[Link]. . . . wie eben, aber mit Ergebnisliste

Also führen wir eine zweite Liste ein, die zu Beginn leer ist. Wenn die Bedingung erfüllt ist, wird mittels
der append-Methode von Listen diese Liste erweitert.

171
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

Beispiel 7.4.33 Anzahl der durch 3 teilbaren Zahlen in der Liste mit Ergebnisliste
#!/usr/bin/python

liste = [7,12,5,23,1,14,18,33,4]

ergListe = []
zaehler = 0
for i in liste:
if i % 3 == 0:
zaehler += 1
[Link](i)

print(zaehler)
print(ergListe)

[Link]. Das größte Element einer Menge finden

Sei also eine Liste von Elementen gegeben, für die es ein Ordnungskriterium gibt, so dass man also das
größte Element bestimmen kann. Der Einfachheit halber ist dies eine Liste von natürlichen Zahlen, auf
denen die übliche Größer-Relation definiert ist.

Beispiel 7.4.34 Größtes Element einer Liste


#!/usr/bin/python

liste = [7,12,5,23,1,14,18,33,4]
max = liste[0]
for i in liste[1:]:
if i > max:
max = i

print(max)

Die Logik ist wohl leicht zu erkennen: bevor die Schleife aufgerufen wird, wird das Maximum mit
dem ersten (erinnere Dich: das ist das Element mit der Hausnummer 0) Element der Liste initialisiert.
Dann wird die Schleife über die Liste ab dem zweiten Element durchlaufen. Jedes Element wird mit dem
Maximum verglichen, und wenn das jeweils in Arbeit befindliche Element größer ist als das aktuelle
Maximum, wird dieses aktuelle Element zum Maximum.

[Link]. An welcher Stelle steht das größte Element einer Menge?

Im Gegensatz zum vorigen Beispiel interessiert nicht das größte Element, sondern nur die Position, an
der dieses in der Liste steht.

172
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

Beispiel 7.4.35 Position des größten Elements einer Liste


#!/usr/bin/python

liste = [7,12,5,23,1,14,18,33,4]
max = liste[0]
pos = 0
for i in range(1, len(liste)):
if liste[i] > max:
pos = i

print(pos)

Eine vollständig andere Logik für die Schleife muss hier angewendet werden. Vor Beginn des Schlei-
fendurchlaufs wird wieder das Maximum mit dem ersten Element initialisiert, zusätzlich dazu wird die
Position mit 0 besetzt. Es kann aber jetzt nicht mehr über die Liste als solche geschleift werden, sondern
hier muss, da die Position interessiert, über die Zahl, die die Länge der Liste angibt, geschleift werden.

7.4.4. Ein bißchen Klassik

Sortieren sollte man können! Vor langer Zeit, ungefähr in der zweiten Hälfte des 20. Jahrhunderts, gab es
wohl kaum ein Buch zur Informatik, in dem nicht auf die verschiedenen Möglichkeiten des Sortierens
eingegangen wurde. Das will ich hier nicht, aber wenigstens die Problematik anreissen. Nehmen wir
an, ich habe eine endliche Menge von Dingen, die nach einem bestimmten Kriterium sortiert werden
sollen: Bücher nach dem Nachnamen, dann dem Vornamen des Autors, und falls der mehrere Bücher
geschrieben hat, auch noch nach dem Erscheinungsjahr; Rock-Platten nach der Band (für schwäbische
Rock-CD’s: der Kapelle9 ), dann nach dem Erscheinungsjahr. Alle diese Probleme benötigen natürlich
eine Methode, um zwei Exemplare nach dem jeweiligen Vergleichskriterium zu vergleichen.
Da ich nicht auf diese Vergleichskriterien eingehen will, vereinfache ich das Problem dadurch, dass
ich als Dinge ganze Zahlen wähle, und dass diese nach der Größe sortiert werden sollen. Da bietet es
sich natürlich an, diese Dinge in eine Liste zu schreiben, womit die Aufgabe verkürzt so formuliert wird:
sortiere doch mal bitte diese Liste aufsteigend:
liste1 = [13,5,8,51,23,41,1,55,36,3,64,7,52,37,32,6,42,38,53,2,12,9,47,39,24,43,21,17]
Eines der historisch ersten Verfahren ist unter dem Namen Bubblesort“ bekannt. Der Name kommt

daher, dass bei diesem Verfahren (je nach Vorgehen) die größten oder kleinsten Elemente wie Luftblasen
aufsteigen. Und es funktioniert so:

Beispiel 7.4.36 Bubblesort im Pseudocode


solange noch nicht vollständig sortiert ist
arbeite die Liste ein Element nach dem anderen von links nach rechts durch
vergleiche das aktuelle Element mit seinem Nachfolger
falls das aktuelle Element größer ist als der Nachfolger
vertausche die beiden Elemente

Das soll einmal an einer kürzeren Liste von Hand begonnen werden.

9 Gruß an Alex und Georg

173
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

Beispiel 7.4.37 Bubblesort einer kurzen Liste von Hand


liste1 = [13,7,8,2]
noch nicht vollständig sortiert, also
erstes Element: 13
Vergleich mit dem Nachfolger 7
13 > 7, also vertauschen
Ergebnis: liste1 = [7,13,8,2]
zweites Element: 13
Vergleich mit dem Nachfolger 8
13 > 8, also vertauschen
Ergebnis: liste1 = [7,8,13,2]
drittes Element: 13
Vergleich mit dem Nachfolger 8
13 > 2, also vertauschen
Ergebnis: liste1 = [7,8,2,13]
(jetzt bin ich am Ende der Liste angelangt
es ist noch nicht vollständig sortiert,
aber immerhin ist das größte Element ans Ende gelangt,
also weiter, genauer wieder von vorne)
erstes Element: 7
Vergleich mit dem Nachfolger 8
7 < 8, also nicht vertauschen
Ergebnis: liste1 = [7,13,8,2]
.... usw

Das Programm folgt:

Beispiel 7.4.38 Bubble-Sort


#!/usr/bin/python

l2 = [13,5,8,51,23,41,1,55,36,3,64,7,52,37,32,6,42,38,53,2,12,9,47,39,24,43,21,17]
sortiert = False

while sortiert == False:


sortiert = True
for z in range(len(l2)-1):
if l2[z] > l2[z+1]:
[l2[z], l2[z+1]] = [l2[z+1], l2[z]]
else:
sortiert = sortiert and True
if z >= 1:
if l2[z] < l2[z-1]:
sortiert = sortiert and False
print(l2)

7.4.5. Eigentlich keine Schleife


Die eingebaute Funktion reduce verhält sich so ähnlich wie eine Schleife, ohne dass man diese Schleife
ausdrücklich programmieren muss. Diese Funktion nimmt ein abzählbares Objekt (einen Text, der aus
n Buchstaben besteht; eine Liste, die n Elemente enthält) und führt nacheinander

• eine gegebene andere Funktion mit den ersten beiden Elementen des abzählbaren Objekts aus und
gibt das Ergebnis dieser Funktion zurück,

174
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

• nimmt dann dieses Ergebnis und das dritte Element, führt wieder die Funktion aus und gibt das
neue Ergebnis zurück
• nimmt dieses neue Ergebnis und das vierte Element ... usw.
Ein Beispiel veranschaulicht das sofort (auch wenn Funktionen in Python noch nicht besprochen wur-
den; aber das folgt innerhalb der nächsten Seiten):

Beispiel 7.4.39 Hier wird eine Funktion definiert


def summe(x,y):
print(x,’+’,y)
return x+y

Das macht die Funktion, wenn man ihr zwei Dinge übergibt:

Beispiel 7.4.40 So funktioniert diese Funktion mit 2 Zahlen


summe(3,5)
3 + 5
8

Beispiel 7.4.41 Und so mit 2 Buchstaben


summe(’a’,’b’)
a + b
’ab’

Klar, oder? Jetzt kommt reduce ins Spiel.

Beispiel 7.4.42 reduce mit dieser Funktion und einer Liste von Zahlen
reduce(summe, [1,2,3,4,5])
1 + 2
3 + 3
6 + 4
10 + 5
15

Nett! Hier werden also auch die Zwischenergebnisse sichtbar.

Beispiel 7.4.43 reduce mit dieser Funktion und einer Zeichenkette


reduce(summe, ’Martin’)
M + a
Ma + r
Mar + t
Mart + i
Marti + n
’Martin’

175
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

Auch schön! Jetzt hast Du wohl verstanden, was reduce macht.

7.4.6. Eingriffe in das Durchlaufen von Schleifen


Bei diesen Eingriffen in den Schleifendurchlauf ist es egal, ob es sich um eine Zählschleife oder eine
Schleife mit Abbruchbedingung handelt. In beiden Fällen kann es passieren, dass man mit manchen
Elementen, die beim Durchlauf auftauchen, nichts anfangen kann, dass bei anderen Elementen genug
geschleift wurde.
Das nächste Beispiel ist (zugegeben!) arg konstruiert, aber es macht klar, welcher Art Eingriffe in
Schleifen vorkommen können und wie sie in Python programmiert werden. Stellen wir uns eine ziem-
lich große Liste von ganzen Zahlen vor, ziemlich unsortiert, und als Aufgabe, die Summe der ersten
5 geraden Zahlen zu bestimmen. Das soll hier in einer Zählschleife realisiert werden. Hier kommt der
Python-Code zu diesem Problem:

Beispiel 7.4.44 Eingriff in den Schleifenablauf


1

2 zahlenListe = [1,5,523,274,143,76,15,72,2456,1,13,752,3416,6134,3475,374,
3 347,4612,57834,437]
4 summe = 0
5 gefundenZaehler = 0
6 for zahl in zahlenListe:
7 if zahl % 2 == 1:
8 continue
9 else:
10 if gefundenZaehler < 5:
11 summe += zahl
12 gefundenZaehler += 1
13 else:
14 break
15

16 print(summe)
17 (gibt aus) 3630
18 print(gefundenZaehler)
19 (gibt aus) 5
20

In Zeile 6 wird gefragt, ob der Rest bei der Division einer Zahl durch 2 gleich 1 ist, also ob die Zahl
ungerade ist. Wenn ja, dann wird durch den Befehl continue der Durchlauf der Schleife abgebrochen,
zum Ende des Schleifenkörpers gesprungen und mit der nächsten Zahl weitergemacht. Wenn das nicht
der Fall ist, wird gefragt, ob der Zähler für die gefundenen geraden Zahlen noch kleiner als 5 ist. Wenn
ja, wird die aktuelle Zahl auf die Summe aufsummiert und der Zähler für die gefundenen Zahlen um 1
erhöht. Wenn der Zähler nicht mehr kleiner als 5 ist, wird durch den Befehl break die gesamte Schleife
sofort beendet.

7.4.7. Was schief gehen kann


Vor allem bei Schleifen mit Abbruchbedingung macht man als Anfänger oder als unaufmerksamer Pro-
grammierer immer wieder 2 klassische Fehler. Diese beiden Fehler sollen hier an Beispielen gezeigt
werden.

Beispiel 7.4.45 Initialisierung der Schleifenvariable?


while x < 5:
print(x)

176
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

Das ist der weniger schlimme Fehler: zu Beginn der Schleife ist die Variable x nicht bekannt, weil
ihr bisher kein Wert zugewiesen wurde. Weniger schlimm ist das deshalb, weil das Programm an die-
ser Stelle einfach mit dem Fehler NameError: name ’x’ is not defined abbricht. Damit ist der
Fehler schnell korrigiert.

Beispiel 7.4.46 Verschlimmbesserung


x = 7
while x < 5:
print(x)

Jetzt hat die Variable x vor Beginn der Schleife einen Wert, und der ist so gewählt, dass die Bedingung
nach dem while erfüllt ist: die Schleife startet und gibt den Wert 7 aus. Danach geht das Programm
wieder zum Schleifenbeginn zurück, der Wert der Variablen x ist 7, die Schleife wird ausgeführt usw.
und so fort, und wenn sie nicht gestorben sind, schleifen sie noch immer. So etwas wird Endlosschleife“

genannt. Jetzt gibt es nur 2 Möglichkeiten: wenn man Glück hat, kann man noch in irgendeiner Form
das Programm abbrechen, wenn nicht, kann man nur noch den Rechner ausschalten.
Merke also: Bei Schleifen mit Abbruchbedingung muss die Variable, die die Schleife steuert, vor dem
Beginn der Schleife initialisiert sein; innerhalb der Schleife muss der Wert dieser Variablen verändert
werden (und zwar so, dass irgendwann die Bedingung nicht mehr erfüllt ist).

7.4.8. Aufgaben zu Schleifen


1. Geh zurück auf die Seite mit dem Bild von Monty Python. Schreibe eine Liste, die die Namen der
Mitglieder der Gruppe enthält. Schreibe ein Programm, das ausgibt Die Mitglieder ... von
li. nach re. sind ...
2. Überlege Dir eine Datenstruktur, die die Rollen enthält, die Eric Idle und John Cleese in den diver-
sen Monty-Python-Filmen spielen. Schreibe ein Programm, das diese Datenstruktur ausliest und
schön ausgibt.
3. Ein Python-Programm soll eine Sternchen-Pyramide malen; das Ergebnis soll so aussehen:

*
***
*****
*******
*********
***********
*************
***************
*****************
*******************
*********************
***********************
*************************
***************************
*****************************
*******************************
*********************************
***********************************
*************************************

4. Ein Programm soll die Quadratzahlen bis zu einer bestimmten Grenze ausgeben.
5. Aufgabe mit der Ausbreitung einer Epidemie:
a) n = Bevölkerung (konstant)
b) x(t) = Gesunde zur Zeit t

177
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

c) y(t) = Kranke ( = Ansteckende) zur Zeit t


d) z(t) = Immune ( = Genesene, Tote, Isolierte) zur Zeit t
e) n=x+y+z
f) x(t+1) - x(t) = -a * x(t) * y(t) (Abnahme der Gesunden proportional zu Anzahl der Gesunden
und Anzahl der Kranken; Infektionsrate = a > 0 )
g) z(t+1) - z(t) = b * y(t) (Zunahme der Immunen proportional zu Anzahl der Kranken; 0 <= b =
Immunisierungsrate <= 1)
6. Quersumme einer Zahl ausrechnen; (beachte dabei: Typ-Konvertierung String-Element -> Zahl)
7. Primzahlen mit dem Sieb des Eratosthenes berechnen
8. Fakultät einer Zahl berechnen
9. ggT und kgV ausrechnen mit Euklids Algorithmus
10. Newtonsches Näherungverfahren zur Berechnung von Nullstellen
11. Eine Zahl soll im Dezimalsystem eingegeben und in ein beliebiges anderes Stellenwertsystem um-
gerechnet werden.
12. Gegeben ist der Satz Dieser Satz hat x Buchstaben sowie einen Punkt.“ Dabei soll für x das Zahl-

wort einer Zahl eingesetzt werden, zum Beispiel so: Dieser Satz hat zwei Buchstaben sowie einen

Punkt.“ Dieser Satz ist sicher falsch (denn der Satz Dieser Satz hat zwei Buchstaben sowie einen

Punkt.“ hat nicht nur 2 Buchstaben)!
Schreibe ein Programm, das überprüft, ob es eine Zahl n gibt, so dass der Satz richtig ist und gib
das Ergebnis aus.
Schreibe ein anderes Programm, das für den Satz Dieser Satz besteht aus n Buchstaben, zehn

Leerzeichen sowie einem Komma und einem Punkt.“ die selbe Prüfung mit der selben Ausgabe
macht.
13. Ein Programm soll geschrieben werden, das die Abrechnung für einen geliehenen Drucker macht.
Dabei wurde mit dem Büromaschinenverleih vertraglich vereinbart, dass die fixen Kosten pro Mo-
nat 840,34 e betragen, die bereits ein Druckvolumen von 2000 Blatt beinhalten. Für jedes weitere
gedruckte Blatt werden 0,038 e berechnet. Auf die bisher genannten Beträge muss noch die Mehr-
wertsteuer von 19 % aufgerechnet werden. Das Programm soll in Schritten von 500 Blatt (bis 10000
Blatt) die gesamten Kosten und die Kosten je Blatt ausgeben.
14. Ein nettes kleines Programm (bei dem man Schleifen und auch das modulo-Rechnen“ anwen-

den kann) ist zu schreiben, das zwei Uhrzeiten addiert. Die Uhrzeiten werden jeweils als Listen
übergeben, also die Uhrzeit 15:33:46 als [15,33,46].
15. Das Programm aus dem Kapitel über Strukturierte Daten“, das in einer Eisdiele spielt, soll erwei-

tert werden, so dass man eine Bestellung von mehreren Eisbechern aufnehmen kann (durchaus
auch mehr als einen Eisbecher der selben Art) und danach eine Rechnung ausgegeben bekommt.
16. Das Programm aus dem Kapitel über Strukturierte Daten“, das mit Daten von Staaten umgeht,

soll so erweitert werden, dass in einem Programm alle Länder, die die selbe Landessprache haben,
aufgelistet werden. Überlege Dir selbst, wie eine sinnvolle Ausgabe aussehen könnte.
17. Schreibe ein Programm, das in einem Dictionary Staaten mit ihren Hauptstädten speichert. In
einem kleinen Rätsel sollen jetzt die Hauptstädte abgefragt werden. Je richtiger Antwort bekommt
man einen Punkt, das Ergebnis soll am Ende des Rätsels angezeigt werden
18. Das vorige Programm soll lernen!! Wenn eine Hauptstadt falsch eingegeben wurde, das aber eine
Hauptstadt eines Staates ist, soll ein Staat-Hauptstadt-Paar dem Dictionary hinzugefügt werden
und das Rätsel von neuem starten, solange, bis alles fehlerfrei beantwortet ist.
19. Das Programm aus dem Kapitel über Strukturierte Daten“, das Adressen behandelt, soll aufge-

bohrt werden, so dass ein schönes Adressbuch ausgegeben wird.
20. Das Raus-“Geld soll gestückelt werden! Das Programm soll z.B. bei einem Rechnungsbetrag von

20,12 e und einer Bezahlung mit einem 100e -Schein ausgeben, dass man einen 50e -Schein, einen
20e -Schein, einen 5e -Schein, zwei 2e -Münzen etc. herausbekommt.
21. Für eine gegebene Funktion (hier: eine ganzrationale Funktion) soll eine Wertetabelle in einem
Intervall mit einer einzugebenden Schrittweite ausgegeben werden.
22. Die Sierpinski-Pfeilspitze kann man dadurch erzeugen, dass man im Pascal’schen Dreieck die
ungeraden und die geraden Zahlen verschiedenfarbig darstellt. Schreibe ein Programm, das die
Sierpinski-Pfeilspitze auf der Kommandozeile (shell) malt. Dabei soll schwarz“ durch ein x“ und
” ”
weiß durch ein Leerzeichen dargestellt werden.

178
KAPITEL 7. PROGRAMMSTRUKTUREN 7.4. SCHLEIFEN

23. Heutzutage kommt man nicht mehr umhin, in einem Text über Programmierung auch auf Ver-
und Entschlüsseln zu sprechen. Schreibe ein Programm, das eine monoalphabetische Verschlüsselung
eines Textes liefert, so wie sie der Legende nach auf Caius Iulius Caesar zurückgeht. Caesar soll
damals einfach um eine bestimmte Zahl im Alphabet weitergezählt haben. Beispiel: Wenn diese
Zahl die 3 war, dann wurde aus A ein D, aus H ein K etc.
Dabei sei der Text, wie damals zu Cäsars Zeit, in reinen Großbuchstaben gegeben. Der verschlüsselte
Text soll auch nur Großbuchstaben enthalten. Leerzeichen bleiben Leerzeichen, Satzzeichen wer-
den erhalten.
a) Die einfache Variante arbeitet mit einer Zeichenkette, die nach Buchstaben durchsucht wird.
Diese Zeichenkette muss einige Buchstaben doppelt enthalten.
b) Die nächstschwierige Variante arbeitet modulo der Länge des Alfabets.
c) Die komfortable Lösung erlaubt auch Kleinbuchstaben und Sonderzeichen. Für diese Lösung
werden zwei Funktionen benötigt: ord(Zeichen) liefert die Nummer des Zeichens zurück,
chr(Zahl) liefert das Zeichen mit der Nummer Zahl zurück.
Ein Tip: geh in IDLE, schau nach, was A für eine Hausnummer hat!
24. Eine verbesserte Methode ist die Verschlüsselung mit Schlüsselwort. Dabei verschiebt man nicht
jeden Buchstaben um den selben Wert, sondern denkt sich ein Schlüsselwort aus. Hier wird das
beispielhaft mit einem sehr kurzen Schlüsselwort, dem Wort BAD“, gemacht.

B ist der zweite Buchstabe des Alfabets, A der erste, D der vierte. Es gibt also folgende einfache
Zuordnung:

Tabelle 7.8. Schlüsselwort


Schlüssel B A D
Wert 2 1 4

Wenn jetzt der Text EIN GEHEIMER BRIEF“ verschlüsselt werden soll, dann geschieht das fol-

gendermaßen (der Einfachheit halber ignoriere ich in diesem Beispiel die Leerzeichen):
a) Der erste Buchstabe des Textes, das E wird mit dem Buchstaben B, dem ersten Buchstaben
des Schlüsselwortes, verschlüsselt. B hat den Wert 2, also wird von E aus zwei Buchstaben
weitergezählt.
b) Der zweite Buchstabe des Textes, das I wird mit dem Buchstaben A, dem zweiten Buchsta-
ben des Schlüsselwortes, verschlüsselt. A hat den Wert 1, also wird von I aus ein Buchstabe
weitergezählt.
c) Der dritte Buchstabe des Textes, das N wird mit dem Buchstaben D, dem dritten Buchstaben
des Schlüsselwortes, verschlüsselt. D hat den Wert 4, also wird von N aus vier Buchstaben
weitergezählt.
d) Der vierte Buchstabe des Textes, das G wird mit dem Buchstaben B, dem ersten Buchstaben
des Schlüsselwortes, verschlüsselt (denn da das Schlüsselwort nur 3 Buchstaben hat, geht es
hier wieder von vorne los). B hat den Wert 2, also wird von G aus zwei Buchstaben weiter-
gezählt.
e) usw.

Tabelle 7.9. Verschlüsselung


Index 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Klartext E I N G E H E I M E R B R I E F
Schlüssel B A D B A D B A D B A D B A D B
Geheimtext G J R I F L G J Q G S F T J I H

Es lohnt sich, genau hinzuschauen! Der 0. und der 4. Buchstabe im Originaltext sind jeweils ein
E“, aber das E“ an Position 0 wird zu einem G“, das an Position 4 zu einem F“. Der Geheimtext
” ” ” ”
an Stelle 4 ist ein F“, ebenso der an Stelle 11. Der Originaltext ist aber unterschiedlich ( E“ bzw.
” ”
B“). Es gibt also keine eindeutige Zuordnung mehr!

179
KAPITEL 7. PROGRAMMSTRUKTUREN 7.5. FUNKTIONEN

25. 10-stellige ISBN:


• Eingabe:
– 9 Stellen der ISBN
• Ausgabe:
– Prüfziffer
– gesamte ISBN
• Tips:
– Google: ISBN
– Rest bei Division

7.5. Funktionen
7.5.1. Allgemeines zu Funktionen
Oft ist eine bestimmte Anweisungsfolge nicht für einen Wert, sondern für mehrere Werte zu durchlau-
fen. Es ist also praktisch, dieser Anweisungsfolge einen Namen zu geben, unter dem sie aufgerufen
werden kann. Ideal ist es, wenn man beim Aufruf dieser Anweisungsfolge unter einem vorher festge-
legten Namen noch einen oder mehrere Werte mitgeben kann. Das ist das Prinzip einer Funktion. Die
Werte, die man einer solchen Funktion mitgibt, werden Parameter“ genannt.

Dadurch gewinnt man. Man gewinnt Zeit: ein Stück Code muss nur einmal geschrieben werden. Man
gewinnt Freunde: jemand anderer kann den Code benutzen, wenn er gut funktioniert. Man gewinnt
Ordnung: das, was ich in einer Funktion codiert habe und von dem erwiesen ist, dass es funktioniert,
kann ich wegräumen“, so dass ich es nicht immer wieder lesen muss.

Funktionen kennt wahrscheinlich jeder aus der Mathematik. Dort sieht eine Funktion zum Beispiel so
aus: f (x) = 2x2 − 3x + 5 Die Funktion hat einen Namen, nämlich f“ 10 , es gibt eine Variable, das x, das

sozusagen in die Funktion eingegeben wird, und es gibt einen (Rückgabe-)Wert, der aus der Funktion
herausgegeben wird, nämlich das, was auf der rechten Seite des Gleichheitszeichens ausgerechnet wird,
wenn man für x einen Wert eingibt. Als Beispiel: wenn man in die oben notierte Funktion den Wert 2
eingibt, berechnet die Funktion 2*4 - 3*2 +5 und gibt als Ergebnis 7 zurück. Wer etwas mehr Mathematik
gemacht hat als die normale Oberstufen-Mathematik, der weiß auch, dass es Funktionen gibt, die mehr
als eine Variable haben.
In einigen Programmiersprachen werden solche abgeschlossenen Blöcke von funktionierenden An-

weisungen“ auch Unterprogramme oder Prozeduren genannt, während Funktionen Unterprogramme
sind, die einen Wert zurückgeben. In Pascal etwa gibt es verschiedene Schlüsselwörter für Prozedu-
ren und Funktionen. In anderen Programmiersprachen hingegen werden die Begriffe gleichbedeutend
benutzt.

7.5.2. Eingebaute Funktionen


Python hat zum Glück schon viele eingebaute Funktionen, und die haben wir auch zum Teil schon
genutzt.
• print() druckt die Werte aus, die in der Klammer stehen
• len() berechnet die Länge von Dingen, die eine Länge haben, z.B. von Texten, von Listen
• int() und float() wandeln eine Eingabe, die mit input() erfolgt ist, in eine Ganzzahl oder
eine Fließkommazahl um.
Andere Funktionen sind in Moduln enthalten, die schon verwendet wurden.
• sqrt() aus dem Modul math berechnet die (Quadrat-)Wurzel einer Zahl, sin() aus dem Modul
math berechnet den Sinus einer Zahl.
10 Soeinfallsreich sind nun mal Mathematiker. Funktionen heißen fast immer f“, und wenn ein Mathematiker mehr als eine

Funktion benötigt, besteht seine Kreativität darin, die Funktionen dann f1 und f2 zu nennen.

180
KAPITEL 7. PROGRAMMSTRUKTUREN 7.5. FUNKTIONEN

7.5.3. Funktionen selbstgebaut


[Link]. Definition und Aufruf von Funktionen

Einfache Funktionen Eine Funktion hat

• einen Funktionsnamen
• einen Funktionskopf
• einen Funktionskörper
• und manchmal einen Rückgabewert (den Funktionswert)

Für den Funktionsnamen gelten alle Regeln, die für Variablennamen (siehe dort) gelten. Es ist guter Stil,
wenn man Funktionen als Namen ein Verb gibt, denn Funktionen tun etwas. Auch hier ist ein Vergleich
mit der Mathematik interessant: in der Mathematik heißen Funktionen fast immer f“, während in der

Programmierung der Funktionsname schon Aufschluss darüber geben sollte, was die Funktion macht.
In Mathematik berechnet eine Funktion immer einen Wert. In der Programmierung macht eine Funktion
irgendwas.
Der Funktionskopf besteht aus dem reservierten Wort def“, gefolgt vom Funktionsnamen und Para-

metern, die in Klammern mitgegeben werden. Selbst wenn einer Funktion keine Parameter mitgegeben
werden, muss ein leeres Paar Klammern geschrieben werden. Der Funktionskopf endet mit einem Dop-
pelpunkt, und inzwischen ist bekannt, was nach dem Doppelpunkt gemacht werden muss: die Anwei-
sungen, die zur Funktion gehören, der Funktionskörper, müssen eingerückt werden. Da es (vor allem zu
Beginn der Entwicklung eines Programms) vorkommt, dass man weiß, dass ein Teil der Problemlösung
durch eine Funktion erledigt werden soll, man aber sich noch nicht mit deren Details auseinandersetzen
will, ist es praktisch, eine Funktion zu schreiben, die nichts tut. Dies geschieht durch die Anweisung
pass:

Beispiel 7.5.1 Funktions-Definition einer Funktion, die nichts tut


>>> def tunix():
pass

Aber hier folgt gleich ein einfaches Beispiel, das etwas tut:

Beispiel 7.5.2 Funktions-Definition


>>> def gruss():
print("Hallo und Guten Tag")

Damit hat man eine Funktion definiert, und es ist klar, was sie leistet. Jetzt kann man diese Funktion
aufrufen:

Beispiel 7.5.3 Funktionsaufruf


>>> gruss()
Hallo und Guten Tag

Diese Funktion hat also keinen Parameter (keine Variable, die etwas in die Funktion reinbringt) und
keinen Rückgabewert, das heißt, es kommt auch nichts aus der Funktion heraus.
Wie vorher schon erwähnt, ist es besonders hilfreich, wenn eine Funktion nicht immer das selbe
macht, sondern abhängig von einem mitgegebenem Wert etwas tut. Ein solcher Wert wird Parameter
oder Argument der Funktion genannt. Also bohren wir das obige Beispiel auf, so dass der Gruss etwas
persönlicher wird:

181
KAPITEL 7. PROGRAMMSTRUKTUREN 7.5. FUNKTIONEN

Beispiel 7.5.4 Funktion mit Parameter


>>> def grussMitName(name):
print("Hallo ", name, " und Guten Tag")

Dies wird jetzt aufgerufen mit

Beispiel 7.5.5 Funktionsaufruf mit Parameter


>>> grussMitName("Martin")
Hallo Martin und Guten Tag

Wie weiter oben angesprochen kommt hier eine Funktion, die ausgibt, ob eine Zahl zwischen zwei
anderen Zahlen liegt.

Beispiel 7.5.6 Funktion mit 3 Parametern: zwischen


def liegtZwischen(z,unten,oben):
return unten < z < oben

erg = liegtZwischen(3, 0, 10)


print(erg)
>>> True
erg = liegtZwischen(8, 0, 10)
print(erg)
>>> False
erg2 = liegtZwischen(’e’, ’a’, ’h’)
print(erg2)
>>> True

Und die letzten 3 Zeilen wundern auch nicht mehr: Python kann auch zum Beispiel überprüfen, ob ein
Buchstabe zwischen zwei anderen liegt. Hier sollte man vielleicht einmal probieren, ob diese Funktion
auch mit anderen Daten als Zahlen und Buchstaben klar kommt.

[Link]. Rückgabewerte und Parameterlisten

Bis jetzt hat eine Funktion etwas gemacht, nicht mehr und nicht weniger. In mancher anderen Program-
miersprache11 wird so etwas Prozedur“ genannt. Funktionen unterscheiden sich in diesen Sprachen

von Prozeduren, dass sie etwas zurückgeben. Das soll an einem einfachen Beispiel vorgeführt werden.

Beispiel 7.5.7 Funktion ohne Rückgabewert


def summeAusdrucken(a, b):
print(a + b)

Dazu muss man nichts sagen! Beim Aufruf dieser Funktion wird einfach die Summe der beiden Pa-
rameter ausgegeben.

11 z. B. in den Wirth-Sprachen

182
KAPITEL 7. PROGRAMMSTRUKTUREN 7.5. FUNKTIONEN

Beispiel 7.5.8 Aufruf der Funktion ohne Rückgabewert


summeAusdrucken(5,7)
>>> 12

Jetzt soll eine Funktion diese Summe zurückgeben. Das reservierte Wort, das einen Rückgabewert
zurückgibt, heißt return“. So sieht das aus:

Beispiel 7.5.9 Funktion mit Rückgabewert


def summeZurueckgeben(a, b):
return a + b

Diese Funktion wird anders aufgerufen.

Beispiel 7.5.10 Aufruf der Funktion mit Rückgabewert


ergebnis = summeZurueckgeben(5,7)
print(ergebnis)
>>> 12

Es folgt ein weiteres Beispiel dazu, und zwar sowohl die Definition als auch die Ausführung:

Beispiel 7.5.11 Funktion mit Rückgabewert


>>> def verdoppeln(zahl):
return 2*zahl
>>> a = verdoppeln(3)
>>> print(a)
6
>>> b = verdoppeln(5.7)
>>> print(b)
11.4

Hier hingegen wird etwas in die Funktion reingegeben und es kommt auch ein Rückgabewert heraus.
Dabei ist es der Funktion egal, welcher Art die Daten sind, die ihr übergeben werden:

Beispiel 7.5.12 nochmal: Funktion mit Rückgabewert


>>> c = verdoppeln("so was ")
>>> print(c)
so was so was

Wie weiter oben schon erwähnt wurde, kann eine Funktion auch mehrere Parameter bekommen.

183
KAPITEL 7. PROGRAMMSTRUKTUREN 7.5. FUNKTIONEN

Beispiel 7.5.13 Funktion mit mehreren Parametern


>>> def telNrDrucken(vorn, nachn, telnr):
print(vorn+’ ’+nachn)
print(’Telefon: ’, telnr)
>>> telNrDrucken(’Martin’,’Schimmels’, ’12345’)
Martin Schimmels
12345

Hier ist es natürlich wichtig, dass beim Aufruf der Funktion die Werte für die Parameter in der selben
Reihenfolge übergeben werden, wie sie die Funktion in ihrem Funktionskopf deklariert hat, also in
diesem Beispiel in der Reihenfolge Vorname, Nachname, Telefonnummer.
Es ist allerdings möglich, von dieser eben beschriebenen Regel abzuweichen, indem man beim Aufruf
einer Funktion nicht nur den Wert für einen Parameter mitgibt, sondern im Aufruf der Funktion dem
Parameternamen einen Wert zuweist. Das obige Beispiel lässt sich also auch so schreiben:

Beispiel 7.5.14 Parameterübergabe mit Parameternamen


>>> def telNrDrucken(vorn, nachn, telnr):
print(vorn+’ ’+nachn)
print(’Telefon: ’, telnr)
>>> telNrDrucken(telnr=’12345’, vorn=’Martin’,nachn=’Schimmels’, )
Martin Schimmels
12345

Hier wird also die Reihenfolge, wie sie in der Parameterliste des Funktionskopfes vorgegeben ist,
nicht eingehalten, sondern die Reihenfolge wird beliebig gewählt, dafür aber bei jedem Parameterwert
mitgeteilt, welchem Parameter dieser Wert zugewiesen werden soll.
Oft weiß man, dass für einen Parameter fast immer ein bestimmter Wert übergeben wird; das wird
in der Informatik als Default-Wert“ bezeichnet. Dann ist es gut, wenn man in der Parameterliste einer

Funktion schon einen Standardwert festlegen kann. Das bedeutet, dass man für diesen Parameter der
Funktion einen Wert an die Funktion übergeben kann (dann wird der genommen), es aber auch sein
lassen kann (dann wird der in der Parameterliste festgelegte Standardwert genommen). Das Beispiel
dazu:

Beispiel 7.5.15 Parameter mit Vorgabewert


>>> def verstaerkung(text, wieOft=1):
print(text * wieOft)
>>> verstaerkung(’hallo’)
hallo
>>> verstaerkung(’hallo’,3)
hallohallohallo

Und, kein Wunder, das funktioniert natürlich auch mit einer Zahl als Wert für den ersten Parameter:

Beispiel 7.5.16 Parameter mit Vorgabewert (numerisch)


>>> verstaerkung(3)
3
>>> verstaerkung(3,4)
12

184
KAPITEL 7. PROGRAMMSTRUKTUREN 7.5. FUNKTIONEN

Es gibt sogar die Möglichkeit, Funktionen zu schreiben, bei denen die Anzahl der Parameter unbe-
kannt ist. In einem solchen Fall übergibt man der Funktion ein Tupel von Werten. Die spannende Frage
ist, wie die Funktion dieses Tupel entgegennimmt. Dies geschieht dadurch, dass dem Parameternamen
in der Klammer der Funktionsdefinition ein *“ vorangestellt wird. Das Beispiel dazu sieht so aus:

Beispiel 7.5.17 Unbekannte Anzahl Parameter


>>> def funktion1(para1, para2, *para3):
print(para1, para2, para3)
>>> funktion1(’Max’, ’Senf’, ’Hof’, ’Isar’, ’Pils’, ’Auto’)
Max Senf (’Hof’, ’Isar’, ’Pils’, ’Auto’)

Den ersten beiden Parametern, beide ohne einen *“ in der Funktionsdefinition, werden also die ers-

ten beiden Werte des Tupels zugewiesen. Dem letzten Parameter, dieser mit *“, wird der gesamte Rest

zugewiesen. Dieser gesamte Rest ist somit wieder ein Tupel, das aus diesem Grund in Klammern ge-
schrieben wird, wobei die einzelnen Teile des Tupels in Anführungsstriche gesetzt und durch Kommata
voneinander getrennt sind.
Mit diesem Wissen ist es aber auch einfach, die Parameter, auch die aus dem Tupel, einzeln auszuge-
ben:

Beispiel 7.5.18 Nochmal: Unbekannte Anzahl Parameter


>>> def funktion1(para1, para2, *para3):
print(para1, para2, end=’ ’)
for x in para3:
print(x,end=’ ’)
>>> funktion1(’Max’, ’Senf’, ’Hof’, ’Isar’, ’Pils’, ’Auto’)
Max Senf Hof Isar Pils Auto

Wenn einer Funktion Schlüsselparameter übergeben werden, also Parameter mit Parameternamen,
dann soll daraus ein Dictionary gemacht werden. Das geschieht mit den **“. Die Erklärung ergibt sich

aus dem folgenden Beispiel:

Beispiel 7.5.19 Ein Dictionary als Ausgabe


>>> def dicParameterAusgeben(**woerterbuch):
print(woerterbuch)
>>> dicParameterAusgeben(Kuh=’cow’,Hund=’dog’,Vogel=’bird’)
{’Hund’: ’dog’, ’Vogel’: ’bird’, ’Kuh’: ’cow’}

[Link]. Verkettung von Funktionen


In der Mathematik wird die Verkettung von Funktionen spätestens in der Oberstufe des Gymnasiums
relevant: da taucht dann vielleicht etwas in der Art von f(x) = sin(ex ) auf. Und die Schüler mögen
es gar nicht!
Dabei ist das Prinzip ganz einfach: man nehme ein x, gebe es in eine erste Funktion hinein, und diese
erste Funktion liefert ein Ergebnis zurück; dieses Ergebnis gebe man in eine zweite Funktion hinein,
und diese liefert das Endergebnis zurück. Bei dem Beispiel aus dem vorigen Absatz wird das x zuerst
in die natürliche Exponentialfunktion reingeschmissen, und als Ergebnis kommt dort ex heraus. Von
diesem Ergebnis wird jetzt der Sinus gebildet. Fertig.
In der Programmierung gibt es das natürlich auch. Hier folgt ein Beispiel, bei dem eine Zahl zuerst
durch eine erste Funktion verdoppelt wird. Das Ergebnis wird dann durch eine zweite Funktion qua-
driert.

185
KAPITEL 7. PROGRAMMSTRUKTUREN 7.5. FUNKTIONEN

Beispiel 7.5.20 Verkettung von Funktionen


def verdoppeln(x):
return 2 * x

def quadrieren(z):
return z*z

zahl = 3
zwischenergebnis = verdoppeln(zahl)
endergebnis = quadrieren(zwischenergebnis)
print(endergebnis)
>>> 36

Das funktioniert! Aber es sieht nicht schön aus. Die beiden Funktionen sind kurz, der Name sagt aus,
was sie jeweils machen, also bleiben die beiden Funktionen so. Der Aufruf hingegen kann verbessert
werden. Also vereinfachen (und verschönern) wir das:

Beispiel 7.5.21 Verkettung von Funktionen


def verdoppeln(x):
return 2 * x

def quadrieren(z):
return z*z

zahl = 3
endergebnis = quadrieren(verdoppeln(zahl))
print(endergebnis)
>>> 36

Den Mathematiker freut es, denn so schreibt er auch die Verkettung von Funktionen. Wenn zuerst die
Funktion f1 mit dem Argument x und dann die Funktion f2 mit dem Ergebnis der ersten Funktion als
Argument aufgerufen werden soll, dann schreibt der Mathematiker f2 (f1 (x))

[Link]. Gültigkeitsbereiche und Namensräume

An dieser Stelle kommt der Begriff Namensraum ins Spiel. Der Namensraum ist der Bereich, in dem eine
Variable (oder ein anderer Teil eines Programms) bekannt und gültig ist. Das wird deswegen auch der
Gültigkeitsbereich genannt. Das war bis jetzt noch kein Problem, weil unsere Programme noch nicht in
kleinere Einheiten unterteilt waren.
Eine Funktion ist aber ein kleines Programm im Programm“, womit eine solche Unterteilung in

kleinere Einheiten geschieht. Damit gilt auch, dass eine Variable, die erst innerhalb einer Funktion zum
ersten Mal benutzt wird, dadurch, dass ihr ein Wert zugewiesen wird, außerhalb der Funktion nicht
bekannt ist. Das wird in der Programmierung eine lokale Variable genannt. Ein einfaches Beispiel, um
das zu demonstrieren, sieht so aus:

186
KAPITEL 7. PROGRAMMSTRUKTUREN 7.5. FUNKTIONEN

Beispiel 7.5.22 Lokale Variable


#!/usr/bin/python

def doofFunktion():
nr = 378
print(’Nummer IN der Funktion:’, nr)

doofFunktion()
print(’Nummer NACH der Funktion:’, nr)

Die Variable nr wird hier in der Funktion definiert und gleich ausgegeben. Nach Beendigung der
Funktion wird nochmals versucht, diese lokale Variable auszugeben. Hier ist die Ausgabe des Pro-
gramms:

Beispiel 7.5.23 Lokale Variable


Nummer IN der Funktion: 378
Nummer NACH der Funktion:
Traceback (most recent call last):
File "./[Link]", line 8, in module
print(’Nummer NACH der Funktion:’, nr)
NameError: name ’nr’ is not defined

Wie man sieht, wird der print-Befehl nach Beendigung der Schleife nicht ausgeführt, weil die Varia-
ble nr außerhalb der Funktion nicht bekannt ist, sondern das Programm bricht mit einer Fehlermeldung
ab.
Die Variable, die innerhalb der Funktion definiert wird, gehört zum Gültigkeitsbereich der Funktion.
Hier ist sie bekannt, außerhalb nicht. Anders sieht es aus, wenn eine Variable im Hauptprogramm de-
finiert wird. Eine solche Variable gehört zum Gültigkeitsbereich des Hauptprogramms und damit auch
zum Gültigkeitsbereich aller Funktionen, die innerhalb des Hauptprogramms definiert werden. Man
nennt eine solche Variable, die im ganzen Programm gültig ist, eine globale Variable“. Das soll an

einem Beispiel verdeutlicht werden:

Beispiel 7.5.24 verschachtelte Aufrufe von Funktionen


#!/usr/bin/env python3

def innereFktErsterEbene():
var1E = ’\tVariable der 1. Ebene’
print(var1E)
print(’\tAufruf aus 1. Ebene: ’+varHauptPgm)

def innereFktZweiterEbene():
var2E = ’\t\tVariable der 2. Ebene’
print(var2E)
print(’\t\tAufruf aus 2. Ebene: ’+var1E)

innereFktZweiterEbene()

varHauptPgm = ’VARIABLE DES HAUPTPROGRAMMS’


print(varHauptPgm)
innereFktErsterEbene()

187
KAPITEL 7. PROGRAMMSTRUKTUREN 7.5. FUNKTIONEN

Innerhalb der Funktion innereFktErsterEbene wird hier die Variable varHauptpgm aufgerufen,
ebenso in der Funktion innereFktZweiterEbene. Das sieht so aus:

Beispiel 7.5.25 Ausgabe des Programms zu verschachtelten Funktionen


>>> VARIABLE DES HAUPTPROGRAMMS
Variable der 1. Ebene
Aufruf aus 1. Ebene: VARIABLE DES HAUPTPROGRAMMS
Variable der 2. Ebene
Aufruf aus 2. Ebene: Variable der 1. Ebene

7.5.4. Funktionen wiederverwenden


Eine Funktion ist ein Stück Code, das funktioniert! Nicht nur, dass eine Funktion einen klar abgegrenz-
ten Tätigkeitsbereich“ hat, eine Funktion sollte so flexibel sein, dass sie mit verschiedenen Werten ar-

beiten kann und es sollte sicher gestellt sein, dass die Funktion auch vollkommen richtig arbeitet.
Wenn das der Fall ist, dann will man so ein kleines Schmuckstück natürlich auch mehrmals benutzen.
Das könnte man natürlich so machen, dass man den Code einfach per copy and paste“ in das neue

Programm nochmals einfügt. Aber das kann Probleme aufwerfen12 , denn unter Umständen fällt einem
beim 15. Mal, dass man die Funktion benutzt, auf, dass man doch noch eine Kleinigkeit ändern muss.
Also alle vorigen 14 Versuche nochmals anschauen???
Viel sinnvoller ist es, eine solche Funktion nur an einer Stelle gespeichert zu haben und nur diese
eine Stelle zu ändern, wenn denn etwas geändert werden muss. Die Technik, die wir dabei anwenden,
ist der Import. Dabei wird über die Import-Funktion von Python alles (oder auch nur Teile) aus der
abgespeicherten Datei in das neue Programm eingefügt. Das kann auf 3 verschiedene Arten geschehen:
1. mittels import datei wird die gesamte Datei importiert. Dabei bleiben die Funktion und even-
tuelle Variable im Namensraum der gespeicherten Datei. Die Funktion und eventuelle Variable
müssen in diesem Fall voll-qualifiziert aufgerufen werden, wenn sie verwendet werden sollen,
das heißt, dass der Dateiname vorangestellt werden muss: [Link]()
2. mittels from datei import funktion wird nur die Funktion importiert. Dabei wird die Funk-
tion in den Namensraum der neuen Datei übernommen. Sie wird in diesem Fall über den Funkti-
onsnamen (ohne irgendeinen Zusatz) aufgerufen.
3. mittels from datei import * werden alle Dinge aus der gespeicherten Datei importiert und in
den Namensraum der neuen Datei übernommen. Von dieser Art des Imports wird abgeraten, da es
hier sehr auf die Disziplin des Programmierers ankommt, damit es keine doppelten Benennungen
von Funktionen oder Variablen kommt.
Das soll jetzt an einem Beispiel gezeigt werden. Ich nehme dazu die Funktion verdoppeln von oben

Beispiel 7.5.26 Funktion verdoppeln


def verdoppeln(zahl):
return 2*zahl

Diese wird in einer Datei [Link] gespeichert. In meinem neuen Programm will ich
diese Funktion benutzen. Zuerst kommt hier die erste der oben beschriebenen Arten des Aufrufs:

Beispiel 7.5.27 Aufruf der Verdoppelung (1.)


import textfunktionen

print([Link](13))

12 und dabei denken wir nicht nur an Karl-Theodor z. G.

188
KAPITEL 7. PROGRAMMSTRUKTUREN 7.5. FUNKTIONEN

Als nächstes folgt der Import mit from“:


Beispiel 7.5.28 Aufruf der Verdoppelung (2.)


from textfunktionen import verdoppeln

print(verdoppeln(13))

7.5.5. Ein Trick, um Funktionen zu testen


Meistens, und wir kommen später noch darauf, ist es so, dass eine Funktion in einer separaten Datei
gespeichert wird, und diese Datei dann importiert wird. Die Vorteile dieses Vorgehens sind klar:

• etwas wird nur einmal geschrieben, und kann dann an verschiedenen Stellen, von verschiedenen
Programmen benutzt werden

• das Programm, an dem man gerade arbeitet, bleibt kurz und übersichtlich, weil der Code einer
Funktion nicht mehr in diesem Programm steht, sondern separat

Trotzdem kann es vorkommen, dass man an einer Funktion nachträglich etwas ändern muss, und dann
aber nicht alle Programme testen will, die diese Funktion benutzen. Da wäre es doch schön, wenn man
innerhalb der Datei, die die Funktion enthält, einen Test eingebaut hätte, der nur dann ausgeführt wird,
wenn diese Funktion getestet werden soll, aber nicht, wenn sie im produktiven Einsatz ist.
Natürlich gibt es diese Möglichkeit in Python. Das Mittel dazu ist die eingebaute Variable name .

Beispiel 7.5.29 Builtin name


>>> print(’Die Variable __name__ hat den Wert ’, __name__)
Die Variable __name__ hat den Wert __main__

So sieht das aus, wenn der Wert der Variablen name von der Python-Shell aus abgefragt wird:
diese Variable hat jetzt den Wert main . Als nächstes schreibe ich ein kleines Programm, das nur den
obigen Befehl enthält und speichere es unter dem Dateinamen [Link].

Beispiel 7.5.30 Builtin name in einer Datei


#!/usr/bin/python
print(’Die Variable __name__ hat den Wert ’, __name__)

Und dieses Datei importiere ich:

Beispiel 7.5.31 Aufruf dieser Datei


>>> import echoName
Die Variable __name__ hat den Wert echoName

Erstaunlich!! Jetzt steht in der Variablen name der Name der importierten Datei! Das ist doch die
Lösung des Problems, einen Test einer Funktion nur durchzuführen, wenn wirklich getestet werden soll,
nämlich dann, wenn diese Funktion aus der Datei heraus, in der die Funktion steht, aufgerufen wird.

189
KAPITEL 7. PROGRAMMSTRUKTUREN 7.5. FUNKTIONEN

Beispiel 7.5.32 Anwendung für den Test einer Funktion


#!/usr/bin/python

def irgendwas():
print(’irgendwas’)

if __name__ == ’__main__’:
irgendwas()

7.5.6. Globale Variable

Über Gültigkeitsbereiche von Variablen ist bisher noch gar nichts gesagt worden, ganz einfach deswe-
gen, weil das bei der Konzeption von Python keine Bedeutung hatte. Oder wie es der Vater von Python
formuliert hat: We’re all consenting adults13“ Deswegen gilt: Variable sind immer überall gültig, sie

sind global. Das zeigen wir an einem Beispiel:

Beispiel 7.5.33 eine globale Variable


#!/usr/bin/python
# -*- coding: utf-8 -*-

globaleVar = ’gloooobal!!’

def eineFunktion():
print(’in der ersten Funktion: ’+globaleVar)

print(’außerhalb jeder Funktion: ’+globaleVar)


eineFunktion()

Die Ausgabe sieht so aus:

Beispiel 7.5.34 Ausgabe von globaler Variablen


außerhalb jeder Funktion: gloooobal!!
in der ersten Funktion: gloooobal!!

Jetzt deklarieren wir eine zweite Funktion, innerhalb derer eine Variable mit dem selben Variablenna-
men definiert wird.

13 [Programming Python2] , Seite 285

190
KAPITEL 7. PROGRAMMSTRUKTUREN 7.5. FUNKTIONEN

Beispiel 7.5.35 Globale Variable und eine Funktion mit lokale Variablen
#!/usr/bin/python
# -*- coding: utf-8 -*-

globaleVar = ’gloooobal!!’

def eineFunktion():
print(’in der ersten Funktion: ’+globaleVar)

def zweiteFunktion():
globaleVar = ’aber eigentlich lokal!!’
print(globaleVar)

print(’außerhalb jeder Funktion: ’+globaleVar)


eineFunktion()
zweiteFunktion()
print(’außerhalb jeder Funktion: ’+globaleVar)

Jetzt sieht die Ausgabe so aus:

Beispiel 7.5.36 Ausgabe von globaler und lokaler Variablen


außerhalb jeder Funktion: gloooobal!!
in der ersten Funktion: gloooobal!!
aber eigentlich lokal!!
außerhalb jeder Funktion: gloooobal!!

Das Ergebnis: die Variable globaleVar innerhalb der Funktion zweiteFunktion ist etwas ganz
anderes als die Variable außerhalb der Funktion. Dafür ist diese Variable aber nur innerhalb der zweiten

Funktion“ bekannt. Das bezeichnet man als lokale Variable“. Außerhalb dieser Funktion wird wieder

die globale Variable benutzt.

191
KAPITEL 7. PROGRAMMSTRUKTUREN 7.5. FUNKTIONEN

Man kann dieses Verhalten verändern, indem man einer Variablen innerhalb einer Funktion das At-
tribut global“ zuordnet. Das sieht so aus:

Beispiel 7.5.37 Globale Variable und eine Funktion mit lokaler Variablen
#!/usr/bin/python
# -*- coding: utf-8 -*-

globaleVar = ’gloooobal!!’

def eineFunktion():
print(’in der ersten Funktion: ’+globaleVar)

def zweiteFunktion():
globaleVar = ’aber eigentlich lokal!!’
print(globaleVar)

def dritteFunktion():
global globaleVar
globaleVar = ’jetzt wieder global, weil in der 3. Fkt. "über-definiert"!!’

print(’außerhalb jeder Funktion: ’+globaleVar)


eineFunktion()
zweiteFunktion()
print(’außerhalb jeder Funktion: ’+globaleVar)
dritteFunktion()
eineFunktion()
print(’außerhalb jeder Funktion: ’+globaleVar)

Die Ausgabe steht hier unten:

Beispiel 7.5.38 Ausgabe von globaler und lokaler Variablen


außerhalb jeder Funktion: gloooobal!!
in der ersten Funktion: gloooobal!!
aber eigentlich lokal!!
außerhalb jeder Funktion: gloooobal!!
in der ersten Funktion: jetzt wieder global,
weil in der 3. Fkt. "über-definiert"!!
außerhalb jeder Funktion: jetzt wieder global,
weil in der 3. Fkt. "über-definiert"!!

192
KAPITEL 7. PROGRAMMSTRUKTUREN 7.5. FUNKTIONEN

7.5.7. Rekursive Funktionen


Die schärfsten Kritiker der Elche
waren früher selber welche.
(F.W. Bernstein 14 )
Was heißt rekursiv“? Schauen wir in einem Wörterbuch (geschrieben von Unix-Fachleuten) nach:

A CHTUNG

rekursiv: siehe rekursiv

Eine rekursive Funktion ist eine Funktion, die in ihrem Funktionskörper sich selbst aufruft.
Es ist manchmal wirklich sinnvoll, von innerhalb einer Funktion dieselbe Funktion, eventuell mit ei-
nem anderen Wert für den Parameter, nochmals aufzurufen. Das wird als Rekursion“ bezeichnet. Eines

der klassischen Beispiele (oder vielleicht das Beispiel dazu überhaupt) ist die Berechnung der Fakultät
einer Zahl. Zur Erinnerung: 5! ist die mathematische Schreibweise für 5-Fakultät und ist definiert als 5!
=1*2*3*4*5
Oder anders gesagt: 5! = 5 * 4! und 4! = 4 * 3!. Das heißt, um 5! auszurechnen, wär es geschickt, wenn
man vorher 4! ausgerechnet hätte. Und so weiter, bis man bei der 1 angelangt ist.

Beispiel 7.5.39 Fakultät rekursiv


def fak_rek(zahl):
if zahl == 1:
return 1
else:
return zahl*fak_rek(zahl-1)

Und der Aufruf dieser Funktion sieht ganz einfach aus:

Beispiel 7.5.40 Fakultät rekursiv


zahl = 12
print(fak_rek(zahl))

7.5.8. Funktionen als Parameter von Funktionen


Ja, geht das denn überhaupt? Und was soll das? Ich schreibe eine Funktion, und diese Funktion soll
intern etwas machen was in einer anderen Funktion bereits gelöst ist. Aber nicht immer soll das selbe
gemacht werden, sondern es können sich verschiedene Anforderungen ergeben.
Das soll an einem einfachen Beispiel gezeigt werden, das Text-Dateien bearbeitet. Als Beispiel-Text
nehmen wir die Datei [Link], die folgenden Text enthält:

Beispiel 7.5.41 Ein doofer Text mit vielen Pythons


Dieser Text ist so sinnvoll, wie die meisten Texte,
die aus der Ecke von Monty Python stammen.
Er soll nur demonstrieren,
dass man mit der Sprache Python
auch Monty Python zu Hilfe kommen kann.

14 Die Wahrheit über Arnold Hau, Frankfurt 1974, S. 87

193
KAPITEL 7. PROGRAMMSTRUKTUREN 7.5. FUNKTIONEN

In diesem Text sollen jetzt alle Zeilen, die Python“ enthalten, ausgegeben werden, wobei das Wort

Python“ in Großbuchstaben geschrieben werden soll.

Die dazugehörige Funktion, die das mit jeder einzelnen Zeile macht, ist schnell geschrieben. Gespei-
chert wird sie in der Datei [Link]

Beispiel 7.5.42 Gross-Schreiben eines Begriffs in einer Zeile


#!/usr/bin/python
# -*- coding: utf-8 -*-

def grossSchreiben(zeile, wort):


print([Link](wort, [Link]()))

Auch der Rahmen für das zeilenweise Bearbeiten einer Textdatei ist kein Hexenwerk:

Beispiel 7.5.43 Rahmen für Bearbeitung einer Text-Datei


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4

5 def textBearbeiten(????):
6 eingabeDatei = open(’[Link]’, ’r’)
7 wort = ’Python’
8 for eineZeile in [Link]():
9 if wort in eineZeile:
10 ????(eineZeile, wort)
11 [Link]()
12

13 if __name__ == ’__main__’:
14 textBearbeiten(????)
15

Auch wenn Dateien erst später im Text (siehe Kapitel 13 Dateizugriff“) behandelt werden, ist das

verständlich. Die beiden letzten Zeilen starten dieses Programm, falls es direkt aufgerufen wird und
nicht irgendwo importiert wird. Die Funktion textBearbeiten hat in der Parameterliste noch Fra-
gezeichen, denn noch weiß diese Funktion nicht, was sie überhaupt für eine Aufgaben bekommt. Als
erstes Aktion führt sie aber das Öffnen der Textdatei aus, das zu suchende Wort wird in der Variablen
wort abgelegt, und dann wird die gesamte Datei mittels readlines in eine Liste eingelesen. Diese
Liste wird in einer for“-Schleife abgearbeitet. Wenn das gesuchte Wort in einer Zeile auftaucht, dann

muss irgendwas mit dieser Zeile gemacht werden, aber da noch nicht klar ist, was, stehen hier auch
noch Fragezeichen.
Doch! Es ist doch klar, was mit jeder Zeile gemacht werden soll, nämlich das, was schon oben in
der Datei [Link] schon codiert wurde. Also muss ich doch nur noch ganz wenige Dinge
ändern.

1. die Funktion grossSchreiben muss aus der Datei [Link] importiert werden,
diesmal mit der Import-Option as eineFunktion“, damit die Funktion, die importiert wird, in-

nerhalb des Programms immer den selben Namen hat.
2. sie wird beim Aufruf von textBearbeiten mitgegeben
3. und im Kopf der Funktion textBearbeiten entgegengenommen
4. und dann aufgerufen, wenn das gesuchte Wort gefunden wurde.

Das Programm sieht also so aus:

194
KAPITEL 7. PROGRAMMSTRUKTUREN 7.5. FUNKTIONEN

Beispiel 7.5.44 Python wird gross geschrieben


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4 from grklSchreiben import grossSchreiben as eineFunktion
5

6 def textBearbeiten(eineFunktion):
7 eingabeDatei = open(’[Link]’, ’r’)
8 wort = ’Python’
9 for eineZeile in [Link]():
10 if wort in eineZeile:
11 eineFunktion(eineZeile, wort)
12 [Link]()
13

14 if __name__ == ’__main__’:
15 textBearbeiten(eineFunktion)
16

Das sieht umständlich aus? Es zahlt sich aber aus. Denn die Datei, die grossSchreiben enthält,
heißt ja [Link]. Schreib also dort eine weitere Funktion kleinSchreiben. Um diese
neue Funktion auf die Text-Datei loszulassen, muss nur eine Stelle in dem Programm geändert werden,
nämlich in der import“-Zeile! Wow!

[Link]. Seiteneffekte

Seiteneffekte sind etwas ganz böses!!!

7.5.9. Aufgaben zu Funktionen


1. Ein Programm soll in zwei Funktionen Fläche und Umfang eines Rechtecks ausrechnen.
2. Ein Programm soll in zwei Funktionen Oberfläche und Volumen eines Quaders ausrechnen.
3. Ein Programm soll in drei Funktionen Mantelfläche, Oberfläche und Volumen einer quadratischen
Pyramide berechnen.
4. Es sollen zwei Funktionen geschrieben werden, die jeweils das Minimum und Maximum eines
Paares zurückgeben, dazu dann ein Programm, das diese beiden Funktionen testet.
5. In einem Programm soll das Newton’sche Näherungsverfahren für die Berechnung einer Null-
stelle einer Funktion durchgeführt werden; hierbei sollen Funktion und Ableitungsfunktion als
Funktionen im Programm geschrieben werden.
6. Ein Programm soll eine Dezimalzahl in eine römische Zahl umwandeln.

7.5.10. lambda-Funktionen
lambda-Funktionen sind eigentlich lambda-Ausdrücke, aber sie arbeiten wie Funktionen. Sie werden
auch oft anonyme Funktionen“ genannt, denn diese Ausdrücke haben keinen Namen. Allerdings kann

ein lambda-Ausdruck einem Namen zugewiesen werden. Ein lambda-Ausdruck gibt immer einen Wert
zurück.
Die Syntax eines lambda-Ausdrucks besteht aus dem Schlüsselwort lambda, gefolgt von einer oder
mehreren Variablen, gefolgt von einem Doppelpunkt. Als letztes steht der Ausdruck, der etwas mit der
oder den Variablen macht. Als Beispiel soll hier eine Berechnung der nächsten Stundenzahl (12-Stunden-
Angaben) dienen; der Nachfolger von 6 ist 7, der Nachfolger von 12 ist aber 1.

195
KAPITEL 7. PROGRAMMSTRUKTUREN 7.5. FUNKTIONEN

Beispiel 7.5.45 Uhrzeiten (Stunden) addieren: der Ausdruck


lambda x: (x+1)%12
>>> (lambda x: (x+1)%12)(6)
7
>>> (lambda x: (x+1)%12)(12)
1

Dieser lambda-Ausdruck nimmt einen Wert für die Variable x entgegen, addiert 1 dazu und berechnet
den Rest modulo 12. Um diesen lambda-Ausdruck zu benutzen, muss er in Klammern geschrieben
werden, gefolgt von dem Wert des Parameters auch in Klammern.
Jetzt wird diesem Ausdruck ein Variablenname gegeben und dann aufgerufen.

Beispiel 7.5.46 Uhrzeiten (Stunden) addieren (benannt)


>>> stundeAddieren = lambda x: (x+1)%12
>>> stundeAddieren(6)
7
>>> stundeAddieren(12)
1

Elegant sind lambda-Ausdrücke als Parameter für andere Funktionen. Ein Beispiel ist die Sortierung
einer Liste nach einem etwas ungewöhnlichen Sortierbegriff. Die Sortierung einer Liste erlaubt als Pa-
rameter das Schlüsselwort key, dem eine Funktion zugewiesen wird, die die Regel für die Sortierung
enthält. Hier soll eine Namensliste nach dem letzten Buchstaben des Namens sortiert werden.

Beispiel 7.5.47 Liste sortieren nach letztem Buchstaben


>>> namensliste = [’Karl’,’Eva’,’Anne’,’Jens’,’Kim’,’Mary’]
>>> [Link](key = lambda x: x[-1])
>>> namensliste
[’Eva’, ’Anne’, ’Karl’, ’Kim’, ’Jens’, ’Mary’]

196
KAPITEL 7. PROGRAMMSTRUKTUREN 7.5. FUNKTIONEN

Jetzt soll ein Dictionary sortiert werden, das als Schlüssel einen Vornamen hat, als Wert eine Liste
bestehend aus dem Nachnamen und dem Wohnort. Sortiert werden soll nach dem Wohnort.

Beispiel 7.5.48 Geschachteltes Dictionary sortieren


>>> adrDic = {’Eva’:[’Maier’,’Stuttgart’], ’Anne’:[’Wahn’,’Pforzheim’],
’Karl’:[’Heim’,’Kassel’], ’Kim’:[’Mann’,’Hamburg’],
’Jens’:[’Schmidt’,’Berlin’], ’Mary’:[’Miller’,’Boston’]}
>>> adrListe = list(zip([Link](),[Link]()))
>>> [Link](key = lambda x: x[1][1])
>>> for einer in adrListe:
... print(einer[0]+’ ’+einer[1][0]+’ aus ’+einer[1][1])
...
Jens Schmidt aus Berlin
Mary Miller aus Boston
Kim Mann aus Hamburg
Karl Heim aus Kassel
Anne Wahn aus Pforzheim
Eva Maier aus Stuttgart

Also wird zuerst aus den Dictionary-Keys und den Dictionary-Values eine Liste gezippt (denn Dic-
tionaries kennen keine Sortierung). Diese Liste wird mittels eines Lambda-Ausdrucks sortiert und dann
ausgegeben. Der lambda-Ausdruck holt aus der Liste das 1. Element (die Liste, die aus Nachname und
Wohnort besteht) und daraus das 1. Element (den Wohnort).

197
Teil V.

Programmentwicklung und
Modularisierung

199
8. Programmentwicklung mit Test

8.1. Der Doctest

Da jetzt schon größere Programme geschrieben werden, vor allem, da jetzt auch Funktionen (Unter-
programme) eingebaut werden, ist es sinnvoll, dass der Entwickler sich schon beim Programmieren
Gedanken macht, was denn von einzelnen Funktionen erwartet wird. Auch da ist Python sehr hilfreich,
denn es kennt den doctest.
Der doctest funktioniert so, dass man in eine Funktion, direkt hinter den XrefId[?Funktionskopf?]
eine Zeichenkette in dreifachen Anführungszeichen schreibt. Diese Zeichenkette enthält in der ersten
Zeile nach 3 Größer-Zeichen einen möglichen Funktionsaufruf, darunter in der nächsten Zeile das er-
wartete Ergebnis.
Selbstverständlich kann man in diese Zeichenkette auch mehr als einen Test schreiben. Dann wieder-
holt sich wieder das Paar Zeile mit 3 Größer-Zeichen, gefolgt von einem möglichen Funktionsaufruf,

gefolgt von einer neuen Zeile mit dem erwarteten Ergebnis“.
Die Beschreibung, wie eine solche Funktion mit eingebautem Test aussieht, hört sich ziemlich umständlich
an. Ein Beispiel macht das aber hoffentlich klar. Es wird eine Funktion geschrieben, die bei 3 Zahlen (die
der Einfachheit halber der Größe nach aufsteigend eingegeben werden) überprüft, ob es sich um ein
pythagoräisches Zahlentripel handelt, ob also erste Zahl zum Quadrat plus zweite Zahl zum Quadrat
die dritte Zahl zum Quadrat ergibt.

Beispiel 8.1.1 Doctest (1. Versuch! Der tut noch nicht richtig!)
1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4

5 def pythTripel(a,b,c):
6 """
7 >>> pythTripel(3,4,5)
8 True
9 >>> pythTripel(3,4,6)
10 False
11 """
12

13 import doctest
14 [Link]()
15

Hier wird also getestet, ob (3,4,5) ein pythagoräisches Zahlentripel ist, und bei diesem Test wird ein
True erwartet, dann wird (3,4,6) getestet, und bei diesem Test wird ein False erwartet. Das alles steht
innerhalb der Zeichenkette. Das Hauptprogramm importiert doctest und ruft danach den Test auf.
Die Ausgabe ist noch nicht ganz das, was wir im Endeffekt erwarten. Aber das ist ja klar, denn die
Funktion pythTripel macht noch nichts.

201
KAPITEL 8. PROGRAMMENTWICKLUNG . . . 8.1. DER DOCTEST

Beispiel 8.1.2 Ausgabe des Doctest (1. Versuch! Der tut noch nicht richtig!
1

2 **********************************************************************
3 File "/home/fmartin/bin/python/L14a_Doctest/[Link]",
4 line 6, in __main__.pythTripel
5 Failed example:
6 pythTripel(3,4,5)
7 Expected:
8 True
9 Got nothing
10 **********************************************************************
11 File "/home/fmartin/bin/python/L14a_Doctest/[Link]",
12 line 8, in __main__.pythTripel
13 Failed example:
14 pythTripel(3,4,6)
15 Expected:
16 False
17 Got nothing
18 **********************************************************************
19 1 items had failures:
20 2 of 2 in __main__.pythTripel
21 ***Test Failed*** 2 failures.
22

Man kann es wohl sofort verstehen, was da passiert. Bei beiden Tests steht ja da, was erwartet wird
(Expected:), und danach kommt das traurige Ergebnis, dass gar nichts passiert ist: Got nothing.
Das Fazit: 2 Tests wurden durchgeführt, beide gingen schief (***Test Failed*** 2 failures).
Wir wissen ja schon, woran es liegt: die Funktion tut noch gar nichts! Das können wir schnell ändern,
indem wir einfach von der Funktion zurückgeben lassen, ob a2 +b2 == c2 ist, also entweder den Wert
True oder den Wert False.

Beispiel 8.1.3 Doctest (2. Versuch! Jetzt sollte ein sinnvolles Ergebnis erscheinen)
1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4

5 def pythTripel(a,b,c):
6 """
7 >>> pythTripel(3,4,5)
8 True
9 >>> pythTripel(3,4,6)
10 False
11 """
12 return a*a + b*b - c*c == 0
13

14 import doctest
15 [Link]()
16

Es folgt die Ausgabe:

Beispiel 8.1.4 Ausgabe des Doctest (Jetzt sollte ein sinnvolles Ergebnis erscheinen)
>>>
>>>

202
KAPITEL 8. PROGRAMMENTWICKLUNG . . . 8.1. DER DOCTEST

Die Ausgabe ist das absolute Nichts!!! Hm, was soll man damit anfangen? Ok, das ist zwar nicht das,
was sich der Programmieranfänger wünscht, aber es ist korrekt: es wird nichts ausgegeben, weil alle
Tests korrekt absolviert wurden.
Zum Glück gibt es aber noch einen Schalter, der auch in diesem Fall eine Ausgabe liefert, die uns
mehr Informationen bietet: verbose, also wörtlich (oder vielleicht eher geschwätzig).

Beispiel 8.1.5 Doctest (3. Versuch! Jetzt gibt es ein sinnvolles Ergebnis)
1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4

5 def pythTripel(a,b,c):
6 """
7 >>> pythTripel(3,4,5)
8 True
9 >>> pythTripel(3,4,6)
10 False
11 """
12 return a*a + b*b - c*c == 0
13

14 import doctest
15 [Link](verbose=True)
16

Jetzt sieht es doch schön aus:

Beispiel 8.1.6 Geschwätzige Ausgabe des Doctest


Trying:
pythTripel(3,4,5)
Expecting:
True
ok
Trying:
pythTripel(3,4,6)
Expecting:
False
ok
1 items had no tests:
__main__
1 items passed all tests:
2 tests in __main__.pythTripel
2 tests in 2 items.
2 passed and 0 failed.
Test passed.

Jetzt wird also ausdrücklich angegeben, was getestet wird, welches Ergebnis erwartet wird, und
zusätzlich die Information, dass der Test ok“ war.

8.1.1. Aufgaben zu doctest


1. Hol Dein Programm zur Lösung von quadratischen Gleichungen nochmals hervor, mach eine
Kopie davon und baue ein:
a) Eine Funktion, die die Diskriminante berechnet.

203
KAPITEL 8. PROGRAMMENTWICKLUNG . . . 8.1. DER DOCTEST

b) Eine Funktion, die eventuelle reelle Lösungen berechnet


c) In jede der beiden Funktionen einen doctest-Block, der das korrekte Funktionieren überprüft.

204
9. Module und Pakete

9.1. Mehr Mathematik


Mathematik in Python hat zu tun mit der Art, wie Mathematiker arbeiten. Wenn sie einen neuen Satz
gefunden haben, müssen sie dessen Richtigkeit beweisen. Aber kein Mathematiker1 wird bei Adam
und Eva anfangen oder bei den natürlichen Zahlen, sondern jeder wird auf anderen Sätzen aufbauen,
die andere Mathematiker zuvor bewiesen haben.
In Python müssen nicht nur John Cleese und Eric Idle zugange gewesen sein, sondern auch Mathema-
tiker: es gibt jede Menge Python-Sätze“, von denen man weiß2 , dass sie richtig sind. Damit muss man

als Python-Programmierer nicht mehr bei den kleinsten elementaren Anweisungen anfangen, wenn
man ein neues Programm schreibt, sondern kann vieles benutzen, was irgendwo schon vorhanden ist.
Und davon handelt dieses Kapitel.
Im Kapitel über Zahlen wurden einfache Rechenaufgaben an Python gestellt, Aufgaben auf Grund-
schulniveau. Python soll uns natürlich auch bei komplizierteren mathematischen Problemen eine Hilfe
sein. Probieren wir es also:

Beispiel 9.1.1 Fehler! Python kann kein Mathe!


>>> rad = 2.68
>>> umf = 2 * pi * rad
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
umf = 2 * pi * rad
NameError: name ’pi’ is not defined

Depp depperter! pi kennt doch jeder!


Der Grund dafür, dass sich Python hier weigert, unseren Befehl auszuführen, ist, dass Python außer
dem Kern der Sprache noch eine ganze Menge Module enthält. Diese Module sind nicht ständig präsent,
sondern sie müssen vielmehr vom Programmierer bei Bedarf zugeladen werden. Dies macht Sinn, denn
somit wird nur das in ein Programm eingebaut, was wirklich benötigt wird, und das spart Zeit bei
der Ausführung des Programms. Also laden wir uns mal das Mathematik-Modul hinzu, nein genauer:
laden wir uns aus dem Mathematik-Modul das hinzu, was wir brauchen:

Beispiel 9.1.2 Import aus der Mathematik-Bibliothek


>>> from math import pi
>>> umf = 2 * pi * rad
>>> print(umf)
16.8389366232

Warum haben wir nicht das gesamten Mathematik-Modul hinzugeladen? Es gibt 2 wichtige Gründe:
erstens packt man so wenig in ein Programm hinein, wie möglich, so viel, wie nötig, zweitens verein-
facht man sich so die Benennung von Variablen, Konstanten, Funktionen usw. Schauen wir einmal, was
passiert, wenn man sich das ganze Mathematik-Modul hinzulädt:

1 nicht vergessen: Mathematiker sind faul


2 weil es jemand bewiesen hat

205
KAPITEL 9. MODULE UND PAKETE 9.1. MEHR MATHEMATIK

Beispiel 9.1.3 Import der gesamten Mathematik-Bibliothek


>>> import math
>>> umf = 2 * pi * rad

Traceback (most recent call last):


File "<pyshell#12>", line 1, in <module>
umf = 2 * pi * rad
NameError: name ’pi’ is not defined

Es scheint nichts geschehen zu sein. pi ist immer noch nicht bekannt, obwohl jetzt alles aus math“

in unser Programm importiert wurde. Aber wenn man ein ganzes Modul importiert, verbleiben alle
Variablen, Konstanten, Funktionen usw. im Namensraum des Moduls, das heißt, dass die Variablen
und Funktionen des Moduls nur als Teile des Moduls bekannt sind. Ich muss also die Variable pi durch
den vollständigen Namen ansprechen:

Beispiel 9.1.4 Qualifzierter Bezeichner aus einer Bibliothek


>>> umf = 2 * [Link] * rad
>>> print(umf)
16.8389366232

Vollständiger Name bedeutet, dass dem Konstantennamen pi hier der Modul-Name math vorange-
stellt wird, durch einen Punkt voneinander getrennt.
Bisher wurden 2 Methoden des Modul-Aufrufs angesprochen:

• Der Import von einzelnen Elementen eines Moduls mit

from modul import dingsbums

• Der Import des gesamten Moduls mit

import modul

Es gibt noch eine dritte Methode, die hier erwähnt, vor der aber auch sehr gewarnt wird.

from modul import *

importiert alles aus dem Modul, aber alles wird in den Namensraum des aufrufenden Programms
übernommen. Das kann sehr gefährlich werden, wenn im aufrufenden Programm eine Variable oder
eine Funktion den selben Namen hat wie im Modul.
Im Modul math“ befindet sich natürlich noch viel mehr, aber was? Ganz einfach, fordern wir Hilfe

an:

206
KAPITEL 9. MODULE UND PAKETE 9.1. MEHR MATHEMATIK

Beispiel 9.1.5 Hilfe zum Mathematik-Modul


>>> help(math)
Help on module math:

NAME
math

FILE
/usr/lib/python2.5/lib-dynload/[Link]

MODULE DOCS
[Link]

DESCRIPTION
This module is always available. It provides access to the
mathematical functions defined by the C standard.

FUNCTIONS
acos(...)
acos(x)

Return the arc cosine (measured in radians) of x.

asin(...)
asin(x)

Return the arc sine (measured in radians) of x.

atan(...)
atan(x)

Return the arc tangent (measured in radians) of x.

atan2(...)
atan2(y, x)

Return the arc tangent (measured in radians) of y/x.


Unlike atan(y/x), the signs of both x and y are considered.

ceil(...)
ceil(x)

Return the ceiling of x as a float.


This is the smallest integral value >= x.

cos(...)
cos(x)

Return the cosine of x (measured in radians).

Natürlich enden die mathematischen Funktionen hier nicht beim cos“! (Aber mehr muss in diesen

Text nicht rein, und wer mehr Mathematik braucht, weiß jetzt, wie man nachschlägt!) Aber damit kann
man doch schon ganz ordentlich arbeiten.
Das Inhaltsverzeichnis des Moduls math zeigt nicht so detailliert an, aber der Überblick ist hilfreich,
denn so weiß man, wonach man weiter blättern kann:

207
KAPITEL 9. MODULE UND PAKETE 9.2. EIGENE MODULE

Beispiel 9.1.6 Inhaltsverzeichnis des Moduls math


>>> dir(math)
[’__doc__’, ’__file__’, ’__loader__’, ’__name__’, ’__package__’, ’__spec__’,
’acos’, ’acosh’, ’asin’, ’asinh’, ’atan’, ’atan2’, ’atanh’, ’ceil’,
’copysign’, ’cos’, ’cosh’, ’degrees’, ’e’, ’erf’, ’erfc’, ’exp’, ’expm1’,
’fabs’, ’factorial’, ’floor’, ’fmod’, ’frexp’, ’fsum’, ’gamma’, ’gcd’,
’hypot’, ’inf’, ’isclose’, ’isfinite’, ’isinf’, ’isnan’, ’ldexp’, ’lgamma’,
’log’, ’log10’, ’log1p’, ’log2’, ’modf’, ’nan’, ’pi’, ’pow’, ’radians’,
’sin’, ’sinh’, ’sqrt’, ’tan’, ’tanh’, ’tau’, ’trunc’]

Beispiel 9.1.7 Noch mehr Mathematik


>>> from math import cos, sin, pi
>>> x = 1.234
>>> sin(x)
0.94381820937463368
>>> sin(pi)
1.2246063538223773e-16
>>> cos(pi)
-1.0

9.2. Eigene Module


Das ist ja nett, dass jemand ein Mathematik-Modul zusammengestellt hat, denn das braucht man doch
tagtäglich. Aber Du und ich, wir sind ja wenigstens genau so genial und fleißig und sozial, und deswe-
gen wollen wir unsere eigenen Produkte, die wir so gut programmiert haben, dass wir oder jemand an-
derer sie wiederverwenden kann, für die Welt da draußen zur Verfügung stellen. Zuerst wollen wir sie
uns selber aber zur Verfügung stellen, das heißt, wir wollen sie wiederbenutzbar machen. Was müssen
wir dazu tun?
Ein Modul ist nichts anderes als ein Verzeichnis, dessen Inhalt vom Anwender (dem Programmierer
also) benutzt werden kann. Dazu sind allerdings noch ein paar Kleinigkeiten zu beachten. Besonders
wichtig ist, dass das Verzeichnis eine Datei init .py (das sind wieder mal 2 Unterstriche vor und 2
nach dem init) enthält. Aber machen wir das ganze mal schön der Reihe nach.

1. Gehen wir davon aus, dass wir in einigen Dateien verschiedene kleine Funktionen geschrieben
haben, mit denen wir zufrieden sind, weil sie gut funktionieren. Also schieben wir diese Dateien
(oder besser vielleicht eine Kopie davon) in ein eigenes Verzeichnis, das wir der Einfachheit halber
eigeneModule“ nennen wollen.

2. Unsere erste Datei heißt [Link] und enthält zwei Funktionen, nämlich die Funktion fak,
die die Fakultät einer Zahl ausrechnet, und die Funktion binko, die den Binomialkoeffizienten
zweier Zahlen ausrechnet.
3. Unsere zweite Datei heißt [Link] und enthält eine Funktion fibo, die die n-te Fibonacci-Zahl
ausrechnet.
4. Jetzt erstelle ich eine Datei init .py, die aus den beiden vorher genannten Dateien die 3 Funk-
tionen importiert. Der Inhalt der Datei init .py ist also:

Beispiel 9.2.1 Eine eigene Modul-Datei


from fakBinko import fak, binko
from fibo import fibo

208
KAPITEL 9. MODULE UND PAKETE 9.2. EIGENE MODULE

5. Jetzt ist alles hergerichtet. Ich kann jetzt in einer anderen Datei das Modul aufrufen. Das sieht so
aus:

Beispiel 9.2.2 Aufruf des eigenen Moduls


#!/usr/bin/python
# -*- coding: utf-8 -*-

import eigeneModule

print([Link](5))
print([Link](5))

Wie man sieht, wird jetzt das ganze Modul importiert. Danach stehen die Funktionen unter
• [Link]()
• bzw. unter [Link]()
zur Verfügung.
Das soll jetzt noch ein wenig mehr Benutzerfreundlichkeit bekommen. Das eigene Modul soll auch
noch einen Hilfetext erhalten, den man sich bei Bedarf anschauen kann. Der Hilfetext ist einfach eine
Zeichenkette in dreifachen Anführungszeichen. Also sieht die Modul-Datei init .py so aus:

Beispiel 9.2.3 Eine eigene Modul-Datei mit Hilfetext


#!/usr/bin/python
# -*- coding: utf-8 -*-
’’’
bisher vorhanden:
fak(z): berechnet die Fakultät von z
binko(n,k): berechnet n über k (Binomialkoeffizient
fibo(z): berechnet die n-te Fibonacci-Zahl
’’’
from fakBinko import fak, binko
from fibo import fibo

209
KAPITEL 9. MODULE UND PAKETE 9.3. PAKETE

Die Hilfe kann ich nach dem Import des Moduls aufrufen:

Beispiel 9.2.4 Aufruf der Hilfe zum eigenen Modul


>>> help(eigeneModule)

Help on package eigeneModule:

NAME
eigeneModule

FILE
/home/fmartin/bin/python/eigeneModule/__init__.py

DESCRIPTION
bisher voranden:
fak(z): berechnet die Fakultät von z
binko(n,k): berechnet n über k (Binomialkoeffizient)
fibo(z): berechnet die n-te Fibonacci-Zahl

PACKAGE CONTENTS
fakBinko
fibo

Dem, der unter Unix / Linux arbeitet, kommt diese Darstellung bekannt vor: so sehen alle Manuals3
aus. Das ist doch einfach schön, außerdem schön einfach und es freut den Lernenden, weil er etwas
wiedererkennt.
geschachtelte Struktur für Module muss noch geschrieben werden

9.3. Pakete
Ein Paket ist ein Verzeichnis, in dem verschiedene Module zusammengefasst sind. Damit Python das
als Paket erkennt, muss das Verzeichnis eine (eventuell leere) Datei init .py enthalten.
Wenn ich also ein Verzeichnis meinPaket anlege, das die Module SuperModul und SuperMario
enthält, binde ich einen dieser Module durch from meinPaket import SuperMario oder durch
import [Link] ein.

3 die man mit man(Befehl) aufruft

210
Teil VI.

Objektorientierte Programmierung

211
10. Klassen
10.1. Ist schon klasse, so eine Klasse!
Wie schon weiter oben bemerkt, ist Python eine objektorientierte Programmiersprache - nur hat das bis
hierher noch niemand gemerkt (oder fast kein Leser). Wenn wir bisher eine Variable deklariert haben,
dann dadurch, dass wir ihr einen Wert zugewiesen haben. Ohne uns darüber bewußt zu werden haben
wir aber dadurch gleichzeitig eine Zuordnung zu einer Klasse gemacht. Das ist einer der großen Vorteile
von Python: diese Sprache ist objektorientiert, aber man muss nicht objektorientiert programmieren, um
sie zu benutzen. Viele kleine Programme, zum Beispiel Werkzeuge, die man auf seinem eigenen Rechner
benutzt, schreibt ein geübter Programmierer in Python in ein paar Zeilen, ohne die Objektorientierung
auszupacken.
Was ist nun aber Objektorientierung? Und wozu dient sie?
Bei der objektorientierten Programmierung geht es darum, die für ein Programm relevanten Daten
möglichst naturgetreu“ abzubilden. Das Mittel dazu ist die Schaffung von Klassen, einer Beschreibung

von Eigenschaften gleichartiger Dinge. Diese gemeinsamen Eigenschaften werden in der Sprache der
Objektorientierung Attribute“ genannt. Diese gleichartigen Dinge haben aber nicht nur gemeinsame

Eigenschaften, sondern handeln“ auch gleich. Diese Handlungen von Elementen einer Klasse nennt

man Methoden“. Kurz gesagt:

• Attribute beschreiben Eigenschaften
• Methoden beschreiben Verhalten

Eine Klasse ist eine Vorlage für viele Objekte. In der Klasse wird beschrieben, wie jedes der zu erzeu-
genden Objekte aussehen soll und wie sich jedes der Objekte verhalten soll. Die Klasse selbst ist nur zu
dieser einen Sache zu gebrauchen: eines oder mehrere Objekte nach ihrem Muster zu bauen. Man kann
sich das vorstellen wie eine Ausstechform beim Plätzchenbacken. Die Form ist wirklich nicht geniess-
bar, weil sie aus Metall oder Plastik ist, aber was man damit aus dem Teig aussticht und backt: lecker,
lecker.
Damit kann man objektorientierte Programmierung so beschreiben: Attribute-Werte beschreiben den
Zustand eines Objekts, die Methoden verändern Attribute. Jedes Objekt behandelt die eigenen Daten
selbst und ist damit verantwortlich für seinen Zustand. Wie jedes Objekt diese Behandlung richtig
macht, weiß das Objekt, weil das Verhalten in der Klasse beschrieben ist.
Attribute und Methoden haben Namen. Man sollte sich von Anfang an darum bemühen, hier konse-
quente Schreibweisen einzuhalten. Wie für alle Variablennamen gilt auch für Attribute und Methoden,
dass sie klein geschrieben werden. Bei längeren Namen bietet sich die Schreibweise mit Unterstrich
(ein langer Variablen Name) oder die Kamel-Schreibweise (einLangerVariablenName) 1 an.
Die wichtigste Regel in Python für den Umgang mit Objekten und ihren Attribute und Methoden
folgt:

• Attribute eines Objektes werden mit [Link]


• und Methoden eines Objektes mit [Link] angesprochen.

Viel wichtiger aber noch ist Konsequenz bei der Wahl des Namens. Wie aus dem vorvorigen Absatz
hervorgeht, beschreiben Attribute Eigenschaften. Für einen Attributnamen nimmt man also Substantive.
Die Werte der Attribute hingegen sind oft Adjektive: das Attribut Farbe“, als Attribut natürlich klein

farbe geschrieben, kann die Werte rot, grün, gelb etc. annehmen.
Methoden aber beschreiben, was mit dem Objekt passiert, meistens sogar genauer: was mit einem At-
tribut des Objekts passiert. Aus diesem Grund nimmt man für Methodennamen Verben, in Fortführung
des obigen Beispiels also etwa eine Methode farbeAendern.
Das Thema gute Programme“ (angefangen bei gute Programme) muss jetzt noch ergänzt werden.

Ein Programm ist gut, wenn eine Klassen-Definition gut ist. Das ist der Fall, wenn eine Klasse viele
1 .. die so heißt, weil die Großbuchstaben wie Kamelhöcker nach oben herausstehen.

213
KAPITEL 10. KLASSEN 10.1. IST SCHON KLASSE, SO EINE KLASSE!

kurze Methoden besitzt. Die Methodennamen sollten Verben sein, und ein Verb beschreibt genau eine
Tätigkeit. Eine Methode ist also gut geschrieben, wenn sie eine Aktion ausführt; das bedeutet andersher-
um aber auch, dass eine Klassenbeschreibung, bei der eine Methode mehr als eine Tätigkeit durchführt,
schlecht ist.
Wenn man sich an diese elementaren Regeln hält:

1. Substantive für Attribute


2. Verben für Methoden

hat man für die objektorientierte Programmierung schon viel gewonnen und viele potentielle Feh-
lermöglichkeiten von vorneherein ausgeschaltet. Wenn man trotzdem irgendwann einen Namen hat,
der nicht diesen Regeln entspricht, hilft es oft, sich in ein Objekt der Klasse hineinzuversetzen. Ich

bin ein T-Shirt. Ich habe eine Farbe. Diese Farbe kann ich ändern.“ Das hört sich zwar am Anfang sehr
albern oder kindisch an, hilft aber, Strukturen zu erkennen.
Ein Beispiel für eine Klasse und die nach ihrem Muster erzeugten Objekte folgt hier: Stecker und
Steckdose sehen (in Deutschland) gleich aus und funktionieren gleich. Es reicht also, dass ich einmal all-
gemein beschreibe, wie Stecker und Steckdosen aussehen und was ihre Fähigkeiten sind. Dann benutze
ich diese Beschreibung, um einen Kühlschrank-Stecker, einen Computer-Stecker, einen Fön-Stecker zu
konstruieren. Wenn meine allgemeine Beschreibung fehlerfrei ist, dann bin ich sicher, dass alle speziel-
len Stecker fehlerfrei funktionieren.
Wenn man diese allgemeine Beschreibung macht — vorausgesetzt, man macht das sinnvoll und rich-
tig — erreicht man dadurch mehreres:

1. Es wächst zusammen, was zusammen gehört. (W. Brandt, aber in einem ganz anderen Zusam-
menhang!) Mit den Elementen einer Klasse kann man dann nicht mehr jeden Unfug anstellen,
sondern nur noch das, was in der Klasse als erlaubte Aktionen festgelegt wurde. Und man kann
einem Element einer Klasse auch keine Eigenschaften andichten, die nicht in der Klasse festgelegt
sind.
2. Und damit ist viel Code wiederverwertbar. Hat man erst einmal eine Klasse ordentlich beschrieben
und getestet, dann verhält die sich wie eine ganz nette schwarze Kiste: ich muss nicht mehr wissen,
was sich im Inneren der Kiste abspielt, sondern ich kann darauf vertrauen, dass sich ein Objekt,
das ich dieser Klasse zuordne, so verhält wie jedes andere Objekt dieser Klasse.
Vor allem ist Code damit wartbar geworden. Der Programmier-Anfänger hat oft die Vorstellung,
dass ein Programm einmal geschrieben und danach nie wieder angeschaut wird. Die Realität aber
ist, dass ein Programm geschrieben wird, die elementaren Eigenschaften, die gefordert wurden
abbildet, aber dass im Laufe der Zeit auffällt, dass z.B. Sonderfälle nicht behandelt wurden. Ebenso
merkt man erst im Laufe der Zeit, dass ein Programm, das von einem Benutzer interaktiv bedient
wird, nicht alle möglichen — damit sind vor allem die unmöglichen“ gemeint — Eingaben eines

Benutzers abfängt. Auch mit etwas, was ich als Programmierer gar nicht erwartet habe (soooo
doof kann doch kein Anwender sein), darf nicht dazu führen, dass etwas falsch bearbeitet wird
oder gar das Programm abbricht
Deswegen findet man oft verschiedene Versionen eines Programms, die sich dadurch unterschei-
den, dass mögliche Fehler ausgemerzt wurden — und andere dafür auftauchen. Deswegen ist es
wichtig, dass ein Programm nicht nur vom Programmierer zur Zeit des Programmierens verstan-
den wird, sondern auch noch Monate später und vielleicht von jemand ganz anderem gelesen
werden kann.
3. Von einer Klasse kann man andere Klassen herleiten. Das bedeutet, dass eine Klasse viele Eigen-
schaften einer anderen Klasse erben kann. Und schon wieder hat man Zeit und Arbeit gespart.

Lies noch einmal nach, was weiter oben über gute Programme geschrieben wurde, und Du verstehst,
dass Objektorientierung dazu beiträgt, Dinge einfach zu halten: einfach in der Bedeutung leicht“, aber

auch einfach in der Bedeutung nur einmal“.

In der Theorie der objektorientierten Programmierung haben sich im Laufe der Zeit Vorgehensweisen
und Richtlinien ergeben, die durch die folgenden Fachbegriffe im Zusammenhang mit objektorientierter
Programmierung beschrieben werden.

1. Vererbung: ein Stecker ist noch sehr allgemein; spezielle Stecker sind Kaltgerätestecker, Monitor-
Stecker, USB-Stecker. Alles, was prinzipiell Stecker auszeichnet, gilt für jeden dieser speziellen
Stecker; aber es gilt für jeden dieser Stecker noch ein bißchen mehr. Das heißt, dass jeder spezielle

214
KAPITEL 10. KLASSEN 10.1. IST SCHON KLASSE, SO EINE KLASSE!

Stecker die allgemeinen Eigenschaften vom allgemeinen Stecker erbt und noch ein paar spezielle
Eigenschaften hinzugefügt werden.
2. Kapselung: alles, was zu einer Klasse gehört, soll (oder manchmal: kann) nur von Objekten dieser
Klasse angesprochen werden. Von außen sind die Eigenschaften der Klasse versteckt“, und damit

gerät man weniger in Gefahr, mit Variablen irgendeinen Unsinn zu machen.
3. Polymorphie heißt Vielgestaltigkeit“. Damit ist gemeint, dass sich eine Eigenschaft in verschie-

denen Klassen verschieden zeigen kann. Ein ganz einfaches Beispiel haben wir schon weiter oben
kennen gelernt, nur ist das gar nicht richtig aufgefallen. Das Zeichen + bezeichnet eine Eigen-
schaft von Zahlen, aber auch eine von Zeichenketten. In Verbindung mit Zahlen bedeutet es die
aus der Schule gewohnte Addition; in Verbindung mit Zeichenketten bedeutet es das Hinterein-
anderschreiben.

Die erste Klasse erstellen wir in IDLE. Das erlaubt es uns, wirklich interaktiv mit der Klasse her-
umzuspielen. Außerdem ist der Editor von IDLE da sehr hilfreich, wie man gleich sehen wird. Eine
Klasse wird durch das Schlüsselwort class festgelegt. Als nächstes benötigt eine Klasse einen Namen.
Während es in der Umgangssprache die Klasse der Autos“ heißt, ist es in der (Python-)Programmierung

üblich, dass der Name einer Klasse ein Substantiv im Singular ist. Hier darf zum ersten Mal ein Groß-
buchstabe am Anfang eines Namens verwendet werden: Klassennamen beginnen mit einem Groß-
buchstaben. Die erste Klasse ist eine Erweiterung des Grusses, den man am Anfang jeder Program-
miertätigkeit an die Welt schicken sollte, das Hallo, Welt“. Jetzt wird es aber in der Form aufgebohrt,

dass eine Person einen Vornamen hat (das soll das einzige Attribut der Person sein) und die Welt höflich
grüßen kann, indem sie auch den eigenen Namen nennt (das wird die einzige Methode der Person).

Beispiel 10.1.1 Klasse Person


1

2 class Person:
3 def __init__(self, vorname):
4 [Link] = vorname
5

6 def gruessen(self):
7 print(’Ein freundliches "Hallo Welt" von ’+[Link]=
8

Nach dem Schlüsselwort class steht hier der Klassenname Person.


Es folgt eine besondere Methode, der Konstruktor2 der Klasse. Der Konstruktor erstellt nach dem
Abbild der Klasse spezielle Instanzen, auch Objekte genannt. In Python heißt er immer init . (Das
sind jeweils 2 Unterstriche vorne und hinten.) Innerhalb des Konstruktors wird der übergebene Vorna-
me (siehe gleich den nächsten Absatz) an die jeweilige Instanz der Klasse übergeben. Auf die jeweilige
Instanz wird immer mit dem Namen self zugegriffen.3 Jede Methode einer Klasse muss als ersten
Parameter diesen Verweis auf das jeweilige Objekt enthalten. Die Methode gruessen ist hoffentlich
klar!
Wer konstruieren kann, sollte auch zerstören können. Wer mit anderen objektorientierten Program-
miersprachen gearbeitet hat, weiß, dass es dort auch einen Destruktor“ gibt. Er vernichtet alles, nach-

dem ein Objekt aufgehört hat zu existieren. In Python gibt es diesen Destruktor auch, aber man braucht
ihn (in 99 Prozent der Fälle) nicht; es kann sogar unangenehm werden, wenn man ihn fälschlich benutzt.
Deswegen wird er hier auch nicht aufgeführt, und falls jemand doch meint, ihn benützen zu müssen:
nachschlagen!
Jetzt sollen tatsächlich ein paar Objekte nach diesem Muster erstellt werden: Objekte sind in diesem
Fall echte Personen. Los gehts:

2 Genau genommen ist das kein Konstruktor. Wer dazu mehr wissen will, sollte die Dokumentation zu Python nachlesen. Aber
die hier beschriebene Methode kommt einem Konstruktor sehr nahe. Also belassen wir es bei dieser Bezeichnung.
3 self entspricht dem this in den Sprachen C und Java. Anders als in diesen Sprachen ist aber self kein reserviertes Wort in
Python. Das bedeutet, dass man durchaus einen anderen Namen dafür benutzen könnte. Aber das sollte man auf keinen Fall
machen. self ist zwar nur eine Empfehlung, aber eine sehr massive!!
Also eher: Du willst doch nicht etwa statt self etwas anderes nehmen??!!!??!!!

215
KAPITEL 10. KLASSEN 10.1. IST SCHON KLASSE, SO EINE KLASSE!

Beispiel 10.1.2 Objekte der Klasse Person können was!


1

2 >>> ich = Person(’Martin’)


3 >>> [Link]()
4 Ein freundliches "Hallo Welt" von Martin
5 >>> hannah = Person(’Hannah’)
6 >>> [Link]()
7 Ein freundliches "Hallo Welt" von Hannah
8

Ja, auch mir tut das weh, dass da als Anweisung [Link]()“ steht, [Link]()“ wäre schöner.
” ”
Aber auch hier gilt eine Vereinbarung: so wie Klassennamen immer ein Substantiv im Nominativ sin-
gular sein sollen, sollen Methodennamen immer ein Verb im Infinitiv sein. Zuerst wird eine Person ich
angelegt. Die benötigt als Attribut einen Vornamen, und der wird als Parameter beim Aufruf der Klas-
se Person mitgegeben. Innerhalb des Konstruktors init wird der Wert dieses Parameters an die
Instanz übergeben, die für das jeweilige Objekt immer mit self angesprochen wird. Die einzige Me-
thode der Klasse wird auch an jedes Objekt weitergegeben, so dass jetzt ich es beherrscht, die Welt zu
gruessen. Das geschieht dadurch, dass der Methodenname durch einen Punkt an den Objektnamen
angehängt wird.
Das zweite Beispiel soll ein bißchen mehr sein und können (sein: das sind die Attribute; können: das
sind die Methoden) Bauen wir also die Klasse Angestellter, die als Attribute den Namen, das Alter,
das Einkommen und die Berufsbezeichnung hat.

Beispiel 10.1.3 Klasse Angestellter


1

2 >>> class Angestellter:


3 def __init__(self, name, alter, einkommen, berufsbezeichnung):
4 [Link] = name
5 [Link] = alter
6 [Link] = einkommen
7 [Link] = berufsbezeichnung
8 >>> ich = angestellter(’Martin Schimmels’, 54, 20000, ’Programmierer’)
9 >>> ek = angestellter(’Eckard Krauss’, 39, 30000, ’Dozent’)
10 >>> print([Link])
11 Martin Schimmels
12 >>> print([Link])
13 Eckard Krauss
14

Und hier folgen die Erläuterungen!


Eine Klasse ist wie eine Backform: ein Muster für das, was man herstellen will. Unser Muster für den
Angestellten sagt uns, dass ein Angestellter immer einen Namen, ein Alter, ein Einkommen und eine
Berufsbezeichnung hat. Die Methode, mit der man aus dem Muster ein tatsächliches Objekt konstruiert,
heißt Konstruktor. Eine Klasse wird immer erstellt durch

Beispiel 10.1.4 Klassendefinition


class Pipapo:
????
????

Und nochmal: die Klasse macht nichts, ist nichts ... außer einem Muster. Objekte nach dem Muster
werden erstellt durch

216
KAPITEL 10. KLASSEN 10.1. IST SCHON KLASSE, SO EINE KLASSE!

Beispiel 10.1.5 Objektdefinition


objekt1 = Pipapo()
objekt2 = Pipapo()
objekt3 = Pipapo()

Aber die 3 Objekte verhalten sich jetzt so, wie es in der Klassenbeschreibung (im Muster) vorgegeben
wurde.
Der Konstruktor einer Klasse heißt in Python immer init . (Das sind zwei Unterstriche vor dem
init und zwei nach dem init.) Wenn ich jetzt also ein Objekt der Klasse Angestellter erzeugen will,
stelle ich eine Variable bereit, in diesem Fall die Variable ich, der ich mitteile, dass sie einen Angestell-
ten darstellen soll. In Klammern werden die Attribute angegeben, also Name, Alter, Einkommen und
Berufsbezeichnung. Damit wird jetzt der Konstruktor der Klasse aufgerufen. Der Konstruktor hat in
Klammern ebenfalls die Attribute angegeben, damit er das, was übergeben wird, in Empfang nimmt.
Zusätzlich hat der Konstruktor immer als ersten Parameter den Parameter self, der eine Referenz auf
sich selbst ist, in diesem Fall also auf die Variable ich. Jetzt werden die übergebenen Parameterwerte
an Attribute des Objekts weitergegeben, was durch die Anweisung [Link] = name geschieht. Da-
mit wird jetzt dem Attribut name des Objekts ich der Wert Martin Schimmels“ zugeordnet. Dass das

tatsächlich funktioniert hat, sieht man einige Zeilen später, wenn der Wert von [Link] ausgegeben
wird. Der ist tatsächlich vorhanden und lautet Martin Schimmels“.

Objektorientierung geht heute - im ersten Jahrzehnt des 21. Jahrhunderts - nicht mehr ohne UML.
UML ist die Abkürzung für Unified Modelling Language“. Und genau das ist es: eine vereinheitliche

Modellierungssprache für die Modellierung von Klassen (und anderem mehr. Aber das gehört jetzt
nicht hierher!).
Modellieren wir also unsere zweite Klasse: Menschen!! (Aber abstrahieren wir soviel es geht, damit
unser Modell einer Klasse überschaubar bleibt.) Menschen haben einen Vornamen, einen Nachnamen,
ein Geburtsdatum. Geburtsdatum und Vorname sind unveränderlich (wenn man mal von Künstlern
und Verbrechern absieht), der Nachname kann sich ändern. Menschen haben einen Wohnort, und der
ändert sich (wahrscheinlich häufiger als der Nachname). So! Das reicht!
In UML sieht das Modell der Klasse Mensch, wie es oben beschrieben wurde, so aus:

Abbildung 10.1. Klassendiagramm Mensch

So schön kann ich natürlich nicht von Hand zeichnen. Es gibt zum Glück jede Menge UML-Programme,
die eine Klasse modellieren und das Ergebnis schön darstellen. Das oben stehende Diagramm wurde
mit dem Programm Umbrello“ gezeichnet, das aus der Linux-Ecke kommt und Open Source“ ist, also
” ”
nichts kostet.
Eine kurze Beschreibung dessen, was man da sieht: im oberen kleinen Kasten steht der Name der
Klasse. Vereinbarung: Klassennamen beginnen mit einem Großbuchstaben. Im zweiten Kasten stehen
die Eigenschaften, in UML Attribute genannt, die durch ein vorangestelltes Minus-Zeichen markiert
sind.
In unserem Fall sind die 3 Attribute allesamt Zeichenketten, auf englisch strings“. Im dritten Kas-

ten stehen die Aktionen, in UML Methoden genannt, gekennzeichnet durch ein vorangestelltes Plus-
Zeichen. Hier ist Umbrello in Aktion, das nicht für eine bestimmte Programmiersprache entworfen wur-
de, sondern für viele Programmiersprachen einsetzbar ist. In fast allen anderen Programmiersprachen
muss man bei der Deklaration einer Variablen angeben, welchen Typ diese Variable zum Inhalt haben
soll, etwa, dass die Variable vom Typ int“ (für integer, also ganze Zahlen) oder vom Typ string“ (für
” ”

217
KAPITEL 10. KLASSEN 10.2. OBJEKTE, OBJEKTE, OBJEKTE

Zeichenketten) sein soll. In Python ist das anders: durch die erste Zuweisung eines Wertes an eine Va-
riable wird die Klasse festgelegt, zu der die Variable gehört. In unserem Fall muss man den Methoden
jeweils eine Information mitgeben: der Methode nachnamenAendern den neuen Nachnamen, der Me-
thode umziehen den neuen Wohnort. Das, was einer Methode mitgegeben wird, wird als Parameter
der Methode bezeichnet.
Methoden sind im Prinzip nicht viel anders als Funktionen, mit dem Unterschied, dass sie an eine
Klasse gebunden sind und nur von Objekten der Klasse benutzt werden können. Das kommt Dir wohl
schon bekannt vor, denn oben haben wir den Begriff des Namensraums eingeführt. Damit kann dieser
Sachverhalt auch anders beschrieben werden: der Namensraum einer Methode ist die Klasse. Ebenso
gilt, dass ein Attribut eine Variable ist, die als Namensraum die Klasse hat.
Eigentlich sollte es überflüssig sein, das nochmals zu erwähnen, aber trotzdem: Attribute sind Varia-
blen, Methoden sind Funktionen, also beginnen Attribut- und Methodennamen mit einem Kleinbuch-
staben.

10.2. Objekte, Objekte, Objekte


Jede Klasse (für uns im Moment jedenfalls!) hat eine Methode, mit Hilfe derer nach dem Modell der
Klasse ein Objekt erzeugt werden kann: den Konstruktor. Das ist wie im Sandkasten: ich habe ein Burg-
Förmchen, Sand rein, glatt streichen, umkippen, und schon habe ich eine Burg.
Dabei machen wir es von Anfang an richtig! Die Klasse kommt in eine eigene Datei, die wir clMensch.
py nennen werden. 4 Und machen wir es Schritt für Schritt, wobei wir nach jedem Schritt testen werden,
ob alles richtig funktioniert.

Beispiel 10.2.1 Eine erste Klasse


class Mensch():
def __init__(self, vorname, nachname, gebdat, wohnort):
[Link] = vorname
[Link] = nachname
[Link] = gebdat
[Link] = wohnort

Eine Klasse wird definiert durch das Schlüsselwort class, gefolgt vom Klassennamen, gefolgt von
einem Paar runder Klammern, in denen eventuell Parameter dieser Klasse stehen. Unsere Klasse be-
kommt im ersten Schritt nur einen Konstruktor. Der Konstruktor wird bei uns mit 5 Parametern aufge-
rufen: der erste Parameter, self, ist Pflicht!!!!! Danach folgen die Parameter, in denen die Werte für jedes
Attribut, das wir deklariert haben, dem Konstruktor mitgegeben werden. In den folgenden Zeilen wird
dem Attribut, gekennzeichnet durch das vorangestellte self, der jeweilige Parameter zugewiesen. An
einem Beispiel verdeutlicht: der Parameter vorname aus der runden Klammer hinter dem Konstruktor-
Namen init wird dem Attribut der Klasse, dem [Link] zugewiesen.
Man sieht: Methoden sehen fast aus wie Funktionen. Es sind auch Funktionen, die aber nicht von
überall gesehen werden und von überall benutzt werden dürfen. Es sind Funktionen, die an Klassen
bzw. an Objekte dieser Klassen gebunden sind.
Die wichtigste Regel im Umgang mit Klassen in Python wiederhole ich also nochmals:

• alles, was zu einer Klasse gehört, egal ob Attribut oder Methode, wird geschrieben als
– [Link]
– bzw. [Link]
Klassenname und Attribut bzw. Klassenname und Methode werden durch einen Punkt voneinan-
der getrennt. Das Schlüsselwort self verweist immer auf das aktuelle Objekt der Klasse, oft auch
die Instanz der Klasse“ genannt.

4 Es ist eine gute Sache, sich anzugewöhnen, Klassen-Dateien immer mit cl“ (oder cl “ oder kl“ oder so ähnlich) anfangen
” ” ”
zu lassen. Sollte man später beruflich in einem Unternehmen programmieren dürfen, wird es sowieso Vorgaben geben, wie
Dateien zu benennen sind.

218
KAPITEL 10. KLASSEN 10.2. OBJEKTE, OBJEKTE, OBJEKTE

Zum Test benötigen wir dann noch eine zweite Datei, [Link], in der wir ein Objekt der
Klasse erzeugen.

Beispiel 10.2.2 Aufruf der Klasse (Erzeugung eines Objektes)


#!/usr/bin/python
from clMensch import Mensch

ich = Mensch(’Martin’, ’Schimmels’, ’01.01.1988’, ’Rottenburg’)

Zuerst muss das Aufruf-Programm natürlich die Klasse importieren. Erst dann kann man ein Objekt
konstruieren. Dazu vergebe ich einen Variablennamen und teile dem Programm mit, dass die Variable
jetzt ein Platzhalter für ein Objekt der Klasse Mensch ist. Das geschieht durch den Zuweisungsoperator
=. Dadurch wird der Konstruktor der Klasse aufgerufen, und der benötigt eine ganze Menge Parameter.
Der Parameter self muss nicht übergeben werden, aber die anderen vier: Vorname, Nachname, Ge-
burtsdatum und Wohnort. So! Objekt erzeugt!!! (Und wenn ich das Programm jetzt laufen lasse, tut sich
gar nichts.)
Also wird unser aufrufendes Programm in einem zweiten Schritt erweitert:

Beispiel 10.2.3 Erzeugung eines Objekts


#!/usr/bin/python
from clMensch import Mensch

ich = Mensch(’Martin’, ’Schimmels’, ’01.01.1988’, ’Rottenburg’)


print([Link]())
print([Link]())

So! Jetzt tut sich etwas: Vor- und Nachname werden angezeigt.
Das, was ich im oben stehenden Beispiel gemacht habe, ist eigentlich absolut verboten: ausserhalb
der Klassen-Definition soll man nicht auf Attribute zugreifen. (Siehe dazu weiter unten bei XrefId[??]
Sichtbarkeit.) Für den Zugriff auf Attribute soll man immer eigene Methoden schreiben. Hier (und das
wiederholt sich für viele unserer Beispiele) schreiben wir also einfach eine Methode, die alle Attribute
eines Objektes und damit das ganze Objekt anzeigt. Damit ändert sich unsere Klassendatei so:

Beispiel 10.2.4 Die erste Klasse mit einer richtigen Methode


class Mensch():
def __init__(self, vorname, nachname, gebdat, wohnort):
[Link] = vorname
[Link] = nachname
[Link] = gebdat
[Link] = wohnort

def anzeigen(self):
print([Link]+’ ’+[Link])
print([Link])
print([Link])

Die Regel von oben wurde auf jeden Fall eingehalten: Die Methode anzeigen führt genau eine Auf-
gabe aus (nämlich die, die durch den Methoden-Namen vorgegeben ist). Also muss dazu nicht mehr
gesagt werden. Nach der Erzeugung eines Objektes greife ich jetzt also nicht mehr auf die Attribute des
Objektes zu, sondern auf eine Methode!

219
KAPITEL 10. KLASSEN 10.2. OBJEKTE, OBJEKTE, OBJEKTE

Beispiel 10.2.5 Aufruf der Methode anzeigen


#!/usr/bin/python
from clMensch import Mensch

ich = Mensch(’Martin’, ’Schimmels’, ’01.01.1988’, ’Rottenburg’)


[Link]()

Wie angekündigt, Schritt für Schritt, wird das Programm unserem Modell angepasst. Die Klasse
braucht eine Methode nachnamenAendern.

Beispiel 10.2.6 Eine weitere Methode


class Mensch():
def __init__(self, vorname, nachname, gebdat, wohnort):
[Link] = vorname
[Link] = nachname
[Link] = gebdat
[Link] = wohnort

def anzeigen(self):
print([Link]+’ ’+[Link])
print([Link])
print([Link])

def nachnamenAendern(self, nachname):


[Link] = nachname

Das sollte klar sein. Auf zum Test!


Das Aufruf-Programm muss jetzt natürlich noch geändert werden, damit man die Änderung der
Klasse sieht.

Beispiel 10.2.7 Aufruf der neuen Methode


#!/usr/bin/python
from clMensch import Mensch

ich = Mensch(’Martin’, ’Schimmels’, ’01.01.1988’, ’Rottenburg’)


[Link]()
[Link](’Meier’)
[Link]()

Und auch das funktioniert prima!


Und zum (vorläufigen) Schluß wird jetzt noch die Methode umziehen geschrieben und getestet.
Zuerst also die Änderung an der Klasse Mensch:

220
KAPITEL 10. KLASSEN 10.3. KAPSELUNG

Beispiel 10.2.8 Noch eine Methode


1

2 class Mensch():
3 def __init__(self, vorname, nachname, gebdat, wohnort):
4 [Link] = vorname
5 [Link] = nachname
6 [Link] = gebdat
7 [Link] = wohnort
8

9 def anzeigen(self):
10 print([Link]+’ ’+[Link])
11 print([Link])
12 print([Link])
13

14 def nachnamenAendern(self, nachname):


15 [Link] = nachname
16

17 def umziehen(self, wohnort):


18 [Link] = wohnort
19

Und dann das Aufruf-Programm:

Beispiel 10.2.9 Aufruf der neuen Methode


1

2 #!/usr/bin/python
3 from clMensch import Mensch
4

5 ich = Mensch(’Martin’, ’Schimmels’, ’01.01.1988’, ’Rottenburg’)


6 [Link]()
7 [Link](’Meier’)
8 [Link]()
9

10 [Link](’Ammerbuch’)
11 [Link]()
12

10.3. Kapselung
Die bisherigen Beispiele haben aus Sicht der Objektorientierung noch einen gewaltigen Fehler. Auf At-
tribute kann man beim obigen Beispiel von außerhalb der Klasse zugreifen, das heißt, dass in einem
Programm folgendes möglich ist:

Beispiel 10.3.1 Keine Geheimnisse (leider)


1

2 #!/usr/bin/python
3 from clMensch import Mensch
4

5 ich = Mensch(’Martin’, ’Schimmels’, ’01.01.1988’, ’Rottenburg’)


6 print([Link])
7

Auf Attribute sollte nur mittels Methoden der Klasse zugegriffen werden. Python hat hier eine Schwäche,
denn anders als in anderen objektorientierten Sprachen wird bei der Deklaration einer Variablen weder
ein Datentyp noch eine Sichtbarkeitsklausel angegeben.

221
KAPITEL 10. KLASSEN 10.3. KAPSELUNG

Es gibt 3 Stufen der Sichtbarkeit:

1. public: Jeder darf von überall alles mit dem Attribut machen.
2. protected: nur die eigene Klasse und daraus abgeleitete Klassen dürfen auf ein solches Attribut
zugreifen.
3. private: Die stärkste Sicherheit: hier darf nur die eigene Klasse auf das Attribut zugreifen.

In Python wird die Sichtbarkeitsstufe durch vorangestellte Unterstriche dargestellt. Das ist leider keine
absolute Sicherheit gegen einen missbräuchlichen Zugriff auf ein Attribut. Die Regeln in Python lauten:

1. Ein Attribut ohne einen führenden Unterstrich ist public, also auch von außerhalb der Klasse les-
bar und veränderbar.
2. Ein Attribut mit genau einem führenden Unterstrich ist protected; damit ist noch keine Sicherheit
gegeben, aber der Programmierer tut damit kund, dass man auf dieses Attribut nicht von außer-
halb zugreifen sollte.
3. Ein Attribut mit genau zwei führenden Unterstrichen ist private; dieses Attribut ist von außerhalb
der Klasse nicht sichtbar und kann somit nur durch Methoden der Klasse gelesen und geschrieben
werden.

Tabelle 10.1. Sichtbarkeit und Kapselung


Stufe Beispiel
public vorname
protected vorname
private vorname

Also sollte man dieses Progrämmchen noch richtig machen (richtig im Sinne der Objektorientierung).
Die Attribute werden privat“ gemacht, so dass nur noch über die Methoden zugegriffen werden kann.

Beispiel 10.3.2 Private Attribute


1

2 class Mensch():
3 def __init__(self, vorname, nachname, gebdat, wohnort):
4 self.__vorname = vorname
5 self.__nachname = nachname
6 self.__gebdat = gebdat
7 self.__wohnort = wohnort
8

9 def anzeigen(self):
10 print(self.__vorname+’ ’+self.__nachname)
11 print(self.__gebdat)
12 print(self.__wohnort)
13

14 def nachnamenAendern(self, nachname):


15 self.__nachname = nachname
16

17 def umziehen(self, wohnort):


18 self.__wohnort = wohnort
19

Die 3 Attribute vorname, nachname und wohnort haben im Konstruktor zwei Unterstriche voran-
gestellt. In der Methode anzeigen und den beiden Methoden, die Wohnort und Nachname ändern,
müssen natürlich dann auch die Attribute mit vorangestelltem Unterstrich angesprochen werden.
Das aufrufende Programm ändert sich gar nicht — außer, dass in der Zeile nach dem ersten Anzeigen
ein Fehler eingebaut wird: es wird nämlich der Versuch gemacht, auf das Attribut nachname von
außerhalb der Klasse zuzugreifen.

222
KAPITEL 10. KLASSEN 10.4. SETTER UND GETTER? ODER DOCH . . .

Beispiel 10.3.3 Aufruf mit Fehler


1

2 #!/usr/bin/python
3 from clMensch import Mensch
4

5 ich = Mensch(’Martin’, ’Schimmels’, ’01.01.1988’, ’Rottenburg’)


6 [Link]()
7 print(ich.__nachname) # Das geht schief! Wenn diese Zeile
8 # entfernt wird, läuft das Programm
9 # natürlich einwandfrei.
10

11 [Link](’Meier’)
12 [Link]()
13

14 [Link](’Ammerbuch’)
15 [Link]()
16

10.4. Setter und Getter? Oder doch lieber nicht?


In anderen objektorientierten Programmiersprachen ist es gute Sitte, für jedes Attribut zwei in der Regel
sehr kurze Methoden zu schreiben:
1. den Getter, meistens get attribut genannt, der nichts anderes macht, als den Wert des Attributs
zu lesen und zurückzugeben
2. den Setter, meistens set attribut genannt, der nichts anderes macht, als dem Attribut einen
neuen Wert zuzuweisen.
Python-Programmierer sind da nicht so strikt. Aber es soll nicht verschwiegen werden, dass das auch
in Python viele Programmierer realisieren.

223
KAPITEL 10. KLASSEN 10.4. SETTER UND GETTER? ODER DOCH . . .

Zuerst einmal schreibe ich die Methoden und rufe eine davon direkt auf.

Beispiel 10.4.1 Getter und Setter (einfach)


1

3 class Hund():
4 def __init__(self, rasse, name):
5 self.set_rasse(rasse)
6 self.set_name(name)
7

8 def get_rasse(self):
9 return [Link]
10

11 def set_rasse(self, rasse):


12 [Link] = rasse
13

14 def get_name(self):
15 return [Link]
16

17 def set_name(self, name):


18 [Link] = name
19

20

21 if __name__ == ’__main__’:
22 w = Hund(’Dackel’, ’Waldi’)
23 h = Hund(’Schäferhund’, ’Hasso’)
24 print(w.get_name())
25 print(h.get_name())
26

27

Das liefert die erwartete Ausgabe:

Beispiel 10.4.2 Ausgabe von Getter und Setter (einfach)


1

3 Waldi
4 Hasso
5

Python-Programmierer machen das aber mit Eigenschaften, das heißt über das Schlüsselwort property
werden den jeweiligen Attributen Methoden zugeordnet.

224
KAPITEL 10. KLASSEN 10.4. SETTER UND GETTER? ODER DOCH . . .

Beispiel 10.4.3 Getter und Setter (mittels property)


1

3 #!/usr/bin/python
4

5 class Hund():
6 def __init__(self, rasse, name):
7 self.unsichtbare_rasse = rasse
8 self.unsichtbarer_name = name
9

10 def get_rasse(self):
11 return self.unsichtbare_rasse
12

13 def set_rasse(self, rasse):


14 self.unsichtbare_rasse = rasse
15

16 def get_name(self):
17 return self.unsichtbarer_name
18

19 def set_name(self, name):


20 self.unsichtbarer_name = name
21

22 name = property(get_name, set_name)


23 rasse = property(get_rasse, set_rasse)
24

25 if __name__ == ’__main__’:
26 w = Hund(’Dackel’, ’Waldi’)
27 h = Hund(’Schäferhund’, ’Hasso’)
28 print([Link])
29 print([Link])
30 [Link] = ’Titan’
31 print(’Hasso heißt jetzt ’+[Link])
32

33

Wird jetzt einem Attribut ein Wert zugewiesen, wird der Setter des Attributs aufgerufen; der Getter
wird aufgerufen, wenn der Name des Attributs abgefragt wird. Das liefert die erwartete Ausgabe:

Beispiel 10.4.4 Ausgabe von Getter und Setter mit Hilfe von property
1

3 Waldi
4 Hasso
5 Hasso heißt jetzt Titan
6

Das ist jetzt besonders wichtig, wenn wir uns wieder der Sichtbarkeit von Attributen zuwenden.
Erinnerst Du Dich noch? Sonst lies noch mal nach! Hier kommt also die obige Klasse, nur mit der
Veränderung, dass jetzt beide Attribute durch vorangestellte doppelte Unterstriche privat geworden
sind.

225
KAPITEL 10. KLASSEN 10.4. SETTER UND GETTER? ODER DOCH . . .

Beispiel 10.4.5 Getter und Setter mit Hilfe von property und private Attribute
1

3 #!/usr/bin/python
4

5 class Hund():
6 def __init__(self, rasse, name):
7 self.__unsichtbare_rasse = rasse
8 self.__unsichtbarer_name = name
9

10 def get_rasse(self):
11 return self.__unsichtbare_rasse
12

13 def set_rasse(self, rasse):


14 self.__unsichtbare_rasse = rasse
15

16 def get_name(self):
17 return self.__unsichtbarer_name
18

19 def set_name(self, name):


20 self.__unsichtbarer_name = name
21

22 name = property(get_name, set_name)


23 rasse = property(get_rasse, set_rasse)
24

25 if __name__ == ’__main__’:
26 w = Hund(’Dackel’, ’Waldi’)
27 h = Hund(’Schäferhund’, ’Hasso’)
28 print([Link])
29 print([Link])
30 [Link] = ’Titan’
31 print(’Hasso heißt jetzt ’+[Link])
32 print(’Das nächste funktioniert nicht,
33 \ndenn "__unsichtbarer_name" ist wirklich unsichtbar’)
34 print(’Hasso heißt jetzt ’+h.__unsichtbarer_name)
35

36

Und hier folgt die Ausgabe des Programms:

Beispiel 10.4.6 Ausgabe mit Hilfe von property und privaten Attributen
1

3 Waldi
4 Hasso
5 Hasso heißt jetzt Titan
6 Das nächste funktioniert nicht,
7 denn "__unsichtbarer_name" ist wirklich unsichtbar
8 Traceback (most recent call last):
9 File "./cl_HundPropertySichtbarkeit.py", line 33, in <module>
10 print(’Hasso heißt jetzt ’+h.__unsichtbarer_name)
11 AttributeError: ’Hund’ object has no attribute ’__unsichtbarer_name’
12

13

226
KAPITEL 10. KLASSEN 10.5. STATISCHE METHODEN

10.5. Statische Methoden


Manchmal ist es wünschenswert, dass nicht nur bestimmte Objekte eine bestimmte Fähigkeit in einer
bestimmten Ausprägung haben. Vielmehr sollen alle Objekte dieselbe Fähigkeit haben, und die Klasse
als solche auch. Das nennt man statische Methode. Ein Beispiel verdeutlicht das.

Beispiel 10.5.1 Statische Methode


1

3 >>> class Mensch(object):


4 def wohnen():
5 print(’jeder Mensch wohnt irgendwo’)
6 wohnen = staticmethod(wohnen)
7 def __init__(self, vn, nn):
8 [Link] = vn
9 [Link] = nn
10 def anzeigen(self):
11 print([Link], [Link])
12 [Link]()
13

14

15 >>> [Link]()
16 jeder Mensch wohnt irgendwo
17 >>> x = Mensch(’Martin’, ’Schimmels’)
18 >>> [Link]()
19 Martin Schimmels
20 jeder Mensch wohnt irgendwo
21 >>>
22

23

In Zeile 6 wird die Methode wohnen zu einer statischen Methode gemacht. In Zeile 15 sieht man,
dass der Aufruf der Methode als Methode der Klasse funktioniert. Nachdem in Zeile 17 ein Objekt der
Klasse erzeugt wurde, wird in der darauffolgenden Zeile die Methode wohnen des Objekts aufgerufen,
und auch das funktioniert.

227
KAPITEL 10. KLASSEN 10.6. VERERBUNG (OHNE . . .

Die oben angegebene Schreibweise ist anschaulich und verständlich. Mittels Dekoratoren“ kann die

Schreibweise verkürzt werden:

Beispiel 10.5.2 Statische Methode


1

2 >>> class Mensch(object):


3 @staticmethod
4 def wohnen():
5 print(’jeder Mensch wohnt irgendwo’)
6 def __init__(self, vn, nn):
7 [Link] = vn
8 [Link] = nn
9 def anzeigen(self):
10 print([Link], [Link])
11 [Link]()
12

13 >>> [Link]()
14 jeder Mensch wohnt irgendwo
15 >>> x = Mensch(’Hannah’, ’Schimmels’)
16 >>> [Link]()
17 Hannah Schimmels
18 jeder Mensch wohnt irgendwo
19

10.6. Vererbung (ohne Erbschaftssteuer)


Richtig interessant, weil arbeitssparend, wird Objektorientierung aber erst, wenn Klassen ihre Eigen-
schaften vererben. Dazu bohren wir das Beispiel mit den Menschen ein wenig auf. Nehmen wir also
typische Menschen an einer Schule, von der es wieder zwei Klassen gibt: die Schüler und die Lehrer.
Die sind alle Menschen, haben also alle Eigenschaften der oben bearbeiteten Klasse Mensch, nämlich,
wir erinnern uns, Vornamen, Nachnamen, Geburtsdatum und Wohnort.
Zusätzlich haben Schüler noch die Eigenschaft klasse, das heißt sie gehen in beispielsweise die
11. Klasse. Außerdem können Schüler eine Aktion durchführen: die neue Methode heißt versetzen,
und bedeutet, dass ein Schüler am Ende des Schuljahres von der 11. Klasse in die 12. Klasse wechselt
(hoffentlich!). Um das Modell einfach zu halten und nachher auch die Methode versetzen schnell zu
programmieren, ist die Klassenangabe nur eine Zahl zwischen 1 und 13 (keine Parallelklassen wie z.B.
12d oder 11/1).
Lehrer hingegen haben die zusätzliche Eigenschaft, dass sie ein Unterrichtsfach“ unterrichten (um

das Modell einfach zu halten, beschränken wir uns hier auf ein Fach). Außerdem hat ein Lehrer noch
ein Deputat, d.h. eine bestimmte Anzahl Stunden, die er unterrichten muss.

228
KAPITEL 10. KLASSEN 10.6. VERERBUNG (OHNE . . .

Und so sieht das Modell in UML aus:

Abbildung 10.2. Klassendiagramm Schueler

Hier werden 3 Klassen abgebildet, und diese Klassen sind durch Pfeile miteinander verbunden. Der
Pfeil zeigt immer auf die übergeordnete Klasse, von der die untergeordneten Klassen etwas (in diesem
Beispiel: alles!) erben. Umbrello spricht hier von einer gerichteten Assoziation“. Die Eigenschaften, die

die untergeordneten (in UML: abgeleiteten) Klassen erben, müssen dort nicht mehr aufgeführt werden.
Alles Gute kommt von oben!
Die Realisierung in Python sieht so aus:

Beispiel 10.6.1 Abgeleitete Klasse


1

2 class Mensch():
3 def __init__(self, vorname, nachname, gebdat, wohnort):
4 [Link] = vorname
5 [Link] = nachname
6 [Link] = gebdat
7 [Link] = wohnort
8

9 def anzeigen(self):
10 print([Link]+’ ’+[Link])
11 print([Link])
12 print([Link])
13

14 def nachnamenAendern(self, nachname):


15 [Link] = nachname
16

17 def umziehen(self, wohnort):


18 [Link] = wohnort
19

20 class Schueler(Mensch):
21 def __init__(self, vorname, nachname, gebdat, wohnort, klasse):
22 Mensch.__init__(self, vorname, nachname, gebdat, wohnort)
23 [Link] = klasse
24

25 def versetzen(self):
26 [Link] += 1
27

Auch hier gibt es eine kurze Erläuterung: in die selbe Datei wie die Klasse Mensch schreibe ich die
Klasse Schueler (keine Umlaute!!!). Um Python anzuweisen, dass es Schueler als eine Unterklasse von

229
KAPITEL 10. KLASSEN 10.6. VERERBUNG (OHNE . . .

Mensch auffassen soll, wird dem Klassennamen in Klammern die Bezeichnung der Oberklasse mitge-
teilt. Der Konstruktor nimmt wieder alle Attribute in Empfang, aber reicht gleich die Attribute, die die
Klasse Schueler von der Klasse Mensch erbt, weiter an den Konstruktor von Mensch nach dem Mot-
to: Mach Du das doch, Du weißt doch schon, wie das geht.“ Das geschieht durch den ausdrücklichen

Aufruf des Konstruktors der Oberklasse: Mensch. init (...). Einzig die (Schul-)Klasse muss hier
in der Unterklasse Schueler initialisiert werden.
Die neue Methode ist wohl ganz leicht zu verstehen. Es wird der Kurzschluß-Operator für die Addi-
tion benutzt.
Jetzt brauchen wir wieder ein Aufruf-Programm, mit dem man die neue Klassen-Definition testen
kann. Hier müssen zwei Klassen-Definitionen importiert werden, die durch Komma voneinander ge-
trennt werden:

Beispiel 10.6.2 Aufruf der abgeleiteten Klasse


1

2 #!/usr/bin/python
3 from clMensch import Mensch, Schueler
4

5 ich = Mensch(’Martin’, ’Schimmels’, ’01.01.1988’, ’Rottenburg’)


6

7 [Link]()
8 [Link](’Meier’)
9 [Link]()
10 ###
11 # ab hier gibt es was neues
12 ###
13 thomas = Schueler(’Thomas’, ’Renz’, ’12.11.1989’, ’Dettenhausen’, 11)
14

15 [Link]()
16

17 [Link]()
18 [Link]()
19

10.6.1. Klassen neuen Stils


Mit dem Übergang zu Version 2.2 von Python hat Guido van Rossum neue Klassen“ eingeführt. Um

eine stringentere Ordnung zu erhalten, gibt es jetzt auch in Python eine Basis-Klasse, die Klasse object
(leider ist der Klassenname wirklich kleingeschrieben!!). Um eine Klasse neuen Stils zu erstellen, muss
also die Klasse, die wir selber als Basisklasse unserer Anwendung gebaut haben, von object erben.
Mit diesen Klassen neuen Stils ist es auch einfacher möglich, sich auf die Methoden der Elternklas-
sen zu beziehen. Im folgenden Beispiel wird eine Vererbung über 2 Generationen gezeigt, bei der die
Kind-Generation von der Eltern-Generation und diese von der Großeltern-Generation erbt. Jede der drei
Generationen hat eine Methode anzeigen, und so sieht das aus, wenn das benutzt wird.

230
KAPITEL 10. KLASSEN 10.6. VERERBUNG (OHNE . . .

Beispiel 10.6.3 Drei Ebenen von Klassen im neuen Stil


1

2 class Ebene1(object):
3 def anzeigen(self):
4 print(’das ist Ebene 1, die Grosseltern-Ebene’)
5

6 class Ebene2(Ebene1):
7 def anzeigen(self):
8 print(’das ist Ebene 2, die Eltern-Ebene’)
9

10 class Ebene3(Ebene2):
11 def anzeigen(self):
12 print(’das ist Ebene 3’)
13 print(’aber ich kenne auch meine Eltern und Grosseltern’)
14 super(Ebene3, self).anzeigen()
15 super(Ebene2, self).anzeigen()
16

17 >>> eineEbene = Ebene3()


18 >>> [Link]()
19 das ist Ebene 3
20 aber ich kenne auch meine Eltern und Grosseltern
21 das ist Ebene 2, die Eltern-Ebene
22 das ist Ebene 1, die Grosseltern-Ebene
23

Die Methode anzeigen der Klasse Ebene3 kann einfacher geschrieben werden, da an der Stelle des
Aufrufs klar ist, was die super“-Ebene ist:

Beispiel 10.6.4 Vereinfachte Methode bei eindeutiger Superklasse
1

2 class Ebene3(Ebene2):
3 def anzeigen(self):
4 print(’das ist Ebene 3’)
5 print(’aber ich kenne auch meine Eltern und Grosseltern. SCHAUT!!!’)
6 super().anzeigen()
7 super(Ebene2, self).anzeigen()
8

231
KAPITEL 10. KLASSEN 10.6. VERERBUNG (OHNE . . .

10.6.2. Weiter mit der Klasse Mensch


Wenn wir jetzt zurückgehen zum Beispiel aus dem vorigen Kapitel, sehen wir dass die Klassenbeschrei-
bung verändert wird:

Beispiel 10.6.5 Klasse Mensch im new style


1

2 class Mensch(object):
3 def __init__(self, vorname, nachname, gebdat, wohnort):
4 [Link] = vorname
5 [Link] = nachname
6 [Link] = gebdat
7 [Link] = wohnort
8

9 def anzeigen(self):
10 print([Link]+’ ’+[Link])
11 print([Link])
12 print([Link])
13

14 def nachnamenAendern(self, nachname):


15 [Link] = nachname
16

17 def umziehen(self, wohnort):


18 [Link] = wohnort
19

In Bezug auf Vererbung ändert sich auch etwas: der Aufruf der Methoden der Oberklasse soll nicht
mehr durch das Voranstellen des Oberklassen-Namens geschehen, sondern durch die Benutzung der
Funktion super. super bekommt immer 2 Parameter: der erste Parameter ist der Name der (aktuellen)
Unterklasse, der zweite Parameter ein Verweis auf das aktuelle Objekt, also self. Das hört sich kom-
pliziert an, vereinfacht aber das Vorgehen wieder erheblich; es bedeutet nämlich umgangssprachlich
formuliert wieder Hey, Objekt, Du weißt doch, von was Du erbst, also ruf mal das oder das von Deiner

Oberklasse auf“. Die Intelligenz steckt also wieder in der Klasse.
Aus dem vorigen Kapitel wird hier der Aufruf des Konstruktors der Oberklasse neu formuliert.
Zusätzlich bekommt die Unterklasse aber eine Methode anzeigen, um zu demonstrieren, dass auch
eine beliebige Methode mit Hilfe von super aufgerufen werden kann. Das Beispiel aus dem vorigen
Kapitel mit der abgeleiteten Klasse Schueler verändert sich zu:

232
KAPITEL 10. KLASSEN 10.7. METHODEN ÜBERSCHREIBEN

Beispiel 10.6.6 Abgeleitete Klasse mit Super-Aufruf (new style)


1

2 class Mensch():
3 def __init__(self, vorname, nachname, gebdat, wohnort):
4 [Link] = vorname
5 [Link] = nachname
6 [Link] = gebdat
7 [Link] = wohnort
8

9 def anzeigen(self):
10 print([Link]+’ ’+[Link])
11 print([Link])
12 print([Link])
13

14 def nachnamenAendern(self, nachname):


15 [Link] = nachname
16

17 def umziehen(self, wohnort):


18 [Link] = wohnort
19

20 class Schueler(Mensch):
21 def __init__(self, vorname, nachname, gebdat, wohnort, klasse):
22 super(Schueler, self).__init__(vorname, nachname, gebdat, wohnort)
23 [Link] = klasse
24

25 def versetzen(self):
26 [Link] += 1
27

28 def anzeigen(self):
29 super(Schueler, self).anzeigen()
30 print(’in Klasse:’, [Link])
31

Was noch zu tun ist:

• Der Schüler benötigt noch eine Methode anzeigen. Dabei sollte selbstverständlich die Methode
anzeigen von Mensch benutzt werden, so weit das möglich ist.
• Die Klasse Lehrer muss noch geschrieben werden.

10.7. Methoden überschreiben


10.7.1. Selbstgeschriebene Methoden
Das nächste Element der Objektorientierung, das die Arbeit erleichtert, ist das Überschreiben von Me-
thoden. Darunter versteht man, dass eine abgeleitete Klasse von ihrer Superklasse nicht mehr alle Me-
thoden erbt, sondern dass manche Methoden vererbt werden, andere in der abgeleiteten Klasse neu
geschrieben werden. Das soll an einem einfachen Beispiel gezeigt werden. Personen können in diesem
Beispiel entweder Männer oder Frauen sein, und diese Personen können verschieden angeredet werden:
eine Person, die nicht näher beschrieben wird, wird ganz formlos mit einem freundlichen Hallo“ und

ihrem Namen angeredet, eine Frau und ein Mann mit einem höflichen Guten Tag“ und einem Frau“
” ”
bzw. Herr“ vor ihrem Namen.

Nach so vielen Informationen über Objektorientierung in Python verstehen die Meisten den Quelltext
des Beispiels beim Durchlesen, oder?

233
KAPITEL 10. KLASSEN 10.7. METHODEN ÜBERSCHREIBEN

Beispiel 10.7.1 Überschreiben der Methode anzeigen


1

2 #!/usr/bin/python
3

4 class Person():
5 def __init__(self, name, anrede):
6 [Link] = name
7 [Link] = anrede
8 def namenAusgeben(self):
9 return [Link]
10 def anreden(self):
11 return [Link] +’, ’+[Link]
12

13 class Herr(Person):
14 def anreden(self):
15 return [Link]+’, Herr ’+[Link]
16

17

18 class Frau(Person):
19 def anreden(self):
20 return [Link]+’, Frau ’+[Link]
21

22 m = Person(’Martin’, ’Hi hello’)


23 print([Link]())
24 d = Frau(’Schreiner’, ’Einen wunderschönen guten Tag’)
25 print([Link]())
26 d = Herr(’Maler’, ’Guten Tag’)
27 print([Link]())
28

Beispiel 10.7.2 Ausgabe des Beispiels mit verschiedenen anzeigen-Methoden


1

2 Hi hello, Martin
3 Einen wunderschönen guten Tag, Frau Schreiner
4 Guten Tag, Herr Maler
5

Jede der 3 Klassen hat eine Methode anzeigen. Die Methode einer der beiden spezialisierten Klassen
Herr bzw. Frau überschreiben die allgemeinere Version. Das bedeutet, dass die speziellere Version von
anzeigen benutzt wird, wenn ein Objekt der spezielleren Klasse angelegt wird und diese Methode
aufgerufen wird.

10.7.2. Magische“ Methoden



Spezielle Methoden, nämlich Methoden, die zu den grundlegenden Klassen wie zum Beispiel der Klasse
der ganzen Zahlen gehören, können auch überschrieben werden. Das zeige ich an einem Beispiel aus
der Elementarmathematik.
Ganze Zahlen (wie auch rationale Zahlen) können addiert werden. Dafür gibt es die Operation +. Das
war ja eine der ersten Aktionen, die in diesem Skript angesprochen wurden:

Beispiel 10.7.3 Endlich wieder rechnen!


1

2 >>> 3+4
3 7
4

234
KAPITEL 10. KLASSEN 10.7. METHODEN ÜBERSCHREIBEN

Aber rationale Zahlen werden ja (oft, sinnvollerweise) als Brüche geschrieben. Da ist der Algorithmus
für die Addition ja nicht der selbe wie bei der Addition von natürlichen oder ganzen Zahlen:
1. größten gemeinsamen Teiler der beiden Nenner suchen; das ist der Hauptnenner
2. beide Brüche durch eventuelles Erweitern auf den Hauptnenner bringen
3. die beiden Zähler addieren
Das kann auch in einer anderen Reihenfolge gemacht werden, und das ist für die Programmierung
etwas einfacher.
1. Zähler des ersten Bruchs mit dem Nenner des zweiten Bruchs multiplizieren, dazu das Produkt
von Zähler des zweiten Bruchs mit Nenner des ersten Bruchs addieren
2. dieses Produkt ist der neue Zähler
3. die beiden Nenner miteinander multiplizieren
4. dieses Produkt ist der neue Nenner
5. dieser neue Bruch ist noch nicht gekürzt
Diese zweite Reihenfolge ist in dem unten dargestellten Programmschnipsel gezeigt. Die Methode kuerzen
sollte jeder selbst programmieren und wird hier nicht gezeigt.
Wichtig ist hier, dass die Methode addieren“ der anderen Zahlen überschrieben wird. Diese Methode

ist die magische Methode add (wieder 2 Unterstriche vor und nach dem Wort add“). Wenn ich jetzt

in meiner Klasse Bruch eine neue Methode add codiere, dann kann ich zwei Objekte der Klasse
Bruch einfach durch ein einfaches Pluszeichen addieren.

Beispiel 10.7.4 Ein Schnipsel der Klasse Bruch


1

3 class Bruch():
4 def __init__(self, zaehler=0, nenner=1):
5 [Link] = zaehler
6 [Link] = nenner
7

8 def __add__(self, b2):


9 [Link] = [Link] * [Link] + [Link] * [Link]
10 [Link] = [Link] * [Link]
11 [Link]()
12 return Bruch([Link], [Link])

Das wird jetzt so aufgerufen:

Beispiel 10.7.5 Aufruf: 2 Brüche addieren


1

2 z1 = int(input(’Zähler eingeben (ganze Zahl): ’))


3 n1 = int(input(’Nenner eingeben (ganze Zahl): ’))
4 b1 = Bruch(z1, n1) # wird verändert
5

6 z2 = int(input(’Zähler eingeben (ganze Zahl): ’))


7 n2 = int(input(’Nenner eingeben (ganze Zahl): ’))
8 b2 = Bruch(z2, n2)
9

10 erg = b1+b2
11

Als erstes sollte man jetzt eine Methode kuerzen schreiben; dazu benötigt man noch den Euklid’schen
Algorithmus für die Suche des größten gemeinsamen Teilers.

235
KAPITEL 10. KLASSEN 10.8. GUTE PROGRAMME ... WANN . . .

Dann drängt es sich geradezu auf, dass man eine eigene Methode anzeigen für Brüche codiert. Und
dann wird jeder wahrscheinlich die anderen Methoden für die Subtraktion, Multiplikation und Division
von Brüchen schreiben wollen!
Hier kommt noch eine Liste der magischen Methoden, die überschrieben werden können:

• Vergleichs-Methoden
– eq : gleich
– ne : ungleich
– gt : größer
– ge : größer oder gleich
– lt : kleiner
– le : kleiner oder gleich

• mathematische Methoden
– add : addieren (auch für Strings!)
– sub : subtrahieren
– mul : multiplizieren
– truediv : dividieren ( echtes“, d.h. 7 / 4 = 1.75)

– floordiv : Ganzzahldivision (d.h. 7 / 4 = 1)
– mod : Modulus (Rest bei der Ganzzahldivision, d.h. 7 % 4 = 3)
– pow : potenzieren (3**4 = 81)

• sonstige
– str : gibt die Zeichenkette zurück
– len : gibt die Länge des Objektes zurück

10.8. Gute Programme ... wann schreibt man objektorientiert?


Schon mehrmals in diesem Text wurde das Thema gute Programme“ angsprochen. Was heißt gute
” ”
Programme“ im Zusammenhang mit Objektorientierung? Und wann sollte man ein objektorientiertes
Programm schreiben? Das ist eine Frage, die ich mir im Laufe der letzten Jahre immer wieder gestellt
habe. Als Programmierer bin ich auch nicht objektorientiert auf die Welt gekommen“. Und viele Pro-

gramme, die ich für den Hausgebrauch geschrieben habe, vor allem kleine Hilfsmittel, die mir die Be-
dienung des eigenen Computers erleichtern sollten, habe ich über Jahre (eher über Jahrzehnte!) mit der
Sprache perl“ geschrieben. Das ist eine schöne Sprache, in der Tierwelt der Programmiersprachen die

eierlegende Wollmilchsau“: man kann alles mit ihr machen, vor allem auch jede Schweinerei. Aber lei-

der versteht man nach ein paar Tagen schon nicht mehr, was man da alles in perl geschrieben hat. Perl
ist von Natur aus nicht objektorientiert.
Nachdem ich Python kennengelernt habe, habe ich begonnen, auch solche Tools für den Hausge-
brauch in Python zu schreiben. Wahrscheinlich gehen viele Programmierer so vor: wenn ich von einer
neuen Sprache höre, überlege ich, wie ich ein Programm, das ich in einer anderen Sprache geschrie-
ben habe, in der neuen Sprache realisieren würde: Programme, die mit Dateien lesen, schreiben oder
verändern; solche, die ganze Dateisysteme bearbeiten; Programme, die auf Datenbanken zugreifen; Pro-
gramme, die irgendetwas im Internet machen; und vieles mehr.
Auf einmal wurden meine Hilfsmittel verständlich. Und mit der Benutzung von Python wurde es mir
auch klar, warum manchmal Objektorientierung zum besseren Verständnis von Programmen beiträgt.
Ein paar dieser Gedanken sollen hier festgehalten werden.

1. Das, was ich selber oft nicht mache, wenn ich mal schnell“ eine Lösung suche, sollte bei umfang-

reicheren Programmen am Anfang stehen: ein gutes Design. Ich selber male wirklich nicht gerne
UML-Diagramme ... aber es hilft!!!
2. Wenn ein Programm zu lang wird, überlege, ob es nicht innerhalb des Programms zusammenhän-
gende Aktionseinheiten“ gibt, die Du zusammenfassen kannst.

236
KAPITEL 10. KLASSEN 10.8. GUTE PROGRAMME ... WANN . . .

3. Das ist oft dann der Fall, wenn ein Ding ganz wenige (oder bestenfalls nur eine) Eigenschaft hat
und diese Eigenschaft immer auf eine sehr ähnliche (oder bestenfalls auf die selbe) Art verändert
wird. Das hört sich doch sehr nach einer Klasse mit einem (oder ganz wenigen) Attribut(en) und
mit einer Methode an.
4. Wenn Du das Gefühl hast, dass zwei Dinge in Deinem Programm sehr ähnlich aussehen und sich
sehr ähnlich verhalten, überlege Dir, ob das eine Ding nicht eine Spezialisierung (oder in der an-
deren Richtung eine Verallgemeinerung) des anderen Dings ist. Wenn Du diese Überlegung total
oder ansatzweise mit ja“ beantworten kannst, spricht vieles dafür, dass Du es hier mit Vererbung

zu tun hast.
5. Wenn Du Dich für Objektorientierung entschieden hast, und dann feststellst, dass Deine Klassen-
datei sehr groß geworden ist, überleg Dir noch einmal, ob das alles, was in der Klassendatei steht,
wirklich zu EINER Klasse gehört oder ob nicht noch eine weitere Klasse mitspielt.
6. Das ist vor allem dann wahrscheinlich, wenn innerhalb der Klassendatei auf Daten zugegriffen
wird, die keine Attribute der Klasse sind.
7. Schau Dir nochmal alle Bezeichner durch: sind Attributnamen wirklich Substantive und Metho-
dennamen wirklich Verben im Infinitiv? Mach das auch in die andere Richtung: suche alle Verben
und überprüfe, ob das wirklich alles Methoden sind; suche alle Substantive und checke, ob das al-
les Attribute sind. Wenn nicht, ändere das schnell. Und wenn nach der Änderung sich irgendetwas
eher seltsam anhört: dann ist wahrscheinlich irgendetwas eher faul!!!

237
11. Ein etwas längeres Programm
11.1. Objektorientierter Entwurf
Stellen wir uns vor, wir sollten ein Programm schreiben, das Konten einer Bank verwaltet. Den Entwurf
wollen wir wieder in einzelnen Schritten durchführen, wobei wir am Anfang sehr grob vorgehen, und
später das Erarbeitete verfeinern. In diesem Sinn legen wir für die Klasse Konto zuerst nur die nötigsten
Attribute und Methoden fest.

Das Besondere an einem Konto fällt (hoffentlich) sofort auf: der Inhaber des Kontos ist ein Mensch!
(Als Aussage des alltäglichen Lebens ist das wirklich keine Weisheit. Als Aussage in unserem Klassen-
Entwurf ist das etwas völlig Neues!) In der Sprache UML ausgedrückt: eines der Attribute der Klasse
Konto ist ein Objekt der Klasse Mensch. Dies wird Aggregation genannt.

239
KAPITEL 11. EIN ETWAS LÄNGERES . . . 11.2. OBJEKTORIENTIERTE . . .

11.2. Objektorientierte Programmierung

11.2.1. Die Klasse Konto


Die Umsetzung der Klassendefinition in Python sieht so aus:

Beispiel 11.2.1 Die Klasse Konto“


1

2 from clMensch import Mensch
3

4 class Konto(object):
5

6 def __init__(self, ktoNr, vorname, nachname, gebdat, wohnort,


7 ktoStand, zinssatz):
8 [Link] = ktoNr
9 [Link] = Mensch(vorname, nachname, gebdat, wohnort)
10 [Link] = ktoStand
11 [Link] = zinssatz
12

13 def einzahlen(self, betrag):


14 pass
15

16 def auszahlen(self, betrag):


17 pass
18

19 def verzinsen(self, zinssatz):


20 pass
21

Das wird wieder in einer eigenen Datei gespeichert, in clKonto.

11.2.2. Das aufrufende Programm


Zuerst wird der Mensch importiert, denn den benötigen wir für den Inhaber. Der Konstruktor weist die
eigentlichen Konto-Attribute Konto-Nummer, Konto-Stand und Zinssatz direkt zu. Die personenbezo-
genen Attribute werden nicht zugewiesen, sondern es wird ein Objekt der Klasse Mensch erzeugt, das
heißt mit der Zeile [Link] = Mensch(vorname, nachname, gebdat, wohnort) wird
der Konstruktor der Klasse Mensch aufgerufen. Die Methoden sind noch nicht ausprogrammiert, statt
dessen steht nur ein Methodenrumpf da mit der leeren Anweisung pass, die nichts bewirkt.
Wieder benötigen wir ein Aufruf-Programm, mit dem wir diesen Klassen-Entwurf testen können:

Beispiel 11.2.2 Aufruf der Klasse Konto


#!/usr/bin/python

from clKonto import Konto

meinKonto = Konto(’101010’, ’Martin’, ’Schimmels’, ’01.01.1988’, ’Rottenburg’,


100.00, 0.02)
print([Link], [Link],
’\n’, [Link])
print(’Kontonr.:’, [Link], ’ Kontostand: ’, [Link])

240
KAPITEL 11. EIN ETWAS LÄNGERES . . . 11.2. OBJEKTORIENTIERTE . . .

11.2.3. Realisierung der Methoden Einzahlen“ und Auszahlen“


” ”
Einzahlungen und Auszahlungen müssen nun programmiert werden. Das sind aber sehr kurze Metho-
den.

Beispiel 11.2.3 Realisierung der ersten Methoden


1

2 from clMensch import Mensch


3

4 class Konto(object):
5

6 def __init__(self, ktoNr, vorname, nachname, gebdat, wohnort,


7 ktoStand, zinssatz):
8 [Link] = ktoNr
9 [Link] = Mensch(vorname, nachname, gebdat, wohnort)
10 [Link] = ktoStand
11 [Link] = zinssatz
12

13 def einzahlen(self, betrag):


14 [Link] += betrag
15

16 def auszahlen(self, betrag):


17 [Link] -= betrag
18

19 def verzinsen(self, zinssatz):


20 pass
21

Und das Aufruf-Programm ruft jede der beiden Methoden einmal auf und gibt jeweils anschließend
den aktuellen Stand aus:

Beispiel 11.2.4 Aufruf der beiden neuen Methoden


1

2 #!/usr/bin/python
3

4 from clKonto import Konto


5

6 meinKonto = Konto(’101010’, ’Martin’, ’Schimmels’, ’01.01.1988’,


7 ’Rottenburg’, 100.00, 0.02)
8 print([Link], [Link],
9 ’\n’, [Link])
10 print(’Kontonr.:’, [Link], ’ Kontostand: ’,
11 [Link])
12

13 [Link](111.23)
14 print([Link], [Link], ’\n’,
15 [Link])
16 print(’Kontonr.:’, [Link], ’ Kontostand: ’, [Link])
17

18 [Link](5.01)
19 print([Link], [Link], ’\n’,
20 [Link])
21 print(’Kontonr.:’, [Link], ’ Kontostand: ’, [Link])
22

241
KAPITEL 11. EIN ETWAS LÄNGERES . . . 11.2. OBJEKTORIENTIERTE . . .

11.2.4. Die Verzinsung


Es fehlt noch die Verzinsung. Auch hier muss wieder eine Vereinbarung für den Test und damit das
ordentliche Funktionieren der Klasse Konto getroffen werden, denn eine an der Realität orientierte
Verzinsungs-Methode können wir nicht testen. Wer will schon ein Jahr vor dem Rechner sitzen, und
warten, bis der Zeitpunkt der Verzinsung gekommen ist!!!
Deswegen wird hier das Modell folgendermaßen abgeändert: jede Transaktion, sei es Einzahlung oder
Auszahlung, wird gezählt, und nach 3 Transaktionen wird die Verzinsung angestoßen.

Beispiel 11.2.5 Die Verzinsung


1

2 from clMensch import Mensch


3

4 class Konto(object):
5 taZaehler = 0
6

7 def __init__(self, ktoNr, vorname, nachname, gebdat, wohnort,


8 ktoStand, zinssatz):
9 [Link] = ktoNr
10 [Link] = Mensch(vorname, nachname, gebdat, wohnort)
11 [Link] = ktoStand
12 [Link] = zinssatz
13

14 def einzahlen(self, betrag):


15 [Link] += betrag
16 [Link] += 1
17 if [Link] % 3 == 0:
18 [Link]([Link])
19

20 def auszahlen(self, betrag):


21 [Link] -= betrag
22 [Link] += 1
23 if [Link] % 3 == 0:
24 [Link]([Link])
25

26 def verzinsen(self, zinssatz):


27 [Link] += [Link]*[Link]
28

Hinzugekommen ist das Attribut taZaehler, das die Transaktionen zählt. Zu Beginn wird dieser
Zähler auf 0 gesetzt, in den einzelnen Methoden wird er hochgezählt (Vorsicht! Es muss natürlich mit
[Link] angesprochen werden!) und nach dem Hochzählen wird abgefragt, ob er durch 3
teilbar ist. Wenn ja, wird die Verzinsung angestossen. Das Aufruf-Programm ändert sich vorerst kaum,
da wir ja immer noch in der Test-Phase sind, es werden einzig die Befehle zum Einzahlen und zur
Anzeige mehrmals kopiert, so dass man mehrere Transaktionen bekommt.
Es gibt natürlich auch hier noch einiges zu verbessern.
1. Zuerst einmal entspricht es keinem guten Stil, Attribute eines Objektes direkt anzusprechen; das
sollte immer mittels einer Methode der Klasse geschehen.
2. Die Anzeige nach der Verzinsung gibt einen Kontostand mit mehr als 2 Dezimalstellen aus. Das
verwirrt auch den wohlwollendsten Bankkunden auf Dauer.
3. Das Aufruf-Programm ist ein Skandal! Immer wieder eine Folge von Befehlen zu kopieren ist
mit dem Berufsethos eines Programmierers nicht zu vereinbaren: da muss eine Schleife mit einer
sinnvollen Abbruchbedingung her.
4. Dabei wird auch endlich ein ordentliches Buchungsverfahren“ verwirklicht, das heißt, dass nicht

mehr im Aufruf-Programm die Buchungen fest verdrahtet sind, sondern dass man über Tastatur-
Eingaben Einzahlungen und Auszahlungen macht.
Das alles wird im nächsten Kapitel behandelt.

242
KAPITEL 11. EIN ETWAS LÄNGERES . . . 11.2. OBJEKTORIENTIERTE . . .

11.2.5. Die ersten Verbesserungen


Schreiben wir also zuerst eine Methode, die die Informationen über ein Konto ausgibt. (Hier wird nur
die neue Methode ausgegeben, die als vorläufig letzte Methode in die Klasse eingefügt wird.)

Beispiel 11.2.6 Eine Ausgabe-Methode


def kontoStandAusgeben(self):
print([Link], [Link])
print(’geboren am’, [Link], ’, wohnhaft in ’,
[Link])
print(’Kontonummer: ’, [Link], ’, Kontostand: ’, [Link])

Das Aufruf-Programm ändert sich dadurch, es wird kürzer, weniger fehleranfällig, überschaubarer;
kurz, es wird schöner!

Beispiel 11.2.7 Verbesserungen des Aufruf-Programms


1

2 #!/usr/bin/python
3

4 from clKonto import Konto


5

6 meinKonto = Konto(’101010’, ’Martin’, ’Schimmels’, ’01.01.1988’,


7 ’Rottenburg’, 100.00, 0.02)
8 [Link]()
9

10 [Link](111.23)
11 [Link]()
12

13 [Link](5.01)
14 [Link]()
15

16 [Link](100.00)
17 [Link]()
18

19 [Link](100.00)
20 [Link]()
21

Die zweite Verbesserung ist nur eine Kleinigkeit. Nur die neu geschaffene Methode kontoStandAusgeben
muss an einer Stelle verändert werden. Siehe dazu im Kapitel über Zeichenketten den Abschnitt über
Formatierung von Zeichenketten. Der Quelltext der veränderten Klassenmethode sieht so aus:

Beispiel 11.2.8 Verbesserung der Ausgabe-Methode


def kontoStandAusgeben(self):
print([Link], [Link])
print(’geboren am’, [Link], ’, wohnhaft in ’,
[Link])
print(’Kontonummer: %12s Kontostand: %+8.2f’ %
([Link], [Link]))

Jetzt kommt die wirklich interessante Veränderung. Es wird nicht mehr fest im Programm verdrah-
tet, wieviele Eingaben gemacht werden sollen, sondern der Benutzer entscheidet, wann das Programm
beendet werden soll: machen wir noch eine Schleife drum!

243
KAPITEL 11. EIN ETWAS LÄNGERES . . . 11.2. OBJEKTORIENTIERTE . . .

Beispiel 11.2.9 Konten bearbeiten in einer Schleife


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4 from clKonto import Konto
5

6 meinKonto = Konto(’101010’, ’Martin’, ’Schimmels’, ’01.01.1988’,


7 ’Rottenburg’, 100.00, 0.02)
8 [Link]()
9

10 def meld():
11 print("Konto-Verwaltung\ne für Einzahlung\na für Auszahlung\ns für Schluss")
12

13 eingabe = ’q’
14 while (eingabe != ’s’):
15 meld()
16 eingabe = input(’Bitte Eingabe:’)
17 if eingabe == ’e’:
18 betrag = float(input(’Einzahlungsbetrag: ’))
19 [Link](betrag)
20 elif eingabe == ’a’:
21 betrag = float(input(’Auszahlungsbetrag: ’))
22 [Link](betrag)
23 elif eingabe == ’s’:
24 print(’und tschüß’)
25 else:
26 print("Falsche Eingabe. nur a, e, s erlaubt")
27 [Link]()
28

Wieder könnte man sich entspannt zurücklehnen. Aber ganz zufrieden ist man nie, das ganze soll
noch besser werden. (Ganz ehrlich: so könnten wir das Programm noch keiner Bank verkaufen!) Was zu
tun ist? Das:
1. Das aufrufende Programm aus dem letzten Programm-Listing ist aus der Sicht des objektorien-
tierten Programmierers nicht in Ordnung. Das, was in diesem Programm steht, ist eigentlich ein
Menu für die Anwendung. Ein Menu ist aber wieder ein Objekt einer Menu-Klasse. Man könnte
sich also überlegen, wie man eine solche Menu-Klasse modelliert, wie man ein Objekt dieser Klas-
se erzeugt und wie man dann dieses Objekt arbeiten lässt. Der Konjunktiv steht hier, weil das
für dieses einfache Programm erst mal nicht nötig ist, um das Prinzip der Objektorientierung an
dem Beispiel der Klasse Konto zu überdenken. In einem der nächsten Beispiele wird das genau
durchgeführt, dass eine Klasse Menu erstellt wird. Ein bißchen Geduld also bitte!
2. Ein Konto ist ja ganz gut und schön, aber mit nur einem Konto wird keine Bank glücklich. Es
sollten schon mehrere Konten möglich sein.
3. Wenn der Rechner ausgeschaltet wird, sind alle Informationen verloren. So geht das nicht. Die
Daten sollten also gespeichert werden, (spätestens) wenn das Programm beendet wird.
Das alles wird im nächsten Kapitel behandelt.

11.2.6. Aufgaben zu Klassen


1. Es soll eine Klasse Buch geschrieben werden, die die Menge der Bücher in einer Leihbücherei
beschreibt. Dazu soll das Buch nur die Attribute Autor, Titel und ausgeliehen sowie die Me-
thoden ausleihen und zurückgeben haben. Ferner soll ein aufrufendes Programm geschrieben
werden, das diese Klasse benutzt.
2. Eine Klasse Bruch soll geschrieben werden, die Brüche darstellt und die Methoden kürzen, ad-
dieren, subtrahieren, multiplizieren und dividieren enthält, außerdem ein aufrufendes Programm,
mit dem man diese Klasse testen kann.

244
KAPITEL 11. EIN ETWAS LÄNGERES . . . 11.3. EIN KLASSISCHES BEISPIEL: STACK . . .

3. Diese Übungsaufgabe hört sich leicht an, ist aber recht kompliziert. Es geht um das bekannte Spiel
unter der Schulbank Schiffe versenken“. Gegeben ist ein Spielfeld der Größe 10 x 10, auf dem ein

Schiff der Länge 4, 2 Schiffe der Länge 3 und 3 Schiffe der Länge 2 versteckt sind. Der Dialog mit
dem Spieler könnte so aussehen:

Beispiel 11.2.10 Schiffe versenken


Zeilen und Spalten sind von 0 bis 9 numeriert
In welche Zeile ..1
und in welche Spalte willst Du zielen?0

0 0 0 0 . 0 . 0 . 0
k X k . 0 0 0 k 0 0
0 0 0 0 0 0 V V V V
0 0 k 0 0 0 0 0 0 0
V V V k 0 0 0 . . 0
0 0 0 0 0 V 0 0 k k
0 0 0 0 k V k V V V
0 0 0 0 0 k k 0 0 0
0 0 . 0 . k k 0 0 0
0 0 0 0 0 k X 0 0 0

Dabei bedeuten:
• 0 : noch nicht beschossenes Feld
• . : Splash! Das war voll ins Wasser!
• k : knapp daneben
• X : Treffer
• V : Schiff total versenkt

11.3. Ein klassisches Beispiel: Stack und Queue


Es gibt im Prinzip nur zwei Zugriffsmethoden auf eine Menge von Dingen:

1. FIFO: die Schlange (queue) Jeder Engländer versteht dieses Prinzip (und vielleicht gar kein ande-
res). Es wird brav sich angestellt, und in der Reihenfolge des Anstellens kommt man dran. So sieht
es auch an der Supermarkt-Kasse aus: wer zuerst ankommt, wird auch zuerst bedient. FIFO heißt
eben first in, first out“.

2. LIFO: der Stapel (stack) Für Frauen ist das wahrscheinlich unverständlich, aber bei Männern funk-
tioniert der Inhalt eines Kleiderschranks nach diesem Prinzip. Der Mann selber (oder die liebe Ma-
ma oder die noch liebere Freundin oder Frau) räumt die T-Shirts in den Kleiderschrank ein, und
am Morgen langt er hinein und nimmt das oberste, das als letztes reingelegt wurde, heraus und
zieht es an. LIFO heißt eben last in, first out“.

245
KAPITEL 11. EIN ETWAS LÄNGERES . . . 11.3. EIN KLASSISCHES BEISPIEL: STACK . . .

11.3.1. Die Queue


Nein, da muss man nichts dazu sagen. Höchstens muss man noch einmal nachschlagen, wie man mit
Listen umgeht! Die Klasse Queue ist dann selbstverständlich!

Beispiel 11.3.1 Klasse Queue


class Queue(object):
def __init__(self):
[Link] = []

def hinzufuegen(self, ding):


[Link](ding)

def entfernen(self):
entf = [Link](0)

def anzeigen(self):
print([Link])

Ein Programm, das diese Queue testet, ist auch nicht viel schwerer:

Beispiel 11.3.2 Aufruf Queue


from cl_Queue import Queue
meineQueue = Queue()
for i in range(5):
[Link](i)
[Link]()
while [Link]:
[Link]()
[Link]()

Beispiel 11.3.3 Die Ausgabe


[0, 1, 2, 3, 4]
[1, 2, 3, 4]
[2, 3, 4]
[3, 4]
[4]
[]

246
KAPITEL 11. EIN ETWAS LÄNGERES . . . 11.3. EIN KLASSISCHES BEISPIEL: STACK . . .

11.3.2. Der Stack


Hier muss man noch weniger sagen!

Beispiel 11.3.4 Klasse Stack


class Stack(object):
def __init__(self):
[Link] = []

def hinzufuegen(self, ding):


[Link](ding)

def entfernen(self):
entf = [Link]()

def anzeigen(self):
print([Link])

Der Aufruf

Beispiel 11.3.5 Aufruf Stack


from cl_Stack import Stack

meinStack = Stack()
for i in range(5):
[Link](i)
[Link]()
while [Link]:
[Link]()
[Link]()

Beispiel 11.3.6 Die Ausgabe


[0, 1, 2, 3, 4]
[0, 1, 2, 3]
[0, 1, 2]
[0, 1]
[0]
[]

247
Teil VII.

Fehler und Ausnahmen

249
12. Fehler. . .
Because something is happening here
And you don’t know what it is
(Bob Dylan 1 )

12.1. .. macht jeder


Vor allem jeder Programmierer macht Fehler. Bei manchen Programmen ist es ganz in Ordnung, dass
das Programm abbricht, wenn ein Fehler passiert. Das ist nicht weiter schlimm, wenn das Programm
nicht gleich das ganze Betriebssystem mit ins Nirwana zieht — wer erinnert sich da noch an das alte
MS-DOS?!?!
Ein Freund hat mir vor ein paar Tagen beschrieben, was in der Institution, für die er ehrenamtlich
arbeitet, passiert ist. Diese Institution hat Mitglieder, Angestellte, Kosten, Einnahmen von Mitgliedern,
Einnahmen aus Geschäften und viele andere Dinge, die — im 21. Jahrhundert selbstverständlich —
auf einem Rechner bearbeitet werden. Wie jedes Unternehmen ist diese Institution darauf bedacht, dass
diese Informationen erhalten bleiben, auch wenn auf den Rechnern etwas Unvorhergesehenes geschieht.
Eine Datensicherung muss also eingerichtet werden.
Bei der Konzeption des Rechnersystems und der Software war das auch beachtet worden. Datensi-
cherung sollte täglich geschehen, und diese Sicherungen, also verschiedene Versionen mit jeweils unter-
schiedlichem Datum, wurden eine bestimmte Zeit aufbewahrt. Bei einer Überprüfung des Rechnersys-
tems, die gemacht wurde, weil Antwortzeiten inakzeptabel geworden waren, stellte der Überprüfende
fest: seit 6 Monaten war keine Sicherung mehr geschrieben worden und eine ganze Gruppe von Daten
wurde noch überhaupt nie gesichert. (Geplant war das alles, und Diejenigen, die das System erstellt
haben, bestätigten, dass diese Sicherungen eingebaut worden waren, aber den Grund, warum es in der
Realität nicht oder nicht mehr funktionierte, wusste mein Bekannter noch nicht.)
Wie kann man als Informatiker (oder Programmierer oder sonst irgendein IT-Fachmann) mit einem
Programm(-System) in einem solchen Fall umgehen? Es gibt verschiedene Ansätze:

1. In dem oben geschilderten Fall ist die zuständige Person nach dem Motto vorgegangen: ich habe
das programmiert (oder die Programme eingerichtet), ich habe es einmal (oder 10 mal oder noch
öfter) getestet, es hat funktioniert, also wird es auch weiterhin immer funktionieren.
Nichts zu tun: das ist, bei meinem Bekannten hat sich das bestätigt, für die für die Einrichtung des
Systems zuständige Person die einfachste, für den Benutzer oder den Kunden aber sicher die im
Zweifelsfall unbefriedigendste Lösung.
2. Die nächste Stufe ist das Minimum, was man von einem System erwarten sollte. Bei jedem Schritt
einer solchen Datensicherung wird eine Meldung ausgegeben. Das könnte dann so aussehen:
===> Daten erfolgreich geschrieben
===> Tabelle xyz mit ii Datensätzen geschrieben
oder:
=X=X=> Fehler !!!
=X=X=> Schreiben der Tabelle xyz nach jj Datensätzen abgebrochen
OK, das sieht doch schon mal nicht schlecht aus. Es erfordert aber, dass der Anwender diese In-
formationen jeden Tag liest, und das sehr sorgfältig. Aber jeder weiß: jetzt hat das an 500 Tagen
funktioniert, dann brauch ich ab jetzt nicht mehr so genau hinschauen. Das wird doch auch wei-
terhin stimmen.
Dazu muss aber das Programm, das für die Datensicherung zuständig ist, bei jeder Aktion die kor-
rekte Ausführung überprüfen, und das müsste der Programmierer tatsächlich Schritt für Schritt
1 Ballad of a thin man auf: Highway 61 revisited

251
KAPITEL 12. FEHLER. . . 12.2. FEHLER WERDEN ABGEFANGEN

programmieren.2 Nach jedem einzelnen der überprüften Schritte muss dann der Programmierer,
nach Anweisung der Fachabteilung, in sein Programm einbauen, was passieren soll: soll die ge-
samte Sicherung abgebrochen werden, soll eine Fehlermeldung ausgegeben werden und die Si-
cherung der weiteren Dateien versucht werden, müssen bereits gesicherte Daten wieder entfernt
werden, damit keine Inkonsistenzen entstehen?
Diese Fehlerbehandlung zu Fuß“ wird umfangreich und damit auf Dauer undurchsichtig, also

auch schwer wartbar. Es ist auch fraglich, ob bei einer solchen Fehlerbehandlung in Handarbeit
alle möglichen Fehlerquellen abgedeckt werden und vor allem keine möglicherweise in Zukunft
auftretende Fehlerquelle nicht bedacht wird.
3. Um das zu verbessern und zu vereinfachen, ist in der Software-Technik das Prinzip der Ausnah-

mebehandlung“ entstanden. Eine Ausnahme ist irgendetwas in einem Programmablauf, was der
Entwickler nicht erwartet. Genauer gesagt: er erwartet nicht, dass es passiert, aber er weiß, dass es
passieren könnte. Im schlimmsten Fall ist eine Ausnahme ein Fehler, der zu falschen Ergebnissen
führt, vielleicht auch zu Datenverlust, in weniger schlimmen Fällen entsteht in einem Programm
eine Situation, die eine weitere Ausführung unmöglich macht, aber noch andere Ausnahme(type)n
sind denkbar.

12.2. Fehler werden abgefangen


Aber meistens soll ein Programm trotz eines Fehlers weiterlaufen, vor allem dann, wenn der Benutzer
etwas macht, was der Programmierer so nicht vorgesehen hat. Nehmen wir an, der Programmierer hat
ein Programm geschrieben, in dem der Benutzer sein Alter eingeben soll, und Otto (der aus Ostfriesland)
sitzt vor dem Programm und gibt ein ich sage meistens Papa zu ihm“. In der Otto-Show ist das ganz

lustig, der Programmierer hatte aber erwartet, dass der Benutzer eine Zahl eingibt, weil mit Hilfe dieser
Zahl, dem Alter in Jahren, etwas berechnet werden soll. Das Programm wird im Normalfall abbrechen
und eine eher verwirrende Fehlermeldung ausgeben. Hier kommt dieses Beispiel, und was die Python-
Shell daraus macht:

Beispiel 12.2.1 Fehler! (Gruß an Otto)


1

2 >>> alter = int(input(’Alter? ’))


3 Alter? ich sage meistens Papa zu ihm
4 Traceback (most recent call last):
5 File "<stdin>", line 1, in <module>
6 File "<string>", line 1
7 ich sage meistens Papa zu ihm
8 ˆ
9 SyntaxError: invalid syntax
10

Was man sich wünschen würde, wäre aber etwas in der Art:

Beispiel 12.2.2 Ein Fehler wird abgefangen


>>> alter = int(input(’Alter? ’))
Alter? ich sage meistens Papa zu ihm
Fehlerhafte Eingabe! Es ist das Alter in Jahren gefragt. Probier es nochmal!
>>> alter = int(input(’Alter? ’))

Und man bekommt eine zweite Chance (und zur Not eine dritte und eine vierte . . . )
Der obigen Dialog mit dem Benutzer wurde realisiert durch folgendes Programm:
2 So hat man das wirklich vor nicht allzu langer Zeit gemacht. Eine extrem lästige Arbeit!

252
KAPITEL 12. FEHLER. . . 12.2. FEHLER WERDEN ABGEFANGEN

Beispiel 12.2.3 Schleife mit Fehlerbehandlung


#!/usr/bin/python
# -*- coding: utf-8 -*-
alterOK = False
while not alterOK:
try:
alter = int(input(’Alter? ’))
alterOK = True
except:
print(’’’Fehlerhafte Eingabe!
Es ist das Alter in Jahren gefragt.
Probier es nochmal!’’’)

Schöner allerdings ist es, den entsprechenden Fehler abzufangen. Das ist ein Fehler der Klasse Value-
Error, also ein Wert-Fehler. Dazu lasse ich einen Text eingeben und versuche, diesen Text in eine Ganz-
zahl umzuwandeln:

Beispiel 12.2.4 Schleife mit Fehlerbehandlung


#!/usr/bin/python
# -*- coding: utf-8 -*-
alterOK = False
while not alterOK:
try:
alter = int(input(’Alter? ’))
alterOK = True
except ValueError:
print(’’’Fehlerhafte Eingabe!
Es ist das Alter in Jahren gefragt.
Probier es nochmal!’’’)

Zu diesem Zweck hat Python eine eingebaute Fehlerbehandlung, die man aber besser als Ausnahme-
behandlung bezeichnet. Das Prinzip ist immer das folgende:

1. Wenn man einen Programmbefehl schreibt, bei dem es möglich ist, dass ein Fehler passiert, teilt
man dem Programm mit, dass es diesen Befehl nicht ausführen soll, sondern probieren soll, ob der
Befehl ausführbar ist.

2. Wenn ja, dann wird der Befehl auch tatsächlich ausgeführt.

3. Wenn der Befehl nicht ausgeführt werden kann, wird eine Ausnahme geworfen.3 Die Ausnahme
ist ein Befehl, der ausgeführt wird, wenn der ursprünglich gewünschte Befehl nicht ausgeführt
werden kann.

4. Es gibt dann noch die Möglichkeit, Befehle anzuschließen, die auf jeden Fall ausgeführt werden,
egal, ob der ursprünglich gewünschte Befehl geklappt hat oder nicht.

In der Frühzeit der Programmierung war einer der häufigsten Fehler, der einen Rechner (zum Beispiel
unter DOS) zum Absturz brachte, dass man versuchte, durch Null zu dividieren.

3 Diese Sprechweise hat sich auch im Deutschen durchgesetzt: sie ist eine wörtliche Übersetzung von to throw an exception“

253
KAPITEL 12. FEHLER. . . 12.2. FEHLER WERDEN ABGEFANGEN

Beispiel 12.2.5 Division funktioniert


1

2 >>> x = 27
3 >>> y = 3
4 >>> ergebnis = x/y
5 >>> print(ergebnis)
6 >>> 9
7

So weit, so gut. Beim nächsten Versuch geht es schief:

Beispiel 12.2.6 Division durch 0


>>> x = 27
>>> y = 0
>>> erg = x/y
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero

Die Fehlermeldung ist verständlich, aber das Programm hat sich verabschiedet.4 Man kann das in
Python durch ein try - except Konstrukt zum Glück verhindern:

Beispiel 12.2.7 Division durch 0 ... wird abgefangen


1

2 >>> try:
3 >>> x = 27
4 >>> y = 0
5 >>> erg = x / y
6 >>> except:
7 >>> print(’Da lief etwas schief. Schau noch mal nach den Werten von x und y’)
8 ’Da lief etwas schief. Schau noch mal nach den Werten von x und y’
9

Sinnvollerweise sollte man diesen ganzen Programm-Schnipsel in eine while-Schleife einbinden, die
es dem Benutzer erlaubt, einen Wert für y so lange einzugeben, bis der ungleich 0 ist.
Das Otto-Waalkes-Gedächtnis-Beispiel sieht dann in Python so aus:

Beispiel 12.2.8 Try - Except (ohne Einschränkung)


>>> try:
alter = int(input(’Alter?’))
except:
print(’keine Zahl’)
...
Alter?d
keine Zahl

Hier wurde einfach blindlings mit except jeder x-beliebige Fehler abgefangen. Und das ist doch
schon ganz gut, denn damit kann das Programm weiterlaufen und als Programmierer kann man sich
überlegen, was in einem solchen Fall gemacht werden soll.
4 Zum Glück wurden die Betriebssysteme inzwischen so verbessert, dass nicht mehr das ganze Betriebssystem sich verabschiedet.

254
KAPITEL 12. FEHLER. . . 12.3. SPEZIELLE FEHLER

Dieses einfache Muster einer Fehlerbehandlung

Beispiel 12.2.9 einfache Fehlerbehandlung


>>> try:
Anweisung(en)
except:
Fehlermeldung

kann verbessert werden zu

Beispiel 12.2.10 Try - Except - Else


>>> try:
Anweisung(en)
except:
Fehlermeldung
else:
weitere Anweisungen, falls keine Ausnahme aufgetreten ist

Das else ist in manchen Fällen sehr hilfreich. Nur so kann man sicherstellen, dass Anweisungen
dann und nur dann ausgeführt werden, wenn keine Ausnahme aufgetreten ist.

12.3. Spezielle Fehler


Oft weiß man aber genauer, welche Art von Fehler passieren könnte. Das erste Beispiel von oben mit
der Division durch Null könnte so verbessert werden:

Beispiel 12.3.1 Division durch 0 ... wird durch passende Fehlerart abgefangen
1

2 >>> try:
3 >>> x = 27
4 >>> y = 0
5 >>> erg = x / y
6 >>> except ZeroDivisionError:
7 >>> print(’y darf nicht 0 sein!!!’)
8 >>> except:
9 >>> print(’irgendein anderer Fehler ist aufgetaucht’)
10 y darf nicht 0 sein!!!
11

Hier kommt ein weiteres Beispiel, bei dem aus Versehen versucht wird, über das Ende einer Liste
hinauszulesen:

Beispiel 12.3.2 Korrekter Index in einer Liste


1

2 >>> eineListe = [’nulltes Element’, ’erstes Element’, ’zweites Element’]


3 >>> eineListe[1]
4 ’erstes Element’
5

So weit kein Problem. Aber was passiert, wenn man jetzt versucht, das siebte Element auszugeben?

255
KAPITEL 12. FEHLER. . . 12.3. SPEZIELLE FEHLER

Beispiel 12.3.3 Falscher Index in einer Liste


>>> eineListe = [’nulltes Element’, ’erstes Element’, ’zweites Element’]
>>> eineListe[7]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range

Immerhin sagt Python mir hier, was falsch ist: der Index ist außerhalb des gültigen Bereichs. Es han-
delt sich also hier um einen Index-Fehler. Das kann man natürlich viel genauer abfangen:

Beispiel 12.3.4 Index-Fehler wird abgefangen


>>> try:
eineListe[7]
except IndexError:
print(’Index außerhalb der erlaubten Grenzen’)

Index außerhalb der erlaubten Grenzen

Hier wurde also der Index-Fehler ausdrücklich abgefangen.


Es können aber in einem Block verschiedenartige Fehler auftreten. Hier zeige ich es bei unserem Ein-
gangsbeispiel mit der Division. Nicht nur die Division durch 0 führt zu einem Abbruch, sondern auch
die Division durch etwas anderes, durch das man nicht dividieren kann:

Beispiel 12.3.5 Durch Text kann man nicht teilen!


>>> x = 3
>>> y = ’Always look on the bright side of life’
>>> erg = x / y
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for /: ’int’ and ’str’

Durch Text kann man nicht teilen! Es sollen also jetzt 2 Fehlerarten abgefangen werden.

Beispiel 12.3.6 Division ... wird durch passende Fehlerart abgefangen (1. Versuch)
>>> try:
>>> x = 27
>>> y = 0
>>> erg = x / y
>>> except ZeroDivisionError:
>>> print(’y darf nicht 0 sein!!!’)
>>> except TypeError:
>>> print(’Der Wert einer der beiden Variablen ist keine Zahl’)
>>> except:
>>> print(’Irgendein anderer Fehler ist aufgetreten’)
y darf nicht 0 sein!!!

Und ein nächster Testlauf:

256
KAPITEL 12. FEHLER. . . 12.3. SPEZIELLE FEHLER

Beispiel 12.3.7 Division ... wird durch passende Fehlerart abgefangen (2. Versuch)
>>> try:
>>> x = 27
>>> y = ’Always look on the bright side of life’
>>> erg = x / y
>>> except ZeroDivisionError:
>>> print(’y darf nicht 0 sein!!!’)
>>> except TypeError:
>>> print(’Der Wert einer der beiden Variablen ist keine Zahl’)
>>> except:
>>> print(’Irgendein anderer Fehler ist aufgetreten’)
Der Wert einer der beiden Variablen ist keine Zahl

Es ist gute Technik, Fehler immer mit einem ganz konkreten Fehlercode abzufangen. Mit einem ein-
fachen try . . . except ohne die Angabe eines Fehlercodes ist es vor allem in der Phase der Programm-
entwicklung ausgesprochen schwierig, einem Fehler auf die Spur zu kommen. Da ist es hilfreich, wenn
der Fehler durch den Fehlercode eingegrenzt wird. Dazu kommt jetzt eine Tabelle der wichtigsten Feh-
lercodes.

12.3.1. Ein Menu-Schnipsel mit Fehlerbehandlung


Immer wieder schreibt man ein Programm und freut sich, dass das Programm so läuft, wie man es
sich ausgedacht hat. Kaum setzt sich der erste Benutzer an das Programm, bricht es ab: der Benutzer
hat bei einer Eingabeaufforderung etwas eingegeben, was uns noch nie in den Sinn kam. Vor allem bei
Auswahl-Menus passiert so etwas immer wieder.
Deswegen folgt hier ein Menu, das die Auswahl aus drei Aktionen erlaubt. Die Funktionen tun nichts,
außer dass sie sich melden. Das Menu ist in einem Dictionary hinterlegt, wobei der Schlüssel für eine
Aktion eine ganze Zahl ist und der Wert der Name der Funktion. Zusätzlich soll der Benutzer durch die
Eingbe von e“ das Programm beenden können. Typische Fehler durch den Benutzer sind

• die Eingabe eines anderen Buchstaben als e“

• die Eingabe einer Zahl, die nicht als Schlüssel im Dictionary steht

257
KAPITEL 12. FEHLER. . . 12.3. SPEZIELLE FEHLER

Das Menu-Programm sieht dann so aus5 :

Beispiel 12.3.8 Menu mit Fehler-Behandlung


#!/usr/bin/python
# -*- coding: utf-8 -*-

eingabe = ’’

def tu1():
print(’hier ist TU 1’)

def tu2():
print(’hier ist TU 2’)

def tu3():
print(’hier ist TU 3’)

menu = {1:tu1, 2:tu2, 3:tu3}

while eingabe != ’e’:


eingabe = input(’1 oder 2 oder 3 oder e’)
print(eingabe)
try:
einNum = int(eingabe)
except ValueError:
if eingabe == ’e’:
break
try:
menu[einNum]()
except KeyError:
print(’keine gültige Zahl’)

Tabelle 12.1. Fehler-Konstanten


Konstante Bedeutung
EOFError Leseoperation über das Ende der Datei hinaus
IOError Fehler bei Ein-/Ausgabe
TypeError Falscher Typ des Parameters / der Variablen
ZeroDivisionError Division durch 0
IndexError Falscher Index (Versuch, über Ende einer Liste zu lesen)

5 Danke an Kati Naumann

258
Teil VIII.

Permanente Speicherung

259
13. Dateizugriff
13.1. Dateien allgemein
Look out kid
It’s somethin’ you did
(Bob Dylan 1 )
Dateien sind Speicherbereiche auf einem Speichermedium, die erstellt, geöffnet, geschlossen, bearbei-
tet und gelöscht werden können. Dafür ist das jeweilige Betriebssystem zuständig, das für jede dieser
Aktionen einen Befehl bereitstellt. 2
Jede Aktion mit Dateien fängt damit an, dass man die Datei öffnet. Damit erstellt man aus Sicht von
Python ein Objekt, das eine Verbindung zu der real existierenden Datei auf dem Datenträger herstellt.
Dabei muss man im Programm festlegen, was man nach dem Öffnen der Datei mit der Datei anstellen
will: will man sie nur lesen, will man sie verändern, oder will man eine neue Datei erstellen (und damit
eventuell eine bereits existierende Datei des selben Namens überschreiben). Der entsprechende Befehl
in Python sieht also so aus:

meineDatei = open(’[Link]’, ’r’) # r steht für Lesen


meineDatei = open(’[Link]’, ’w’) # w steht für (Neu-)Schreiben
meineDatei = open(’[Link]’, ’a’) # a steht für Anhängen, also
# verändern
meineDatei = open(’[Link]’, ’rb’) # rb steht für binary Lesen,
# z.B. für Bild/Musik etc.
# -Daten
meineDatei = open(’[Link]’, ’wb’) # wb steht für binary
# Schreiben z.B. für
# Bild/Musik etc. Daten
meineDatei = open(’[Link]’, ’r+’) # r+ Lesen und Schreiben bei
# existierender Datei
meineDatei = open(’[Link]’, ’w+’) # w+ Lesen und Schreiben,
# nicht existierende Datei
# wird angelegt,
# existierende Datei wird
# überschrieben

Damit ist klar: ab diesem Zeitpunkt ist meineDatei ein Objekt der Klasse file.
Diese Klasse hat einige Methoden, die jetzt für den Zugriff auf den Inhalt der Datei benutzt werden.
Grundsätzlich gilt: was man aufmacht, muss man auch wieder zumachen. Man sollte jede Datei nach
Gebrauch wieder schließen, und dazu dient die Methode close:

[Link]() # Die Methode close des Objektes wird


# aufgerufen

Schreiben wir also zwei Programme: zuerst eines, das eine Datei schreibt, dann ein zweites, das diese
Datei wieder liest. Für das Schreiben steht die Methode write zur Verfügung.
1 Subterranean Homesick Blues auf: Bringing It All Back Home
2 Ganz sicher bin ich mir nicht, ob das wirklich stimmt. In Unix-ähnlichen Betriebssystemen wird eine leere Datei durch den
Befehl touch dateiname erstellt (JA! Das ist wirklich sinnvoll!!) Gibt es einen analogen Befehl unter Windows?

261
KAPITEL 13. DATEIZUGRIFF 13.1. DATEIEN ALLGEMEIN

Beispiel 13.1.1 Datei schreiben


#!/usr/bin/python
# Schreib-Programm
neueDatei = open(’[Link]’, ’w’)
[Link](’Ich liebe Python.\n Und natürlich meine Freundin.’)
[Link]()

Jetzt kann man auf Betriebssystemebene (oder mit einem Hilfsprogramm wie xxx-Commander) se-
hen, dass diese Datei erstellt worden ist.
Das Thema Dateizugriff“ wurde mit dem Schreiben begonnen, da das die einfachere Operation ist.

Man muss sich dabei aber klar machen, dass der Dateizugriffsmodus w“ bedeutet, dass unbedingt

geschrieben wird. Falls eine Datei des selben Namens bereits existiert, wird diese überschrieben. Das
ist einfacher, weil es immer funktioniert, allerdings kann man da auch ganz schnell viel zerstören. Das
Lesen ist schon allein deswegen komplizierter, weil das Programm nicht weiß, wieviel es zu lesen gibt.
Erwartet man eine eher kleine Datei, ist es oft sinnvoll, die ganze Datei auf einmal einzulesen und
dann das Gelesene in einer Schleife abzuarbeiten. Wenn man allerdings weiß, dass die zu lesende Datei
vielleicht mehrere 100 MB groß ist, ist es sinnvoller, diese Datei Stück für Stück (das heißt günstigstenfalls
Zeile für Zeile) einzulesen und jede Zeile einzeln zu bearbeiten. Im Vergleich zu der ersten Methode be-
deutet das, dass hier die Schleife nicht innerhalb des Gelesenen sondern vor dem Lesen steht (oder wie
der Programmierer sagt: man schleift über das Lesen).
Hier wird die erste Methode angewandt, um die Datei zu lesen, nämlich alles auf einmal. Die Python-
Methode dazu heißt wieder genauso, wie man das erwartet: readlines (beachte den Plural) liest alle
Zeilen der Datei.

Beispiel 13.1.2 Datei lesen (alles auf einmal)


#!/usr/bin/python
# -*- coding: utf-8 -*-
# Lese-Programm
liebeDatei = open(’[Link]’, ’r’)
alleZeilen = [Link]()
print(alleZeilen)
[Link]()

Wenn man die Schleife um das Lesen herummachen will, benutzt man die Methode readline. Ei-
gentlich ist das auch wieder logisch, dass man in diesem Fall nur eine Zeile liest, deswegen also der
Singular. Dann sieht das Programm so aus:

Beispiel 13.1.3 Datei zeilenweise lesen


#!/usr/bin/python
# -*- coding: utf-8 -*-

dat = open(’[Link]’, ’r’)


ende = False
while not(ende):
zeile = [Link]()
if not(zeile):
ende = True
else:
print(zeile)
[Link]()

262
KAPITEL 13. DATEIZUGRIFF 13.1. DATEIEN ALLGEMEIN

Hier muss man gewährleisten, dass nicht versucht wird, über das Ende der Datei rauszulesen. Das
würde einen Programmabsturz verursachen, also muss mit dem logischen Schalter ende das Dateiende
abgefangen werden.
Seit Python Version 2.4 gibt es für den Dateizugriff Iteratoren“, also Mechanismen, die mitzählen“,
” ”
wieviel man gelesen hat und die damit wissen, was als nächstes drankommt. Der Unterschied ist, dass
3
Iteratoren mit Hilfe einer Exception abgefangen werden, während beim readline am Ende der Da-
tei einfach eine leere Zeichenkette in der entsprechenden Variablen (im Beispiel oben in der Variablen
zeile) steht. Der Iterator, der immer auf die nächste Zeile zeigt, heißt, wen wundert es, next. Das
Programm ändert sich leicht:

Beispiel 13.1.4 Datei zeilenweise mit Iterator lesen


#!/usr/bin/python
# -*- coding: utf-8 -*-

dat = open(’[Link]’, ’r’)


ende = False
while not(ende):
try:
zeile = next(dat)
print(zeile)
except StopIteration:
ende = True
break
[Link]()

Beispiel 13.1.5 Die Ausgabe des Programms


>>> Dies ist ziemlicher Blödsinn.
Es geht nur darum, einige Zeilen zu füllen.
Damit hat das Programm die Möglichkeit, mehrere Zeilen zu lesen.
Zur Probe werden die Zeilen dann ausgegeben.

Der Befehl open öffnet die Datei, macht aber noch nichts mit der Datei. Allerdings kann man den
Datei-Handle als Liste benutzen und mit einer for-Schleife zeilenweise über die Datei schleifen:

Beispiel 13.1.6 Datei lesen mit for-Schleife


#!/usr/bin/python

meineDat = open("[Link]","r")
for zeile in meineDat:
print(zeile)
[Link]()

>>> Dies ist ziemlicher Blödsinn.


Es geht nur darum, einige Zeilen zu füllen.
Damit hat das Programm die Möglichkeit, mehrere Zeilen zu lesen.
Zur Probe werden die Zeilen dann ausgegeben.

3 Das Thema Fehler und Ausnahmen steht erst weiter hinten im Text.

263
KAPITEL 13. DATEIZUGRIFF 13.1. DATEIEN ALLGEMEIN

Seit Version 2.5 gibt es in Python das Schlüsselwort with. Mit Hilfe von with wird ein Dateiobjekt
geöffnet und vor allem nach dem Dateizugriff geschlossen. Das sieht dann so aus:

Beispiel 13.1.7 Gesamte Datei lesen mit with


#!/usr/bin/python

with open(’[Link]’, ’r’) as dat:


zeilen = [Link]()
for eineZeile in zeilen:
print(zeile)

Und die Ausgabe des Programms ist die selbe wie oben.
Die nächste Datei benutzt, dass durch with ein Iterator über die Datei erzeugt wird. Damit kann die
for-Schleife diesen Iterator benutzen, womit das Programm nochmals kürzer wird.

Beispiel 13.1.8 Datei zeilenweise lesen mit with


#!/usr/bin/python

with open(’[Link]’, ’r’) as dat:


for zeile in dat:
print(zeile[:-1])

13.1.1. print funktioniert auch!


Mit der print-Funktion ab Python 3.x kann man auch einfach Dateien beschreiben. Dabei wird ausge-
nutzt, dass der Funktion ein benannter Parameter mit dem Namen file mitgegeben werden kann.

Beispiel 13.1.9 Datei mit print schreiben


>>> print(’hallo Martin’, file=open(’[Link]’,’w’))

Dies öffnet eine Datei und schreibt etwas hinein.

13.1.2. Textanalyse
Im nächsten Beispiel soll ein Text daraufhin untersucht werden, welches die häufigsten Wörter sind, die
er enthält. Dazu wird

1. ein leeres Dictionary angelegt, in dem am Ende die Wörter mit ihrer Häufigkeit stehen werden
2. eine Datei geöffnet
3. die Datei zeilenweise gelesen
4. a) von jeder Zeile der Zeilenvorschub am Ende entfernt
b) aus jeder Zeile die Satz- und Sonderzeichen entfernt
c) jede Zeile in ihre einzelnen Wörter aufgesplittet
d) i. von jedem Wort nachgeschaut, ob es schon im Dictionary steht
ii. wenn ja, wird der Zähler um 1 erhöht
iii. sonst wird der Zähler auf 1 gesetzt

5. das Dictionary ausgegeben

264
KAPITEL 13. DATEIZUGRIFF 13.2. FORTFÜHRUNG DES . . .

Beispiel 13.1.10 Häufigkeit von Wörtern


#!/usr/bin/python

import string
einDat = open(’/home/fmartin/texte/sonstiges/[Link]’,’r’)

zaehler = {}

for zeile in einDat:


zeile = [Link]()
zeile = [Link]([Link](’’,’’,[Link]))
woerter = [Link]()
for einWort in woerter:
if einWort in zaehler:
zaehler[einWort] += 1
else:
zaehler[einWort] = 1
print(zaehler)

Das Programm ist getestet! Schreib Dir selbst (mit einem Editor, nicht mit einer Textverarbeitung!!!)
eine Datei mit irgendwelchem Text, speichere sie und ändere den Pfad und den Namen der zu öffnenden
Datei. Und schau Dir dann die Ausgabe des Programms an.
Schau Dir an, was die Hilfe-Funktion zu

1. [Link]

2. [Link]

3. [Link]

sagt.

13.2. Fortführung des Konten-Programms


Die erste Änderung hat noch nichts mit dem Dateizugriff zu tun, denn hier geht es darum, das Pro-
gramm so zu ändern, dass man mehrere Konten bearbeiten kann. Dazu sollte das Anlegen eines Kontos
nicht mehr fest im Programm kodiert sein, sondern interaktiv erfolgen. Also muss man den Konstruktor
der Klasse Konto ändern.
Wahrscheinlich fällt hier wieder jedem auf, wie elegant der objektorientierte Ansatz ist. Um für alle
möglichen Konten, die wir bearbeiten wollen, diese Änderung durchzuführen, muss man tatsächlich
nur an einer Stelle eingreifen. Ich schreibe hier die alte Version des Konstruktors nochmals hin:

Beispiel 13.2.1 Der bisherige Konstruktor für Konten


1

2 def __init__(self, ktoNr, vorname, nachname, gebdat, wohnort,


3 ktoStand, zinssatz):
4 [Link] = ktoNr
5 [Link] = Mensch(vorname, nachname, gebdat, wohnort)
6 [Link] = ktoStand
7 [Link] = zinssatz
8

und hintendran gleich die neue Version, nach der Änderung, die ich ein paar Zeilen zuvor angespro-
chen habe:

265
KAPITEL 13. DATEIZUGRIFF 13.2. FORTFÜHRUNG DES . . .

Beispiel 13.2.2 Neuer Konstruktor: Parameter sind teilweise initialisiert


1

2 def __init__(self, ktoNr, vorname, nachname, gebdat, wohnort,


3 ktoStand = 0, zinssatz = 0.02):
4 [Link] = ktoNr
5 [Link] = Mensch(vorname, nachname, gebdat, wohnort)
6 [Link] = ktoStand
7 [Link] = zinssatz
8

Was hier passiert, wurde schon im Abschnitt über variable Parameter beim Funktionsaufruf beschrie-
ben.
Im Aufruf-Programm muss sich allerdings viel ändern. Als erstes bekommt das Programm zwei
Funktionen, mit denen man dem Benutzer die möglichen Eingaben, je nachdem in welchem Programm-
Teil der Benutzer sich gerade befindet, auf den Bildschirm schreibt. Ein bißchen Hilfe muss sein.

Beispiel 13.2.3 Ein paar kleine Hilfen für die Benutzer


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4 from clKonto import Konto
5

6 alleKonten = {}
7

8 def meldModus():
9 print("Konto-Verwaltung\ne für Einzahlung\na für Auszahlung\ns für Schluss")
10

11 def meldAnl():
12 print("Konto-Verwaltung\nn für ’Neues Konto anlegen’\ns für Schluss")
13

Außerdem wird ein leeres Dictionary alleKonten angelegt.


Danach startet man eine Schleife, um einige Konten anzulegen:

Beispiel 13.2.4 Eine Schleife für das Anlegen eines Kontos


1

2 eingabe = ’q’
3 while (eingabe != ’s’):
4 meldAnl()
5 eingabe = input(’Bitte Eingabe:’)
6 if eingabe == ’n’:
7 neuKtoNr = input(’Bitte neue Konto-Nummer eingeben: ’)
8 neuVorname = input(’Bitte Vornamen eingeben: ’)
9 neuNachname = input(’Bitte Nachnamen eingeben: ’)
10 neuGebdat = input(’Bitte Geburtsdatum eingeben: ’)
11 neuWohnort = input(’Bitte Wohnort eingeben: ’)
12 aktuellesKonto = Konto(neuKtoNr, neuVorname, neuNachname,
13 neuGebdat, neuWohnort)
14 alleKonten[neuKtoNr] = aktuellesKonto
15 elif eingabe == ’s’:
16 pass
17 else:
18 print("Falsche Eingabe. nur n und s erlaubt")
19

In den Zeilen mit input werden die Parameter für jeweils ein neues Konto entgegengenommen. Mit

266
KAPITEL 13. DATEIZUGRIFF 13.3. IN DIE DATEI DAMIT!!!

diesen Werten wird der Konstruktor für ein Konto aufgerufen und damit ein Objekt erzeugt, das ein-
deutig zu identifizieren ist durch die Kontonummer. Diese Kontonummer als Schlüssel und das Konto-
Objekt als Wert werden in dem Dictionary abgelegt.
Jetzt folgen zwei ineinanderverschachtelte while-Schleifen. In der äußeren Schleife wählt man bis
zur Abbruchbedingung immer ein neues Konto aus. Die Abbruchbedingung ist hier willkürlich auf die
Kontonummer 9999 gesetzt. In der inneren Schleife befindet sich die Bearbeitung eines einzelnen Kontos
mit einzahlen, auszahlen und verzinsen, so wie sie bisher schon existierte:

Beispiel 13.2.5 Interaktive Auswahl eines Kontos aus einer Liste


aktuelleKontoNr = 0
while (aktuelleKontoNr != 9999):
print("angelegte Konten: ", [Link]())
print("Konto auswählen: (ENDE mit 9999)")
aktuelleKontoNr = input(’Kontonummer eingeben: ’)
if aktuelleKontoNr != 9999:
aktuellesKonto = alleKonten[aktuelleKontoNr]

eingabe = ’q’
while (eingabe != ’s’):
meldModus()
eingabe = input(’Bitte Eingabe:’)
if eingabe == ’e’:
betrag = float(input(’Einzahlungsbetrag: ’))
[Link](betrag)
elif eingabe == ’a’:
betrag = float(input(’Auszahlungsbetrag: ’))
[Link](betrag)
elif eingabe == ’s’:
print(’und tschüß’)
else:
print("Falsche Eingabe. nur a, e, s erlaubt")
[Link]()
else:
pass

13.3. In die Datei damit!!!


13.3.1. Der Modul pickle
Fast schämt man sich, dafür ein neues Kapitel anzufangen. Das Schreiben von Objekten in eine Datei,
im nächsten Programm auch das Lesen von Objekten aus einer Datei, wird von einem Modul erledigt,
der auf den schönen Namen pickle hört. Zuerst muss natürlich das Modul pickle importiert werden.
Der Anfang des Aufruf-Programms ändert sich dadurch zu:

Beispiel 13.3.1 Modul importieren: Ein Objekt in eine Datei schreiben


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4 from clKonto import Konto
5 import pickle
6

Ganz an das Ende des Programms wird dann die Dateibehandlung eingefügt. Sie besteht aus 4 Schrit-
ten: Dateinamen vergeben, Datei öffnen, Objekt in die Datei dumpen, Datei schließen.

267
KAPITEL 13. DATEIZUGRIFF 13.3. IN DIE DATEI DAMIT!!!

Beispiel 13.3.2 Ein Objekt in eine Datei schreiben


1

2 dateiName = ’[Link]’
3 ktoDatei = open(dateiName, ’wb’)
4 [Link](alleKonten, ktoDatei)
5 [Link]()
6

Damit das ganze Kapitel aber nicht total peinlich ist, folgt noch ein Aufruf-Programm, mit dem man
die geschriebene Datei wieder auslesen kann. Auf die Verarbeitung der gelesenen Daten wird hier ver-
zichtet, da man das aus dem vorigen Aufruf-Programm kopieren kann.

Beispiel 13.3.3 Lesen eines Objektes aus einer Datei


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4 from clKonto import Konto
5 import pickle
6

7 alleKonten = {}
8

9 dateiName = ’[Link]’
10 ktoDatei = open(dateiName, ’rb’)
11 while ktoDatei:
12 try:
13 alleKonten = [Link](ktoDatei)
14 except EOFError:
15 break
16 [Link]()
17

18 print("angelegte Konten: ", [Link]())


19

W ICHTIG

Unter Python 2.x war der Dateizugriff mittels pickle nicht mehr mit Attributen
rb und wb, sondern mit r und w.

Ein leeres Dictionary wird angelegt, dann der Dateiname an eine Variable zugewiesen, die Datei wird
geöffnet, und dann wird die Datei, die nur ein einziges Objekt enthält, in das Dictionary eingelesen. Der
Lese-Prozess wird durch ein try - except - Konstrukt abgesichert. Danach wird die Datei geschlossen
und nur zur Kontrolle werden die gelesenen Kontonummern ausgegeben.

268
KAPITEL 13. DATEIZUGRIFF 13.3. IN DIE DATEI DAMIT!!!

13.3.2. Der Modul shelve


Mit Hilfe des Moduls shelve kann man eine Art Datenbank simulieren. Dazu gibt es gleich ein Beispiel.

Beispiel 13.3.4 Schreiben einer Struktur mittels shelve


1

2 class Person():
3 def __init__(self,v,n,o):
4 [Link] = v
5 [Link] = n
6 [Link] = o
7

8 class ShelveNamen():
9 def __init__(self):
10 import shelve
11 [Link] = [Link](’namen’,’w’)
12 def satzSchreiben(self, schluessel, p):
13 [Link][schluessel] = p
14 def schliessen(self):
15 [Link]()
16

17 datenbank = ShelveNamen()
18

19 for i in range(5):
20 vn = input(’Vorname: ’)
21 nn = input(’Nachname: ’)
22 ort = input(’Ort: ’)
23 per = Person(vn,nn,ort)
24 schluessel = input(’Schluessel: ’)
25 [Link](schluessel, per)
26 [Link]()
27

In den ersten 5 Zeilen wird eine Klasse Person beschrieben, die nur die 3 Attribute Vorname, Nach-
name und Ort hat. Methoden benötigt diese Klasse nicht, da die einzelnen Objekte nichts machen sollen,
sondern nur gespeichert werden sollen.
In den Zeilen 7 bis 14 wird eine Klasse ShelveNamen beschrieben, die im Konstruktor eine Datei an-
legt, die die Datensätze (also die Objekte) aufnehmen soll. Diese Klasse hat die Methode satzSchreiben,
die genau das macht, und die Methode schliessen, die die Datei am Ende schließt.
Im eigentlichen Programm wird dann zuerst eine datenbank angelegt, danach werden 5 Objekte der
Klasse Person erzeugt, jedes mit einem Schlüssel versehen und jeweils in die Datenbank geschrieben.
Zum Schluß wird die Datei geschlossen.

269
KAPITEL 13. DATEIZUGRIFF 13.4. AUFGABEN ZU DATEIEN

Das ergibt folgenden Dialog beim Aufruf:

Beispiel 13.3.5 Bildschirmausgabe des Programms


1

2 Vorname: Martin
3 Nachname: Schimmels
4 Ort: Oxxxxx
5 Schluessel: Martin
6 Vorname: Hannah
7 Nachname: yyyy
8 Ort: zzzz
9 Schluessel: Hannah
10 Vorname: Theresa
11 Nachname: xyz
12 Ort: xyz
13 Schluessel: Theresa
14 Vorname: Berthold
15 Nachname: zyx
16 Ort: zyxx
17 Schluessel: Berti
18 Vorname: Peter
19 Nachname: abc
20 Ort: abc
21 Schluessel: Peter
22

23 >>> db = [Link](’namen’,’r’)
24 >>> db[’Peter’].vn
25 ’Peter’
26 >>> db[’Peter’].nn
27 ’abc’
28 >>> db[’Martin’].nn
29 ’Schimmels’
30

Die ersten 20 Zeilen sind die Eingaben der je 3 Attribute jedes Objektes sowie des Schlüssels jedes
Objektes. Die folgende Zeile öffnet die Datei zum lesen. Und dann kommt das Datenbank-ähnliche“

dieser Speicherung: die einzelnen Attribute eines Datenbanksatzes (also eines Objekts) können mittels
des Schlüssels und des Attributnamens ausgelesen werden.

13.4. Aufgaben zu Dateien


1. Das Eisdielen-Programm soll weiter verändert werden, so dass eine Rechnung zu einer Bestellung
in eine Datei geschrieben wird. Die Rechnungen sollen eine eindeutige Rechnungsnummer be-
kommen (hochzählen!), und der Dateiname soll jeweils [Link] heißen (wobei 234 hier für
die Rechnungsnummer steht.

270
14. Datenbanken
If your mem’ry serves you well
(Bob Dylan 1 )

14.1. MySQL
Python hat Module für den Datenbankzugriff für viele verschiedene relationale Datenbanken. MySQL
ist eine Datenbank, die unter die freie Software fällt, und MySQL ist weit verbreitet, weil es eine sehr
mächtige Datenbank ist. Für MySQL gibt es auch die Möglichkeit, eine Lizenz zu erwerben und sich
damit Support zu sichern. Das führte dazu, dass MySQL nicht nur im Hobby“-Bereich verbreitet ist,

sondern auch große Unternehmen mit dieser Datenbank arbeiten.
Für die Arbeit mit Datenbanken gilt vieles, was auch für die Arbeit mit Dateien (siehe dort) gilt. Ein
Datenbankzugriff besteht immer aus drei Schritten:

1. Verbindung zur Datenbank herstellen


2. Aktion auf der Datenbank ausführen
3. Verbindung zur Datenbank lösen

Das Herstellen der Verbindung besteht wiederum aus zwei Teilen:

1. Eine Verbindung wird eingerichtet


2. Ein Cursor wird auf diese Verbindung gesetzt

Das Schreiben in eine Datenbank sieht im schlichtesten Fall folglich so aus:

Beispiel 14.1.1 Schreiben in eine Datenbank


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4

5 import MySQLdb
6 verbindung = [Link]("localhost", db="nameort",
7 user="karldepp", passwd="doof")
8 cursor = [Link]()
9

10 [Link]("INSERT INTO namen (vorname, name, plz)


11 VALUES (%s, %s, %s)", (’Ernst’, ’Maier’, ’72108’))
12

13 [Link]()
14 [Link]()
15

Das Modul für die Datenbank, hier für MySQL, muss import werden. Dieses Modul enthält eine Me-
thode connect, die als erstes aufgerufen wird. Auf die erstellte Verbindung wird der Cursor aufgesetzt,
sozusagen ein Zeiger auf die Datenbank, an den eventuelle Befehle übergeben werden. Im nächsten
Schritt wird für diesen Cursor die Methode execute aufgerufen, die den als Parameter übergebenen
SQL-Befehl ausführt. Danach wird zuerst der Cursor, dann die Verbindung geschlossen.
Das alles sind durchaus kritische Operationen. Aber der Umgang mit kritischen Operationen wurde
ja im vorigen Kapitel angerissen: Dinge, von denen man nicht weiß, ob sie wirklich so klappen, wie
1 This Wheel’s on Fire auf: The Basement Tapes

271
KAPITEL 14. DATENBANKEN 14.1. MYSQL

man sich das als Entwickler gedacht hat, versucht man erst und fängt eine mögliche Ausnahme ab. Eine
bessere Version sieht so aus:

Beispiel 14.1.2 Schreiben in eine Datenbank mit Fehlerbehandlung


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4

5 import MySQLdb
6 try:
7 verbindung = [Link]("localhost", db="nameort",
8 user="karldepp", passwd="doof")
9 except:
10 print(’Verbindung konnte nicht hergestellt werden’)
11 else:
12 try:
13 cursor = [Link]()
14 except:
15 print(’Cursor konnte nicht gesetzt werden’)
16 else:
17 [Link]("INSERT INTO namen (vorname, name, plz)
18 VALUES (%s, %s, %s)", (’Ernst’, ’Maier’, ’72108’))
19

20 [Link]()
21 [Link]()
22

Man sieht: das ist eine verschachtelte try - except Anweisung, da ja bei jedem Schritt eine Aus-
nahme auftreten kann.

272
KAPITEL 14. DATENBANKEN 14.1. MYSQL

Das ist aber nicht wirklich schön, diese geschachtelte try - except Anweisung. Hier ist es bes-
ser, mehrere Anweisungen zu versuchen und für jede mögliche Ausnahme eine spezielle Fehlerklasse
abzufragen. Das Programm ändert sich also noch einmal:

Beispiel 14.1.3 Schreiben in eine Datenbank mit differenzierter Fehlerbehandlung


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4

5 import MySQLdb
6 try:
7 verbindung = [Link]("localhost", db="plzort",
8 user="karldepp", passwd="doof")
9 cursor = [Link]()
10 except [Link]:
11 print(’Verbindung konnte nicht hergestellt werden’)
12 except:
13 print(’Cursor konnte nicht gesetzt werden’)
14 else:
15 try:
16 [Link]("INSERT INTO plzort (plz, ort)
17 VALUES (%s, %s)", (’72070’, ’Tübingen’))
18 except:
19 print(’Insert fehlgeschlagen’)
20 else:
21 print(’ok’)
22 [Link]()
23 [Link]()
24 [Link]()
25

26

MySQL (wie jeder SQL-Dialekt) puffert Befehle. Wenn man mit einer Entwicklungsumgebung wie
zum Beispiel der MySQL-Workbench arbeitet, merkt man das gar nicht. Bei einem solchen Werkzeug,
das für das interaktive Arbeiten ausgerichtet ist, ist es wichtig, dass das Ergebnis der Eingabe eines
Befehls gleich sichtbar ist. Befehle werden hier sofort ausgeführt. Wenn man nicht interaktiv arbeitet,
muss man das Schreiben aus dem Puffer in die Datenbank meistens von Hand anstoßen. Das geschieht
mit dem SQL-Befehl commit.

Das Lesen aus einer Datenbank ist ein ganzes Stück komplizierter. Das sollte eigentlich klar sein: wenn
ich (in eine Datenbank) schreibe, weiß ich, was ich schreibe; da kann nichts unerwartetes passieren.
Wenn ich ein Wort schreibe, dann ist das Ergebnis ein Wort, wenn ich zehn Wörter schreibe, ist das
Ergebnis zehn Wörter, wenn ich 3 Zahlen schreibe, ist das Ergebnis 3 Zahlen.

Wenn ich (aus einer Datenbank) lese, weiß ich nicht, was da auf mich zukommt. Das kann ein Wort,
das können 10 Wörter oder 3 Zahlen sein. Auf eine Datenbank bezogen bedeutet das, dass ich das
Ergebnis eines SELECT-Befehls nicht vorhersagen kann. Da kann es noch schlimmer kommen, als es
im vorigen Satz geschildert wurde: es kann sogar gar nichts als Ergebnis zurückgegeben werden! Die
Ergebnismenge kann 0, 1 oder viele Elemente enthalten.

Deswegen ist das Vorgehen ein leicht anderes. Die erste Änderung ist, dass das Ergebnis der Ausführung
des Befehls, also das, was durch [Link]() geschieht, einer Variablen zugewiesen werden muss.
Die zweite Änderung ist dann eigentlich logisch: über das, was in dieser Variablen steht, muss jetzt eine
Schleife gemacht werden, damit ich die einzelnen Datensätze nacheinander verarbeiten kann.

273
KAPITEL 14. DATENBANKEN 14.2. .. MIT PYTHON-BORDMITTELN

Beispiel 14.1.4 Lesen aus einer Datenbank


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4

5 import MySQLdb
6 connection = [Link]("localhost", db="nameort",
7 user="karldepp", passwd="doof")
8 cursor = [Link]()
9 t2 = [Link]("SELECT * FROM namen")
10 for i in range(t2):
11 print([Link]())
12

13 [Link]()
14 [Link]()
15

14.2. .. mit Python-Bordmitteln


In Python gibt es einen weiteren Daten-Verpacker, der wie pickle Objekte entgegen nimmt, aber einige
Fähigkeiten mehr hat. Der Modul shelve hat Eigenschaften, die an eine Datenbank erinnern.

274
Teil IX.

Noch ein paar Beispiele zur OOP

275
15. Ein weiteres Projekt: ein Getränkeautomat
15.1. Objektorientierter Entwurf und Realisierung der Klasse
Ein Getränkeautomat nimmt Geld entgegen und spuckt ein Getränk aus, sofern das Geld reicht und die
Ware vorhanden ist. Falls zuviel Geld eingeworfen wurde, wird das restliche Geld auch ausgegeben.
Diese Beschreibung gilt nicht nur für einen Getränkeautomaten, sondern allgemein für einen Auto-
maten: der nimmt Geld entgegen, überprüft den Warenbestand, gibt Waren aus und berechnet Restgeld
und gibt das zurück. Deswegen wird die Klasse gleich als allgemeiner Automat codiert. Wiederverwert-
barkeit ist ja eines der Ziele der objektorientierten Programmierung.
Die einfache Klasse sieht folgendermaßen aus:

Abbildung 15.1. Klassendiagramm Automat

Die einzelnen Methodennamen sprechen hoffentlich für sich. Trotzdem:


• bestandPruefen: ist noch genügend des gewünschten Getränks im Automaten?
• geldEinwerfen: Klar! Hier soll aber geprüft werden, ob es eine zulässige Münze ist
• neueWareAufnehmen: ein neues Getränk wird eingespeist
• wareWaehlen: Welches Schweinderl hättn’s denn gern?

277
KAPITEL 15. EIN WEITERES PROJEKT: EIN . . . 15.1. OBJEKTORIENTIERTER ENTWURF . . .

Beispiel 15.1.1 Klassenentwurf des Getränkeautomaten


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4

5 class Automat():
6 def __init__(self, waren=[], kredit = 0):
7 [Link] = waren
8 [Link] = kredit
9

10 def geldEinwerfen(self):
11 print(’Geld eingeworfen’)
12

13 def guthabenAnzeigen(self):
14 print(’Guthaben anzeigen’)
15

16 def wareWaehlen(self):
17 print(’Ware auswählen’)
18

19 def neueWareAufnehmen(self):
20 print(’neue Ware hinzugenommen’)
21

22 def bestandPruefen(self):
23 print(’Bestand der gewählten Ware geprüft’)
24

Dieser Klassenentwurf wird in einer Datei cl [Link] gespeichert.


Das interessanteste und vielleicht wichtigste Attribut ist das Attribut waren. Das ist eine Liste, in
die in einem der späteren Entwicklungsschritte eine ganze Menge von Waren eingelagert“ werden. Da

zu Beginn von einem leeren Automaten ausgegangen wird, wird an den Konstruktor eine leere Liste
übergeben. Außerdem sind die einzelnen Methoden noch nicht ausformuliert, sondern geben einfach
einen Text aus.
Zu der Klasse Automat gehört jetzt eigentlich ein aufrufendes Programm. Dieses sollte die einzelnen
Methoden testen, die bisher nur als Dummies“ existieren. Die einfache Lösung wäre ein sequentielles

Programm, das eine Instanz des Automaten erzeugt und dann nacheinander die einzelnen Methoden
aufruft.
Aber das würde den Regeln der Objektorientiertheit widersprechen. Denn das, was im vorigen Ab-
schnitt beschrieben wurde, ist eigentlich wieder ein Objekt, nämlich ein Objekt einer noch zu schaffen-
den Klasse Menu. Diese Klasse benötigt nur eine einzige Methode, die Methode auswahlTreffen
• auswahlTreffen: das Menu für den Getränkeautomaten: neue Waren anlegen, Geld einkassieren,
etc.

Also dann: los gehts!

278
KAPITEL 15. EIN WEITERES PROJEKT: EIN . . . 15.1. OBJEKTORIENTIERTER ENTWURF . . .

Beispiel 15.1.2 Klassenentwurf des Menus


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4

5 from cl_automat import Automat


6

7 class Menu():
8

9 def __init__(self):
10 [Link] = Automat()
11 [Link] = ’g = Geld einwerfen,
12 w = Ware wählen, n = neue Ware einführen,
13 e = Ende\n’
14

15 def auswahlTreffen(self):
16 auswahl = [’e’, ’w’, ’g’, ’n’]
17 eingabe = ’x’
18 while eingabe <>’e’:
19 eingabe = input([Link])
20 if eingabe == ’g’:
21 [Link]()
22 elif eingabe == ’w’:
23 [Link]()
24 elif eingabe == ’n’:
25 [Link]()
26 elif eingabe == ’e’:
27 pass
28 else:
29 print(’fehlerhafte Eingabe; nur e, g, n, w zulässig’)
30

Damit das Menu weiß, dass es sich um ein Menu für einen Automaten handelt, muss zuerst die Klas-
senbeschreibung aus der Datei cl automat importiert werden; danach wird im Konstruktor des Menus
ein Objekt der Klasse Automat erzeugt. Die Methode auswahlTreffen ruft dann die Methoden des
Automaten auf.
Wie immer gehört dazu auch ein aufrufendes Programm, das einfach ein Objekt der Klasse anlegt
und dann die Haupt-Methode der Klasse, nämlich das Auswahlmenu aufruft.

Beispiel 15.1.3 Das aufrufende Programm für den Getränkeautomaten


#!/usr/bin/python
# -*- coding: utf-8 -*-

from cl_menu import Menu

getraenkeautomat = Menu()
[Link]()

Das ist doch richtig schön, ein solch kurzes Programm. Die ganze Intelligenz steckt in der Klasse. Und
jedes Objekt der Klasse macht alles genau so gut wie jedes andere!!
Kommen wir also zur zweiten Version, in der ein bißchen etwas passiert.

279
KAPITEL 15. EIN WEITERES PROJEKT: EIN . . . 15.2. DIE WAREN KOMMEN IN DEN . . .

15.2. Die Waren kommen in den Automaten


. . . und damit die Waren in den Automaten kommen, müssen wir natürlich zuerst eine Klasse für die
Waren deklarieren.

Abbildung 15.2. Klassendiagramm Ware

Diese Klasse hat vorläufig eine einzige Methode, nämlich den Konstruktor.
Interaktiv soll jetzt eine Ware angelegt werden, wobei die drei Attribute des Objektes gefüllt werden.
Gleichzeitig wird die Methode warenAnzeigen geschrieben, die jedes Mal nach Anlegen eines neuen
Objektes aufgerufen wird. Im folgenden werden nur diese beiden Methoden angezeigt, der Rest der
Klassendefinition bleibt so wie in der vorigen Version.

Beispiel 15.2.1 Die Waren kommen hinzu


1

2 class Ware():
3 def __init__(self, bezeichnung, verkPreis, bestand):
4 [Link] = bezeichnung
5 [Link] = verkPreis
6 [Link] = bestand
7

8 class Automat():
9 ...
10 ...
11 def warenAnzeigen(self):
12 print(’folgende Waren können gekauft werden: ’)
13 print(’%20s %10s %10s’ % (’Ware’, ’Preis’, ’Bestand’))
14 for ware in [Link]:
15 print(’%20s %10.2f %10i’ % ([Link], [Link], [Link]))
16

17 def neueWareAufnehmen(self):
18 bez = input(’Bezeichnung der neuen Ware: ’)
19 vkPr = float(input(’Verkaufspreis der neuen Ware: ’))
20 best = float(input(’Lagerbestand der neuen Ware: ’))
21 nW = ware(bez, vkPr, best)
22 [Link](nW)
23 print(’neue Ware hinzugenommen’)
24 [Link]()
25

Das aufrufende Programm ändert sich überhaupt nicht! (Ist das ein gutes Zeichen??? Schon, oder? )

15.3. Geld regiert die Welt


Jetzt soll das Geld behandelt werden. Das bedeutet, dass die Methode des Geldeinwerfens geschrieben
werden muss, und es ist sinnvoll, die Methode, die den aktuell eingeworfenen Betrag anzeigt, gleich
mitzubehandeln. Das UML-Diagramm der Klasse ändert sich nicht, nur die beiden angesprochenen
Methoden werden ausformuliert.

280
KAPITEL 15. EIN WEITERES PROJEKT: EIN . . . 15.4. JETZT KANN GEKAUFT WERDEN!

Beispiel 15.3.1 Geld einwerfen und Guthaben anzeigen


1

2 def geldEinwerfen(self):
3 muenzen = [1, 2, 5, 10, 20, 50, 100, 200]
4 einwurf = float(input(’Münze einwerfen: ’))
5 if einwurf in muenzen:
6 [Link] += einwurf
7 else:
8 print(’ungültige Münze, gültig sind: ’, muenzen)
9 [Link]()
10

11 def guthabenAnzeigen(self):
12 print(’aktuelles Guthaben: %5.2f \euro\/ ’ % ([Link]/100.0))
13

Das ist wirklich sehr einfach. Es wird eine Liste der zulässigen Münzen erstellt (dabei muss nur beach-
tet werden, dass 100 Cent gleich 1 e ist). Falls man eine korrekte Münze eingibt, wird das zum aktuellen
Guthaben — hier Kredit genannt — dazuaddiert.
Das aufrufende Programm ändert sich überhaupt nicht! (Ist das ein gutes Zeichen??? Aber sicher!! )
Ich weiß, ich wiederhole mich . . .

15.4. Jetzt kann gekauft werden!


Es fehlt nur noch die Realisierung der Methoden, die für den tatsächlichen Kauf zuständig sind. Dazu
gehört, dass geprüft wird, ob der Bestand ausreichend ist und ob das Guthaben groß genug ist. Falls
ja, muss Restgeld herausgegeben werden und das Guthaben zurückgesetzt werden. Außerdem muss in
diesem Fall der Bestand heruntergezählt werden.

Beispiel 15.4.1 Der Kauf


1

2 def wareWaehlen(self):
3 print(’Ware auswählen’)
4 [Link]()
5 ausgewaehlt = input(’Nr. der gewünschten Ware eingeben: ’)
6 if not [Link](ausgewaehlt):
7 print(’zu wenig Ware auf Lager’)
8 elif [Link] <= [Link][ausgewaehlt].verkPreis:
9 print(’Du hast zuwenig Geld eingeworfen’)
10 else:
11 print(’Ware wird ausgegeben’)
12 [Link][ausgewaehlt].bestand -= 1
13 print(’Restgeld %4.2f \euro\/ wird ausgegeben’ %
14 ([Link] - [Link][ausgewaehlt].verkPreis))
15 [Link] = 0.0
16

17 def bestandPruefen(self, nr):


18 if [Link][nr].bestand <= 1:
19 return False
20 else:
21 return True
22

Hier gehört nur noch ein blöder Spruch hin: Das aufrufende Programm ändert sich überhaupt nicht!
(Ist das ein gutes Zeichen??? Super!!!! )

281
KAPITEL 15. EIN WEITERES PROJEKT: EIN . . . 15.5. TO DO!!

15.5. To Do!!
Vorschläge, was zu diesem Programm noch hinzugefügt werden kann:
• Fehler müssen abgefangen werden (z.B. wenn man eine Produktnummer außerhalb des gültigen
Bereichs wählt)
• Die Münzen können erweitert werden, so dass auch Geldscheine angenommen werden.
• Eine Stückelung des Restgeldes kann realisiert werden, wobei zu beachten ist, dass nicht die opti-
male Stückelung herausgegeben wird, sondern unter Umständen auch viel Kleingeld, weil andere
Münzen nicht mehr vorhanden sind. Aha: ein Geldbestand des Automaten muss also hinzugefügt
werden.
• Es kann ermöglicht werden, dass man mehr Geld als für eine Ware einwirft und dann auch meh-
rere Waren kauft.

282
16. Noch ein Beispiel: Zimmerbuchung in
einem Hotel
16.1. Vorstellung des Projekts
Natürlich soll hier nicht eine vollständige Software für das Management eines Hotels geschrieben wer-
den. Das Modell wird sehr vereinfacht, und in verschiedenen Versionen dann verfeinert.
Wir gehen von einem Hotelzimmer aus. Dieses wird als Klasse modelliert, wobei diese Klasse bewusst
einfach gehalten wird.

16.2. Der erste Entwurf: Eine Klasse für Hotelzimmer


Ein ordentliches Hotelzimmer hat eine Zimmernummer, man sollte wissen, wieviele Betten in dem Zim-
mer sind, ob das Zimmer aktuell frei ist und wieviel eine Übernachtung in diesem Zimmer kostet. Man
sollte die Attribute des Zimmers, so wie sie im vorigen Satz beschrieben worden sind, anzeigen können
und in dieser ersten Version den Schalter für die Belegung (frei / belegt) umlegen können. Das UML-
Bild dazu sieht folgendermaßen aus (beachte dabei, dass die Attribute und Methoden alphabetisch sor-
tiert sind).

Abbildung 16.1. Klassendigramm Hotelzimmer

283
KAPITEL 16. NOCH EIN BEISPIEL: . . . 16.2. DER ERSTE ENTWURF: EINE KLASSE . . .

Die Realisierung in Python folgt:

Beispiel 16.2.1 Eine erste Klasse


#!/usr/bin/python
# -*- coding: utf-8 -*-

class Hotelzimmer():
def __init__(self, nr, anzBetten, preis = 30, frei = True):
[Link] = nr
[Link] = anzBetten
[Link] = frei
[Link] = preis

def belegen(self):
if [Link]:
[Link] = False
else:
print(’Zimmer ist bereits belegt’)

def freigeben(self):
if [Link]:
print(’Zimmer ist bereits frei’)
else:
[Link] = True

def anzeigen(self):
print(’Nr.:’, [Link], ’Anzahl Betten: ’, [Link])
if [Link]:
print(’frei’)
else:
print(’belegt’)

if __name__ == ’__main__’:
zi1 = Hotelzimmer(1, 2)
[Link]()
[Link]()
[Link]()
[Link]()
[Link]()
[Link]()
[Link]()

Der Konstruktor bekommt als Parameter die oben genannten Attribute, wobei den Attributen preis
und frei ein Defaultwert mitgegeben wird. Die Methoden belegen und freigeben fragen den ak-
tuellen Stand ab und führen die gewünschte Aktion durch, wenn sie möglich ist. Beachte hierbei, dass
das Attribut frei mit den Wahrheitswerten True und False arbeitet.

284
KAPITEL 16. NOCH EIN BEISPIEL: . . . 16.3. DER ZWEITE ENTWURF: EIN . . .

A NMERKUNG
Da dieser Klassenentwurf noch sehr einfach ist, wird hier kein externes auf-
rufendes Programm geschrieben, sondern über die Abfrage if name ==
’ main ’: die Klasse aus sich heraus gestartet. Es wird mit dieser Zeile ab-
gefragt, ob dieses Modul als Hauptprogramm oder als eine importierte Datei
gestartet wird. Da das jetzt das Hauptprogramm ist, werden die folgenden Zeilen
ausgeführt

16.3. Der zweite Entwurf: ein aufrufendes Programm


You could have done better
But I don’t mind
(Bob Dylan 1 )
Die Klasse Hotelzimmer wird hier nicht verändert, sondern es wird ein aufrufendes Programm
hinzugefügt. Dieses bietet in einer Endlos-Schleife ein Menu an und verarbeitet die Auswahl.

Beispiel 16.3.1 Menu fürs Hotel


#!/usr/bin/python
# -*- coding: utf-8 -*-
from clZimmer import Hotelzimmer

def menu():
auswahl = input(’\n#### AUSWAHL ####\nZimmer anzeigen: Z
\nZimmer belegen: B\nZimmer freigeben: F
\nEnde: E\n#### ....... ####
\b\b\b\b\b\b\b\b\b\b\b\b’)
menuListe = {’Z’: [Link], ’B’: [Link],
’F’: [Link], ’E’: beenden}
menuListe[auswahl]()

def beenden():
global weiter
print(’danke für Deinen Besuch’)
weiter = 0

weiter = 1
zimmer1 = Hotelzimmer(1, 2)
while weiter:
menu()

1 Don’t think twice, it’s alright auf: The Freewheeling Bob Dylan

285
KAPITEL 16. NOCH EIN BEISPIEL: . . . 16.4. DER DRITTE ENTWURF: DAS HOTEL

16.4. Der dritte Entwurf: das Hotel


Dieser dritte Entwurf geht wesentlich weiter: wenn man viele freie Zimmer hat, kann man ein Hotel
aufmachen. Oder in der Sprache Python: ich erstelle eine neue Klasse Hotel, die als einziges Attribut
eine (zu Beginn leere) Liste von Zimmern hat. (Fast einziges Attribut: es gibt noch ein Attribut weiter,
das die Werte True oder False annehmen kann. Das Hotel hat ferner die Methode menu, die vom
Konstruktor aufgerufen wird und eine Endlos-Schleife enthält, die die anderen Methoden aufruft.
Diese anderen Methoden sind:
• anzeigen: ruft (falls es überhaupt schon Zimmer gibt!!) in einer Schleife die Methode anzeigen der
Klasse Hotelzimmer auf.
• beenden: beendet die Endlos-Schleife dadurch, dass der Schalter weiter umgelegt wird.
• neuesZimmerAnlegen: erfragt vom Benutzer die benötigten Werte und ruft dann den Konstruktor
der Klasse Hotelzimmer auf.
• belegen: ist noch nicht realisiert, sondern nur als Muster angelegt.
• freigeben: ist noch nicht realisiert, sondern nur als Muster angelegt.
Das zugehörige UML-Diagramm sieht so aus:

Abbildung 16.2. Klassendiagramm Hotel

286
KAPITEL 16. NOCH EIN BEISPIEL: . . . 16.4. DER DRITTE ENTWURF: DAS HOTEL

Beispiel 16.4.1 Entwurf der Klasse Hotel


class Hotel():
def __init__(self):
[Link] = []
[Link] = True
while [Link]:
[Link]()

def menu(self):
auswahl = input(’\n#### AUSWAHL ####\nalle Zimmer anzeigen: Z
\nZimmer belegen: B\nZimmer freigeben: F
\nneues Zimmer anlegen: N
\nEnde: E\n#### ....... ####
\b\b\b\b\b\b\b\b\b\b\b\b’)
menuListe = {’Z’: [Link], ’B’: [Link],
’F’: [Link], ’N’:[Link],
’E’: [Link]}
menuListe[auswahl]()

def beenden(self):
print(’danke für Deinen Besuch’)
[Link] = False

def anzeigen(self):
if len([Link]) == 0:
print(’Es gibt noch keine Zimmer’)
else:
for zimmer in [Link]:
[Link]()

def belegen(self):
print(’Funktion noch nicht verfügbar’)

def freigeben(self):
print(’Funktion noch nicht verfügbar’)

def neuesZimmerAnlegen(self):
anzBetten = int(input(’Anzahl Betten des Zimmers: ’))
preis = float(input(’Preis des Zimmers: ’))
neuesZi = Hotelzimmer(len([Link])+1, anzBetten, preis)
[Link](neuesZi)

Hinzu kommt ein aufrufendes Programm. Nicht erschrecken: völlig undurchschaubar !!!!!

Beispiel 16.4.2 Aufrufendes Programm für das Hotel


#!/usr/bin/python
# -*- coding: utf-8 -*-
from clZiHo import Hotel

meinHotel = Hotel()

287
KAPITEL 16. NOCH EIN BEISPIEL: . . . 16.5. DER VIERTE ENTWURF: METHODEN . . .

16.5. Der vierte Entwurf: Methoden werden ergänzt


Die Methode anzeigen der Klasse Hotel bekommt den zusätzlichen Parameter frei; sofern dieser
den Wert True hat, werden nur die freien Zimmer angezeigt.
Die Methoden belegen und freigeben rufen nach Auswahl des Zimmers durch den Benutzer die
entsprechende Methode der Klasse Hotelzimmer auf.
Vorsicht! Da es kein Zimmer mit der Nummer ”0”gibt, Python aber ab 0 zählt, muss hier der einge-
gebene (weil angezeigte) Index um eins vermindert werden.

288
KAPITEL 16. NOCH EIN BEISPIEL: . . . 16.5. DER VIERTE ENTWURF: METHODEN . . .

Beispiel 16.5.1 Nächster Entwurf für die Klasse Hotel


class Hotel():
def __init__(self):
[Link] = []
[Link] = True
while [Link]:
[Link]()

def menu(self):
auswahl = input(’\n#### AUSWAHL ####\nalle Zimmer anzeigen: Z
\nZimmer belegen: B\nZimmer freigeben: F
\nneues Zimmer anlegen: N
\nEnde: E\n#### ....... ####
\b\b\b\b\b\b\b\b\b\b\b\b’)
menuListe = {’Z’: [Link], ’B’: [Link],
’F’: [Link], ’N’:[Link],
’E’: [Link]}
menuListe[auswahl]()

def beenden(self):
print(’danke für Deinen Besuch’)
[Link] = False

def anzeigen(self, frei = False):


if len([Link]) == 0:
print(’Es gibt noch keine Zimmer in diesem Hotel’)
else:
if frei:
for zimmer in [Link]:
if [Link]:
[Link]()
else:
for zimmer in [Link]:
[Link]()

def belegen(self):
print(’folgende Zimmer sind verfügbar: ’)
# erster Parameter = True: freie Zimmer anzeigen
[Link](True)
auswahl = int(input(’gewünschte Zimmer-Nr. angeben: ’))
[Link][auswahl - 1].belegen()

def freigeben(self):
[Link](False)
auswahl = int(input(’freizugebendes Zimmer: ’))
[Link][auswahl - 1].freigeben()

def neuesZimmerAnlegen(self):
anzBetten = int(input(’Anzahl Betten des Zimmers: ’))
preis = float(input(’Preis des Zimmers: ’))
neuesZi = Hotelzimmer(len([Link])+1, anzBetten, preis)
[Link](neuesZi)

289
17. Und noch ein Beispiel: ein Adressbuch

17.1. Vorstellung des Projekts

Auch dieses Beispiel soll Schritt für Schritt entwickelt werden, wobei in diesem Fall zuerst das Adress-
buch (der Name stimmt nicht, denn unter dem Namen einer Person werden nicht seine Adressda-
ten gespeichert, sondern sein Alter. Einfach weniger zu schreiben, Faulheit regiert die Welt.) nicht-
objektorientiert realisiert wird. Auch das wird zeigen, dass es in Python einfach und vor allem durch-
schaubar ist, ein solches kleines Projekt durchzuführen. Vor allem sind die Veränderungen von einem
Schritt zum nächsten oft offensichtlich und gut nachzuvollziehen.
Es sollen in diesem Adressbuch nur drei Daten einer Person gespeichert werden, der Vorname, der
Nachname und das Alter. Im Adressbuch sollen diese drei Daten geändert werden können, es sol-
len natürlich neue Datensätze hinzugefügt werden können und ebenso soll man Datensätze löschen
können.

17.2. Der erste Entwurf: eine Liste von Listen

Der erste Versuch speichert die Daten einer Person in einer Liste. Das sieht also so aus:

Beispiel 17.2.1 Adresse in einer Liste

#!/usr/bin/python
# -*- coding: utf-8 -*-

martin = [’Martin’, ’Schimmels’,54]


ekki = [’Eckard’, ’Krauss’,41]

Die Personen-Daten von mehreren Personen speichern wir in einer Liste von Listen, also:

namen = [martin,ekki]

Auf diese Informationen kann man jetzt über die üblichen Listen-Operationen zugreifen (daran denken:
man fängt bei 0 an zu zählen!), im folgenden Programm-Listing in der ersten for-Schleife auf die Ele-
mente der äußeren Liste, in der zweiten for-Schleife auf die Elemente der Elemente der äußeren Liste,
also auf die Elemente der jeweils inneren Listen.

291
KAPITEL 17. UND NOCH EIN BEISPIEL: EIN . . . 17.3. DER ZWEITE ENTWURF: EIN FAULER . . .

Beispiel 17.2.2 Zugriff auf die Adress-Liste

#!/usr/bin/python
# -*- coding: utf-8 -*-

martin = [’Martin’, ’Schimmels’,54]


ekki = [’Eckard’, ’Krauss’,41]
namen = [martin,ekki]

for einName in namen:


print(einName)

for einName in namen:


print(einName[0],einName[1])

Die Ausgabe sieht so aus:

>>> [’Martin’, ’Schimmels’, 54]


>>> [’Eckard’, ’Krauss’, 41]
>>> Martin Schimmels
>>> Eckard Krauss

17.3. Der zweite Entwurf: ein fauler Trick


Hier soll nur eine weiter oben bei [anwTupel] bereits angesprochene Vereinfachung eingebaut werden.
Vielen wird das wie ein fauler Trick vorkommen, aber es ist etwas sehr Python-spezifisches. Da die Da-
ten in einem Datensatz immer an der selben Stelle auftauchen, Vorname immer an 0. Stelle, Alter immer
an 2. Stelle, wird hier eine Tupel-Zuweisung gemacht, so dass man die Elemente eines Datensatzes mit
ihren Bedeutungen ansprechen kann:

Beispiel 17.3.1 Adress-Liste (mit faulem Trick)


#!/usr/bin/python
# -*- coding: utf-8 -*-

martin = [’Martin’, ’Schimmels’,54]


ekki = [’Eckard’, ’Krauss’,41]
namen = [martin,ekki]
#### Trick: Dem Tupel vorname, nachname, alter wird das Tupel 0,1,2 zugewiesen.
#### Damit kann man
#### das [Link] Element mit dem "Index" "vorname" ansprechen
vorname, nachname, alter = 0, 1, 2

for einName in namen:


print(einName)

for einName in namen:


print(einName[vorname],einName[nachname])

292
KAPITEL 17. UND NOCH EIN BEISPIEL: EIN . . . 17.4. DER DRITTE ENTWURF: EINE LISTE . . .

17.4. Der dritte Entwurf: eine Liste von Dictionaries


Was mit dem vorigen Trick bereits angedeutet wurde, wird hier mit typischen Python-Mitteln realisiert:
die Daten jeder einzelnen Person werden in einem Dictionary gespeichert, die Dictionaries kommen in
eine Liste.

Beispiel 17.4.1 Adress-Liste als Dictionary


#!/usr/bin/python
# -*- coding: utf-8 -*-

martin = {’vorname’:’Martin’, ’nachname’:’Schimmels’,’alter’:54}


ekki = {’vorname’:’Eckard’, ’nachname’:’Krauss’,’alter’:41}
namen = [martin,ekki]

for einName in namen:


print(einName)

for einName in namen:


print(einName[’vorname’],einName[’nachname’])

Das ist zwar ein bißchen mehr Schreibarbeit, aber es ist dafür auch noch nach Jahren beim ersten
Lesen zu verstehen!

293
KAPITEL 17. UND NOCH EIN BEISPIEL: EIN . . . 17.5. DER VIERTE ENTWURF: AKTIONEN . . .

17.5. Der vierte Entwurf: Aktionen (aber nur angedeutet)!!


In diesem Entwurf wird das Adressbuch mit Leben gefüllt, das heißt, hier werden Funktionen eingefügt,
die tatsächlich etwas mit den Daten machen. Zuerst muss aber ein Menu eingebaut werden, das diese
Funktionen in einer Endlos-Schleife aufruft. Die Funktionen werden erst einmal als Dummy angelegt,
das Menu selber fehlt noch. Aber wenn das Menu dann fertig ist, weiß ich schon, was gemacht werden
soll: die Initialisierung wird gestartet, dann verschwindet man im Menu, bis dieses ausdrücklich wieder
verlassen wird. Der Rahmen dafür sieht so aus:

Beispiel 17.5.1 Funktionen für die Adress-Liste(noch Dummies)


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4

5 def initialisiere():
6 global namen
7 martin = {’vorname’:’Martin’, ’nachname’:’Schimmels’,’alter’:54}
8 ekki = {’vorname’:’Eckard’, ’nachname’:’Krauss’,’alter’:41}
9 namen = [martin,ekki]
10

11 def anzeigen(mitNummer = False):


12 print(’hier ist Funktion anzeigen’)
13

14 def einfuegen():
15 print(’hier ist Funktion einfügen’)
16

17 def aendern():
18 print(’hier ist Funktion ändern’)
19

20 def loeschen():
21 print(’hier ist Funktion loeschen’)
22

23 def beenden():
24 print(’Jetzt wird das Programm beendet’)
25

26 def menu():
27 print(tut mir leid, das Menu ist noch nicht fertig’)
28

29 initialisiere()
30 menu()
31

An die Arbeit! Das Menu wird gebaut. Zuerst wird ein Schalter weiter eingefügt, dessen Wert stan-
dardmäßig 1 (und damit True) ist und dessen Wert nur bei Betätigung der Taste E auf 0 (und damit auf
False) geändert wird. Danach wird in der Endlos-Schleife (solange weiter = True ist) ein Buchstabe ein-
gelesen. Die vielen \b“ bewirken, dass der Buchstabe in der letzten Zeile der Eingabeaufforderung an

der Stelle der Punkte eingelesen wird. Jetzt passiert wieder etwas, was in Python so elegante Program-
me erlaubt. Wert in einem Dictionary kann irgendetwas sein: eine Zahl, ein Text, eine Liste, selbst noch
ein Dictionary, aber auch eine Funktion. Das wird hier ausgenutzt: das Menu selber ist ein Dictionary,
dessen Schlüssel die einzugebenden Buchstaben und dessen Werte die Funktionen sind. Damit ist der
Aufruf der Funktion je nach eingegebenem Buchstabe nur noch das Herausholen eines Wertes aus dem
Dictionary.

294
KAPITEL 17. UND NOCH EIN BEISPIEL: EIN . . . 17.5. DER VIERTE ENTWURF: AKTIONEN . . .

Beispiel 17.5.2 Adress-Liste mit Menu


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4

5 def initialisiere():
6 global namen
7 martin = {’vorname’:’Martin’, ’nachname’:’Schimmels’,’alter’:54}
8 ekki = {’vorname’:’Eckard’, ’nachname’:’Krauss’,’alter’:41}
9 namen = [martin,ekki]
10

11 def anzeigen(mitNummer = False):


12 print(’hier ist Funktion anzeigen’)
13

14 def einfuegen():
15 print(’hier ist Funktion einfügen’)
16

17 def aendern():
18 print(’hier ist Funktion ändern’)
19

20 def loeschen():
21 print(’hier ist Funktion loeschen’)
22

23 def beenden():
24 print(’Jetzt wird das Programm beendet’)
25

26 def menu():
27 weiter = 1
28 while weiter:
29 auswahl = input(’#### AUSWAHL ####\n
30 alle Namen anzeigen: Z\n
31 Namen einfügen: N\n
32 Namen löschen: L\n
33 Namen ändern: A\n
34 Ende: E\n
35 #### ....... ####\b\b\b\b\b\b\b\b\b\b\b\b’)
36 menuListe = {’N’: einfuegen, ’L’: loeschen,’A’:aendern,
37 ’E’:beenden, ’Z’:anzeigen}
38 menuListe[auswahl]()
39 if auswahl == ’E’:
40 weiter = 0
41

42 initialisiere()
43 menu()
44

295
KAPITEL 17. UND NOCH EIN BEISPIEL: EIN . . . 17.6. DER FÜNFTE ENTWURF: AKTIONEN . . .

17.6. Der fünfte Entwurf: Aktionen (jetzt tut sich wirklich etwas)!!
Jetzt wollen wir etwas sehen. Also fangen wir mit der Funktion anzeigen an. In dieser Funktion muss
die Liste namen als global bekanntgegeben werden. Danach wird eine Überschriftszeile generiert. Die
Ausgabe der einzelnen Datensätze geschieht in einer for-Schleife, analog wie im dritten Entwurf.

Beispiel 17.6.1 Adress-Liste anzeigen


1

2 def anzeigen():
3 global namen
4 print(’##### Namensliste #####’)
5 for einName in namen:
6 print(’##\t’, end=’ ’)
7 print(einName[’vorname’],einName[’nachname’],einName[’alter’])
8 print(’##### ----------- #####’)
9

Das Einfügen eines neuen Namens in die Liste ist auch kein Hexenwerk. Die einzelnen Informationen
werden über input eingelesen, das ganze wird zu einem Dictionary verbunden und dieses Dictionary
wird an die Liste namen angehängt

Beispiel 17.6.2 Eintrag in Adress-Liste machen


1

2 def einfuegen():
3 global namen
4 print(’Neuer Name wird eingefügt!’)
5 vorname = input(’Vorname: ’)
6 nachname = input(’Nachname: ’)
7 alter = input(’Alter: ’)
8 [Link]({’vorname’:vorname, ’nachname’:nachname, ’alter’:alter})
9

Das Löschen eines Namens ist eigentlich auch nicht viel schwieriger. Dazu kommt die Funktion del
für Listen ins Spiel, die mit der Nummer des Listenelements aufgerufen wird. Wenn die Liste aller-
dings länger (als 5) ist, wird die Abzählerei doch ein wenig lästig. Deswegen muss zuerst die Funktion
anzeigen so abgeändert werden, dass zusätzlich zu den Informationen über die Personen auch noch
die laufende Nummer in der Liste angezeigt wird. Dazu wird die Funktion anzeigen mit einem Para-
meter, der den Wahrheitswert True hat, aufgerufen. Der Standardwert für diesen Parameter ist False.

Beispiel 17.6.3 Adress-Liste mit Nummern anzeigen


1

2 def anzeigen(mitNummer = False):


3 global namen
4 i = 0
5 print(’##### Namensliste #####’)
6 for einName in namen:
7 print(’##\t’, end=’ ’)
8 if mitNummer:
9 print(i, end=’ ’)
10 i += 1
11 print(einName[’vorname’],einName[’nachname’],einName[’alter’])
12 print(’##### ----------- #####’)
13

Und die Funktion löschen“ gleich hintendran:


296
KAPITEL 17. UND NOCH EIN BEISPIEL: EIN . . . 17.6. DER FÜNFTE ENTWURF: AKTIONEN . . .

Beispiel 17.6.4 Adresse löschen


def loeschen():
global namen
print(’Diese Namen sind in der Liste! ’)
anzeigen(1)
loeschNr = input(’Bitte Nummer des zu löschenden Namens eingeben: ’)
del namen[loeschNr]

Richtig umfangreich wird jetzt allerdings die Funktion aendern. Allerdings wirklich nur umfang-
reich, schwierig ist das nicht. Es werden wieder alle Einträge mit laufender Nummer angezeigt, man
wählt eine Nummer aus, die Informationen zu einem Namen werden ausgegeben und eine Eingabe
angefordert. Falls nur die Enter-Taste gedrückt wurde, das heißt also, wenn die Eingabe der leere String
ist, wird der alte Wert beibehalten.

Beispiel 17.6.5 Adresse ändern


def aendern():
global namen
print(’Diese Namen sind in der Liste! ’)
anzeigen(1)
aendNr = input(’Bitte Nummer des zu ändernden Namens eingeben: ’)
#### Vorname
print(’alter Vorname: ’, namen[aendNr][’vorname’])
neuerVorname = input(’ neuer Vorname(Enter für beibehalten): ’)
if neuerVorname != u’’:
namen[aendNr][’vorname’] = neuerVorname
#### Nachname
print(’alter Nachname: ’, namen[aendNr][’nachname’])
neuerNachname = input(’ neuer Nachname(Enter für beibehalten): ’)
if neuerNachname != u’’:
namen[aendNr][’nachname’] = neuerNachname
#### Alter
print(’altes Alter: ’, namen[aendNr][’alter’])
neuesAlter = input(’ neues Alter(Enter für beibehalten): ’)
if neuesAlter != u’’:
namen[aendNr][’alter’] = neuesAlter

297
KAPITEL 17. UND NOCH EIN BEISPIEL: EIN . . . 17.7. DER SECHSTE ENTWURF: . . .

Das kann natürlich auch etwas weniger umfangreich geschrieben werden, indem man im Hauptpro-
gramm die Struktur eines Datensatzes festlegt, diese Struktur in der Funktion aendern global macht
und dann über die Felder dieser Struktur schleift:

Beispiel 17.6.6 Adress-Liste anzeigen (über eine Schleife)


strukturAdr = [’vorname’, ’nachname’, ’alter’]

def aendern():
global strukturAdr
print(’Diese Namen sind in der Liste! ’)
anzeigen(1)
aendNr = input(’Bitte Nummer des zu ändernden Namens eingeben: ’)
for attribut in strukturAdr:
print([Link](), ’ (alt): ’, namen[aendNr][attribut])
aenderung = input(’ neu (Enter für beibehalten): ’)
if aenderung != u’’:
namen[aendNr][attribut] = aenderung

17.7. Der sechste Entwurf: persistente Speicherung


Die Daten sollen jetzt auch erhalten bleiben, wenn das Programm beendet wird und danach neu auf-
gerufen wird, sie sollen also in einer Datei gespeichert werden. Zu diesem Zweck wird das Modul
pickle benutzt, der eine Hülle (ein Wrapper) für beliebige Datenstrukturen darstellt. Beim Aufruf des
Programms wird überprüft, ob schon eine Adress-Datei existiert. Wenn ja, wird diese gelesen, ansons-
ten wird mit einer vorgegebenen Liste mit zwei Einträgen gearbeitet. Diese Entscheidung wird in der
ursprünglichen Funktion initialisiere getroffen, wobei über eine Ausnahme eine Nicht-Existenz
der Datei abgefangen wird. Falls die Datei existiert, wird in einer neuen Funktion nDatLesendie Datei
gelesen.

Beispiel 17.7.1 gespeicherte Adress-Liste lesen


def nDatLesen(namenDatei):
global namen
while namenDatei:
try:
namen = [Link](namenDatei)
except EOFError:
break
[Link]()

def initialisiere():
global namen
nDat = ’[Link]’
try:
namenDatei = open(nDat, ’r’)
nDatLesen(namenDatei)
except IOError:
martin = {’vorname’:’Martin’, ’nachname’:’Schimmels’,’alter’:54}
ekki = {’vorname’:’Eckard’, ’nachname’:’Krauss’,’alter’:41}
namen = [martin,ekki]

1 capitalize schreibt den ersten Buchstaben eines Wortes groß

298
KAPITEL 17. UND NOCH EIN BEISPIEL: EIN . . . 17.8. JETZT WIRD ES OBJEKTORIENTIERT

Beim Beenden des Programms wird jetzt die Liste in eine Datei geschrieben. Sicherheitshalber wird
überprüft, ob sich die Datei zum Schreiben öffnen lässt und im Falle des Mißlingens wird das über eine
Ausnahme abgefangen. Ansonsten ist das Schreiben einer beliebigen Struktur einfach: pickle nimmt
die Struktur und schreibt sie per dump, so wie sie ist, in eine Datei.

Beispiel 17.7.2 Adress-Liste schreiben


def beenden():
print(’Jetzt wird das Programm beendet’)
global namen
nDat = ’[Link]’
try:
namenDatei = open(nDat, ’w’)
except IOError:
print(’na so was’)
[Link](namen, namenDatei)
[Link]()

17.8. Jetzt wird es objektorientiert


17.8.1. Der Klassenentwurf
Wer bis hierher die verschiedenen Stadien des Programms verfolgt hat und weiter oben die Beispiele ob-
jektorientierter Programmierung studiert hat, wird an den bisherigen Entwürfen viele objektorientierte
Ansätze feststellen. Dann soll das Programm jetzt also wirklich objektorientiert werden. Dazu wird zu-
erst einmal eine Klasse Adresse mit ihren Attributen und Methoden entworfen und getestet. In einem
weiteren Schritt wird eine Klasse Adressbuch hinzugefügt.
Die Klasse Adresse hat die Attribute Vorname, Nachname und Alter, außerdem Methoden, um jedes
der Attribute zu ändern und ein Menu, das in die verschiedenen Änderungen verzweigt. Außerdem
können Datensätze angelegt und angezeigt werden.

Abbildung 17.1. Klassendiagramm Adresse

299
KAPITEL 17. UND NOCH EIN BEISPIEL: EIN . . . 17.8. JETZT WIRD ES OBJEKTORIENTIERT

Der Klassenentwurf ist danach selbsterklärend:

Beispiel 17.8.1 Klasse Adresse


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4

5 class Adresse():
6 def __init__(self, vorname=’’, nachname=’’, alter=0):
7 if vorname == ’’ and nachname == ’’ and alter == 0:
8 [Link]()
9 else:
10 [Link] = vorname
11 [Link] = nachname
12 [Link] = alter
13

14 def anzeigen(self):
15 print([Link], ’ ’, [Link], ’ ’, [Link])
16

17 def vornameAendern(self):
18 aString = ’alter Vorname: ’+[Link]+ ’ neuer Vorname: ’
19 [Link] = input(aString)
20

21 def nachnameAendern(self):
22 aString = ’alter Nachname: ’+[Link]+’ neuer Nachname: ’
23 [Link] = input(aString)
24

25 def alterAendern(self):
26 aString = ’altes Alter: ’+str([Link])+’ neues Alter: ’
27 [Link] = input(aString)
28

29 def aendern(self):
30 auswahl = input( ’Was soll geändert werden? (V)orname,
31 (N)achname, (A)lter ’ )
32 menuAendern = {’V’: [Link], ’N’: [Link],
33 ’A’:[Link]}
34 menuAendern[auswahl]()
35

36 def anlegen(self):
37 print(’neuer Name wird aufgenommen!’)
38 [Link] = input(’Vorname: ’)
39 [Link] = input(’Nachname: ’)
40 [Link] = input(’Alter: ’)
41

300
KAPITEL 17. UND NOCH EIN BEISPIEL: EIN . . . 17.8. JETZT WIRD ES OBJEKTORIENTIERT

Dazu benötigt man wieder ein Programm, das diese Klasse aufruft:

Beispiel 17.8.2 Aufruf der Klasse Adresse


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4

5 from clAdr import Adresse


6

7 ich = Adresse(’Martin’, ’Schimmels’, 54)


8 [Link]()
9 [Link]()
10 [Link]()
11

12 du = Adresse()
13 [Link]()
14

17.8.2. Zur Klasse Adresse kommt die Klasse Adressbuch hinzu


Im nächsten Schritt wird eine weitere Klasse erstellt, die Elemente der Klasse Adresse enthält: das
Adressbuch. Die Realisierung dieses Adressbuches sieht der Anwendung im fünften Entwurf sehr ähnlich.

301
KAPITEL 17. UND NOCH EIN BEISPIEL: EIN . . . 17.8. JETZT WIRD ES OBJEKTORIENTIERT

Beispiel 17.8.3 Adressbuch-Klasse


1

2 class AdressBuch():
3 def __init__(self):
4 [Link] = True
5 [Link] = []
6 while [Link]:
7 [Link]()
8

9 def menu(self):
10 auswahl = input(’\n#### AUSWAHL ####\n
11 alle Namen anzeigen: Z\n
12 Namen einfügen: N\n
13 Namen löschen: L\n
14 Namen ändern: A\n
15 Ende: E\n
16 #### ....... ####\b\b\b\b\b\b\b\b\b\b\b\b’)
17 menuListe = {’N’:[Link], ’L’:[Link],
18 ’A’:[Link], ’E’:[Link], ’Z’:[Link]}
19 menuListe[auswahl]()
20

21 def einfuegen(self):
22 neuerName = Adresse()
23 [Link](neuerName)
24

25 def loeschen(self):
26 print(’Folgende Namen sind in der Liste: ’)
27 [Link]()
28 loeschNr = input(’Nummer des zu löschenden Datensatzes angeben: ’)
29 del [Link][loeschNr]
30 print("So sieht’s jetzt aus: ")
31 [Link]()
32

33 def aendern(self):
34 print(’Folgende Namen sind in der Liste: ’)
35 [Link]()
36 aendNr = input(’Nummer des zu ändernden Datensatzes angeben: ’)
37 [Link][aendNr].aendern()
38

39 def beenden(self):
40 [Link] = False
41

42 def anzeigen(self):
43 lfdNr = 0
44 print(’\n##### Namensliste #####’)
45 for einName in [Link]:
46 print(’##\t’,lfdNr,’\t’)
47 [Link]()
48 lfdNr += 1
49 print(’##### ----------- #####’)
50

302
KAPITEL 17. UND NOCH EIN BEISPIEL: EIN . . . 17.8. JETZT WIRD ES OBJEKTORIENTIERT

Das Adressbuch selber wird durch das folgende aufrufende Programm realisiert:

Beispiel 17.8.4 Aufruf des Adressbuchs


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4

5 from clAdr import AdressBuch


6

7 meineAdressen = AdressBuch()
8

Das soll wirklich alles sein? Wer es nicht glaubt, soll es halt einfach ausprobieren!!

303
KAPITEL 17. UND NOCH EIN BEISPIEL: EIN . . . 17.8. JETZT WIRD ES OBJEKTORIENTIERT

17.8.3. Dauerhafte Speicherung

Das wird wieder fast wortwörtlich aus dem fünften Entwurf übernommen:

Beispiel 17.8.5 Adressbuch-Klasse mit Speicherung


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4 import pickle
5 class Adresse():
6 def __init__(self, vorname=’’, nachname=’’, alter=0):
7 if vorname == ’’ and nachname == ’’ and alter == 0:
8 [Link]()
9 else:
10 [Link] = vorname
11 [Link] = nachname
12 [Link] = alter
13

14 def anzeigen(self):
15 print([Link], ’ ’, [Link], ’ ’, [Link])
16

17 def vornameAendern(self):
18 aString = ’alter Vorname: ’+[Link]+ ’ neuer Vorname: ’
19 [Link] = input(aString)
20

21 def nachnameAendern(self):
22 aString = ’alter Nachname: ’+[Link]+’ neuer Nachname: ’
23 [Link] = input(aString)
24

25 def alterAendern(self):
26 aString = ’altes Alter: ’+str([Link])+’ neues Alter: ’
27 [Link] = input(aString)
28

29 def aendern(self):
30 auswahl = input(’Was soll geändert werden?
31 (V)orname, (N)achname, (A)lter ’ )
32 menuAendern = {’V’: [Link],
33 ’N’: [Link],
34 ’A’: [Link]}
35 menuAendern[auswahl]()
36

37 def anlegen(self):
38 print(’neuer Name wird aufgenommen!’)
39 [Link] = input(’Vorname: ’)
40 [Link] = input(’Nachname: ’)
41 [Link] = input(’Alter: ’)
42

304
KAPITEL 17. UND NOCH EIN BEISPIEL: EIN . . . 17.8. JETZT WIRD ES OBJEKTORIENTIERT

Beispiel 17.8.6 Adressbuch-Klasse mit Speicherung (Forts.)


1

2 class AdressBuch():
3

4 def __init__(self):
5 [Link] = True
6

7 [Link] = ’[Link]’
8 try:
9 namenDatei = open([Link], ’r’)
10 [Link](namenDatei)
11 except IOError:
12 [Link] = []
13 while [Link]:
14 [Link]()
15

16 def nDatLesen(self, namenDatei):


17 while namenDatei:
18 try:
19 [Link] = [Link](namenDatei)
20 except EOFError:
21 break
22 [Link]()
23

24 def menu(self):
25 auswahl = input(’\n#### AUSWAHL ####\n
26 alle Namen anzeigen: Z\n
27 Namen einfügen: N\n
28 Namen löschen: L\n
29 Namen ändern: A\n
30 Ende: E\n
31 #### ....... ####\b\b\b\b\b\b\b\b\b\b\b\b’)
32 menuListe = {’N’:[Link],
33 ’L’:[Link],
34 ’A’:[Link],
35 ’E’:[Link],
36 ’Z’:[Link]}
37 menuListe[auswahl]()
38

39 def einfuegen(self):
40 neuerName = Adresse()
41 [Link](neuerName)
42

43 def loeschen(self):
44 print(’Folgende Namen sind in der Liste: ’)
45 [Link]()
46 loeschNr = input(’Nummer des zu löschenden Datensatzes angeben: ’)
47 del [Link][loeschNr]
48 print("So sieht’s jetzt aus: ")
49 [Link]()
50

305
KAPITEL 17. UND NOCH EIN BEISPIEL: EIN . . . 17.8. JETZT WIRD ES OBJEKTORIENTIERT

Beispiel 17.8.7 Adressbuch-Klasse mit Speicherung (2. Forts.)


1

2 def aendern(self):
3 print(’Folgende Namen sind in der Liste: ’)
4 [Link]()
5 aendNr = input(’Nummer des zu ändernden Datensatzes angeben: ’)
6 [Link][aendNr].aendern()
7

8 def beenden(self):
9 [Link] = False
10 try:
11 namenDatei = open([Link], ’w’)
12 except IOError:
13 print(’na so was’)
14 [Link]([Link], namenDatei)
15 [Link]()
16

17 def anzeigen(self):
18 lfdNr = 0
19 print(’\n##### Namensliste #####’)
20 for einName in [Link]:
21 print(’##\t’,lfdNr,’\t’)
22 [Link]()
23 lfdNr += 1
24 print(’##### ----------- #####’)
25

306
18. Immer noch das Adressbuch — nur
schöner
18.1. Das Adressbuch kommt in die Datenbank
Die permanente Speicherung der Daten in einer Datei mit Hilfe von pickle ist nicht der Weisheit letz-
ter Schluß. Das vorhergehende Beispiel wird daher so erweitert, dass die Adress-Daten jetzt in einer
Tabelle einer relationen Datenbank gespeichert werden. Der Open-Source-Standard für solch kleine An-
wendungen ist das DBMS“ mysql.

An der Klasse Adresse muss zuallererst eine Kleinigkeit geändert werden. Da die Daten in der Da-
tenbank einen Primärschlüssel haben sollten, wird in der Tabellenstruktur für die Adressen eine laufen-
de Nummer eingefügt. Diese laufende Nummer muss auch in der Klasse Adresse bearbeitet werden.
Zusätzlich wird, weil die beiden Klassen Adresse und Adressbuch in der selben Datei stehen, bereits
hier die MySQL-Bibliothek eingebunden.

307
KAPITEL 18. IMMER NOCH DAS . . . 18.1. DAS ADRESSBUCH KOMMT IN DIE . . .

Die Klasse sieht dann so aus:

Beispiel 18.1.1 Klasse Adresse mit laufender Nummer


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4 import MySQLdb
5 class Adresse():
6 def __init__(self, lfdnr = 0, vorname=’’, nachname=’’,
7 strasse = ’’, plz = ’’, ort = ’’):
8 if vorname == ’’ and nachname == ’’:
9 [Link]()
10 else:
11 [Link] = lfdnr
12 [Link] = vorname
13 [Link] = nachname
14 [Link] = strasse
15 [Link] = plz
16 [Link] = ort
17

18 def anzeigen(self):
19 print(’\n######## Nr. des Datensatzes: ’, [Link],
20 ’\n## ’,[Link], ’ ’, [Link],
21 ’\n## ’, [Link], ’\n## ’,
22 [Link], ’ ’, [Link], ’\n########’)
23

24 def vornameAendern(self):
25 print(’häää?? Vornamen ändern??’)
26 aString = ’alter Vorname: ’+[Link]+ ’ neuer Vorname: ’
27 [Link] = input(aString)
28

29 def nachnameAendern(self):
30 aString = ’alter Nachname: ’+[Link]+’ neuer Nachname: ’
31 [Link] = input(aString)
32

33 def strAendern(self):
34 aString = ’alte Strasse: ’+str([Link])+’ neue Strasse: ’
35 [Link] = input(aString)
36

37 def plzAendern(self):
38 aString = ’alte PLZ: ’+str([Link])+’ neue PLZ: ’
39 [Link] = input(aString)
40

41 def ortAendern(self):
42 aString = ’alter Ort: ’+str([Link])+’ neuer Ort: ’
43 [Link] = input(aString)
44

45 def aendern(self):
46 auswahl = input(’Was soll geändert werden?
47 (V)orname, (N)achname, (A)lter,
48 (S)trasse, (P)LZ, (O)rt ’ )
49 menuAendern = {’V’: [Link], ’N’: [Link],
50 ’S’: [Link], ’P’: [Link],
51 ’O’: [Link]}
52 menuAendern[auswahl]()
53

308
KAPITEL 18. IMMER NOCH DAS . . . 18.1. DAS ADRESSBUCH KOMMT IN DIE . . .

Beispiel 18.1.2 Klasse Adresse mit laufender Nummer (Forts.)


1

2 def anlegen(self):
3 print(’neuer Name wird aufgenommen!’)
4 [Link] = input(’Vorname: ’)
5 [Link] = input(’Nachname: ’)
6 [Link] = input(’Strasse: ’)
7 [Link] = input(’PLZ: ’)
8 [Link] = input(’Ort: ’)
9

Die Klasse AdressBuch ändert sich mehr. Im Konstruktor der Klasse wird weiterhin zuerst eine
leere Liste adrListe erzeugt, in der für den Fall, dass alle Datensätze gelesen werden sollen, diese
zwischengespeichert werden. Danach wird die Verbindung zum DBMS hergestellt und versucht, die
Datenbank test adr zu öffnen. Falls das nicht gelingt, wird diese Datenbank erstellt. In einem zweiten
Schritt wird dann versucht, die Tabelle namen zu lesen, im Falle des Mißlingens wird eine solche Tabelle
erstellt. Danach wird die Liste gefüllt (eventuell bleibt sie leer, falls in der Tabelle der Datenbank noch
keine Daten vorhanden sind). Im letzten Schritt des Konstruktors wird die Endlos-Schleife des Menus
aufgerufen. Außerdem wird hier am Ende jeder Transaktion die Liste geleert und neu aus der Datenbank
eingelesen.

Beispiel 18.1.3 Konstruktor der Klasse AdressBuch


1

2 class AdressBuch():
3

4 def __init__(self):
5 [Link] = True
6 [Link] = []
7 try:
8 [Link] = [Link](host=’localhost’, db=’test_adr’)
9 [Link] = [Link]()
10 except:
11 print(’Datenbank "test_ms" existiert noch nicht und wird angelegt’)
12 [Link] = [Link](host=’localhost’)
13 [Link] = [Link]()
14 [Link](’CREATE DATABASE test_adr’)
15 [Link](’use test_adr’)
16 try:
17 [Link](’SELECT COUNT(*) FROM namen’)
18 except:
19 [Link](’CREATE TABLE namen (
20 lfdnr INT NOT NULL AUTO_INCREMENT,
21 vorname VARCHAR(30),
22 nachname VARCHAR(30),
23 str VARCHAR(30),
24 plz CHAR(5),
25 ort VARCHAR(30),
26 PRIMARY KEY(lfdnr))’)
27 [Link]()
28 while [Link]:
29 [Link]()
30 [Link] = []
31 [Link]()
32

Die einzelnen Methoden der Klasse AdressBuch sehen denen aus dem vorigen Beispiel sehr ähnlich.

309
KAPITEL 18. IMMER NOCH DAS . . . 18.1. DAS ADRESSBUCH KOMMT IN DIE . . .

Es wird (fast) immer ein Query-String aufgebaut, der dann mit dem Befehl execute ausgeführt wird.
Bei der Methode aendern muss allerdings eine andere Logik verwendet werden: vor dem Ändern
wird der zu ändernde Datensatz in ein Objekt der Klasse Adresse eingelesen, dieses Objekt wird für
die Änderung an die Klasse Adresse weitergegeben, und das veränderte Objekt, das aus der Klasse
zurückkommt, wird in die Datenbank geschrieben. Da man nicht weiß, welches Attribut des Objekts
geändert wurde, wird einfach jedes Attribut geändert.

Beispiel 18.1.4 Methoden der Klasse AdressBuch


1

2 def nDatLesen(self):
3 [Link](’SELECT * FROM namen ORDER BY nachname, vorname’)
4 for (lfdnr, vn, nn, strasse, plz, ort) in [Link]():
5 geleseneAdr = Adresse(lfdnr, vn, nn, strasse, plz, ort)
6 [Link](geleseneAdr)
7

8 def menu(self):
9 auswahl = input(’\n#### AUSWAHL ####\n
10 alle Namen anzeigen: Z\n
11 Namen einfügen: N\n
12 Namen löschen: L\n
13 Namen ändern: A\n
14 Ende: E\n
15 #### ....... ####\b\b\b\b\b\b\b\b\b\b\b\b’)
16 menuListe = {’N’:[Link], ’L’:[Link],
17 ’A’:[Link], ’E’:[Link], ’Z’:[Link]}
18 menuListe[auswahl]()
19

20 def einfuegen(self):
21 neuerName = Adresse()
22 [Link](’INSERT INTO namen
23 (vorname, nachname, str, plz, ort)
24 VALUES(%s, %s, %s, %s, %s)’,
25 ([Link], [Link],
26 [Link], [Link],
27 [Link]))
28

29 def loeschen(self):
30 print(’Folgende Namen sind in der Liste: ’)
31 [Link]()
32 loeschNr = input(’Nummer des zu löschenden Datensatzes angeben: ’)
33 loeschBefehl = ’DELETE FROM namen WHERE lfdnr = ’+str(loeschNr)
34 [Link](loeschBefehl)
35

310
KAPITEL 18. IMMER NOCH DAS . . . 18.1. DAS ADRESSBUCH KOMMT IN DIE . . .

Beispiel 18.1.5 Methoden der Klasse AdressBuch (Forts.)


1

2 def aendern(self):
3 print(’Folgende Namen sind in der Liste: ’)
4 [Link]()
5 aendNr = input(’Nummer des zu ändernden Datensatzes angeben: ’)
6 vorleseBefehl = ’SELECT * FROM namen WHERE lfdnr = ’+str(aendNr)
7 [Link](vorleseBefehl)
8 for (lfdnr, vn, nn, strasse, plz, ort) in [Link]():
9 geleseneAdr = Adresse(lfdnr, vn, nn, strasse, plz, ort)
10

11 [Link]()
12 updBefehl = "UPDATE namen SET vorname = ’"+[Link]+"’,
13 nachname = ’"+[Link]+"’,
14 str = ’"+[Link]+"’,
15 plz = ’"+[Link]+"’,
16 ort =’"+[Link]+"’
17 WHERE lfdnr = "+str(aendNr)
18 [Link](updBefehl)
19

20 def beenden(self):
21 [Link] = False
22

23 def anzeigen(self):
24 lfdNr = 0
25 print(’\n##### Namensliste #####’)
26

27 for einName in [Link]:


28 [Link]()
29 print(’##### ----------- #####’)
30

311
19. Eine Ampel
19.1. Der Entwurf
The traffic lights they turn blue tomorrow
(Jimi Hendrix1 )
In meinem nächsten Beispiel soll eine funktionierende Ampel programmiert werden. Dabei soll die
in Deutschland übliche Reihenfolge der Ampelfarben angezeigt werden, d.h. rot -> rot-gelb -> grün ->
gelb -> rot. Starten wir also mit einem Modell in UML.
Betrachten wir zuerst die Attribute der Ampel. Eine Ampel hat also verschiedene Zustände: rot,
rot-gelb, grün, gelb, also ein Attribut zustand. Diese Zustände werden in zwei Dictionaries abge-
legt. Im ersten Dictionary wird den Zahlen 0 bis 3 jeweils einer der Zustände zugeordnet, und zwar
in der Reihenfolge, die oben angegeben wurde. Ferner wird ein zweites Dictionary angelegt, in dem
den Zuständen (in der beschreibenden Form rot, rot-gelb usw.) ein Tripel von Farben zugeordnet wird.
Die Farben werden der Übersichtlichkeit halber aus einem weiteren Dictionary genommen, in dem dem
Farbnamen der übliche numerische Wert in der RGB-Schreibweise zugeordnet wird. Das letzte Attribut
der Ampel ist der aktuelle Zustand.
Die Klasse Ampel hat nur zwei Methoden. Zum einen die Methode umschalten, die Modulo 3 durch
die numerischen Zustände wechselt, zum zweiten die Methode anzeigen, die genau das macht. Das
UML-Diagramm sieht also so aus:

Abbildung 19.1. Klassendiagramm Ampel

1 The wind cries Mary auf: Are you experienced?

313
KAPITEL 19. EINE AMPEL 19.2. DIE REALISIERUNG

19.2. Die Realisierung


Der Quellcode für diese Klasse sieht so aus:

Beispiel 19.2.1 Klassenentwurf der Ampel


1

2 #!/usr/bin/python
3

4 class Ampel():
5 def __init__(self):
6 [Link] = {0:’rot’, 1:’rot-gelb’, 2:’gruen’, 3:’gelb’}
7 [Link] = {’rot’:’#FF0000’, ’gelb’:’#FFFF00’,
8 ’gruen’:’#00FF00’, ’schwarz’:’#000000’}
9 [Link] = {
10 ’rot’:[[Link][’rot’], [Link][’schwarz’], [Link][’schwarz’]],
11 ’rot-gelb’:[[Link][’rot’], [Link][’gelb’], [Link][’schwarz’]],
12 ’gruen’:[[Link][’schwarz’], [Link][’schwarz’], [Link][’gruen’]],
13 ’gelb’:[[Link][’schwarz’], [Link][’gelb’], [Link][’schwarz’]]}
14 [Link] = 0
15

16 def umschalten(self):
17 # das eigentliche Umschalten. BEACHTE: hier wird mod(3) gerechnet
18 [Link] = ([Link] + 1)%len([Link])
19

20 def anzeigen(self):
21 print(’\n=========\nDie Ampel ist %s’ % [Link][[Link]])
22 print(’Farben: ’, [Link][[Link][[Link]]])
23

Das aufrufende Programm ist wieder sehr einfach. Hier wird eine Endlosschleife benutzt, um die
Ampel umzuschalten.

Beispiel 19.2.2 Aufruf einer Ampel


#!/usr/bin/python

from clAmpel import Ampel

eingabe = ’12345’
meineAmpel = Ampel()
while eingabe != ’x’:
eingabe = input(’Umschalten!!! Ende mit x’)
[Link]()
[Link]()

19.3. Persistente Speicherung


Die Ampel funktioniert. Sie schaltet um und zeigt den aktuellen Zustand an. Aber leider merkt sich
die Ampel nicht, welchen Zustand sie gerade hat. Bei jedem Neustart des Programms ist der Zustand
der selbe, nämlich der, der im Konstruktor angegeben wird. Um das zu verbessern, wird der aktuelle
Zustand in eine Datei geschrieben und bei jedem Neustart des Programms aus dieser Datei gelesen.

314
KAPITEL 19. EINE AMPEL 19.4. EINE KREUZUNG HAT 4 AMPELN! . . .

Beispiel 19.3.1 Klasse Ampel mit Speicherung des Zustands


1

2 #!/usr/bin/python
3

4 class Ampel():
5 def __init__(self, bezeichnung = ’Nord’):
6 [Link] = bezeichnung
7 [Link] = {0:’rot’, 1:’rot-gelb’, 2:’gruen’, 3:’gelb’}
8 [Link] = {’rot’:’#FF0000’, ’gelb’:’#FFFF00’,
9 ’gruen’:’#00FF00’, ’schwarz’:’#000000’}
10 [Link] = {
11 ’rot’:[[Link][’rot’], [Link][’schwarz’], [Link][’schwarz’]],
12 ’rot-gelb’:[[Link][’rot’], [Link][’gelb’], [Link][’schwarz’]],
13 ’gruen’:[[Link][’schwarz’], [Link][’schwarz’], [Link][’gruen’]],
14 ’gelb’:[[Link][’schwarz’], [Link][’gelb’], [Link][’schwarz’]]}
15 [Link] = [’oben’, ’mitte’, ’unten’]
16

17 def umschalten(self):
18 # aus Datei den aktuellen Zustand lesen
19 try:
20 [Link](’r’)
21 [Link] = int([Link]())
22 [Link]()
23 except:
24 [Link] = 0
25

26 # das eigentliche Umschalten. BEACHTE: hier wird mod(3) gerechnet


27 [Link] = ([Link] + 1)%len([Link])
28

29 # in Datei den aktuellen Zustand schreiben


30 [Link](’w’)
31 [Link]()
32 [Link]()
33

34 def anzeigen(self):
35 print(’\n=========\nDie Ampel ist %s’ % [Link][[Link]])
36 print(’Farben: ’, [Link][[Link][[Link]]])
37

38 ### Datei-Operationen
39 def dateiOeffnen(self, modus):
40 dateiName = [Link]+’.dat’
41 [Link] = open(dateiName,modus)
42

43 def dateiSchreiben(self):
44 [Link](str([Link]))
45

46 def dateiSchliessen(self):
47 [Link]()
48

Das aufrufende Programm muss nicht verändert werden!

19.4. Eine Kreuzung hat 4 Ampeln! Der Entwurf.


Wenn eine Ampel funktioniert, kann man mal vier Ampeln an einer Kreuzung aufstellen. Der Einfach-
heit halber werden die 4 Straßen, die an der Kreuzung zusammentreffen, und damit die 4 Ampeln, die

315
KAPITEL 19. EINE AMPEL 19.4. EINE KREUZUNG HAT 4 AMPELN! . . .

an den jeweiligen Straßen stehen, mit den 4 Himmelsrichtungen benannt.

Abbildung 19.2. Eine Kreuzung

Aber natürlich sind nicht immer alle Lichter aller 4 Ampeln an. Die Regeln für die Ampeln sind aus
den folgenden 4 Zeichnungen zu entnehmen. Zuerst darf man von Nord nach Süd (und umgekehrt)
fahren.

Abbildung 19.3. Kreuzung: Freie Fahrt von Nord nach Süd

Dann wird umgeschaltet in die Gelb-Phase.

Abbildung 19.4. Kreuzung: Alle warten

316
KAPITEL 19. EINE AMPEL 19.5. DIE REALISIERUNG

Dann darf man von West nach Ost (und umgekehrt) fahren.

Abbildung 19.5. Kreuzung: Freie Fahrt von West nach Ost

Dann wird umgeschaltet in die andere Gelb-Phase.

Abbildung 19.6. Kreuzung: Wieder warten alle

In einer Tabelle sieht das so aus:

Tabelle 19.1. Die Ampel-Phasen


Beschreibung Nord Ost Süd West
freie Fahrt N - S grün rot grün rot
Umschalten gelb rot - gelb gelb rot - gelb
freie Fahrt W - O rot grün rot grün
Umschalten rot - gelb gelb rot - gelb gelb

19.5. Die Realisierung


Da die Klasse Ampel so gut funktioniert, ist die Klasse Kreuzung ganz kurz. Und viel erklärt werden
muss hier auch nicht. Hier also der Code.

317
KAPITEL 19. EINE AMPEL 19.5. DIE REALISIERUNG

Beispiel 19.5.1 Klassenentwurf der Kreuzung


1

2 #!/usr/bin/python
3

4 from clAmpel import Ampel


5

6 class Kreuzung():
7 def __init__(self):
8 [Link] = [’Nord’, ’West’, ’Sued’, ’Ost’]
9

10 [Link] = Ampel(’Nord’)
11 [Link] = Ampel(’West’)
12 [Link] = Ampel(’Sued’)
13 [Link] = Ampel(’Ost’)
14 [Link] = [[Link], [Link], [Link], [Link]]
15

16 def umschalten(self):
17 for eineAmpel in [Link]:
18 [Link]()
19

Weiter hinten bei [Ampel im WWW], wenn Python als Sprache für dynamische Web-Seiten behandelt
wird, gibt es die Realisierung der Kreuzung als HTML-Seite mit einem Knopf zum Umschalten.

318
Teil X.

Grafik! Internet!

319
20. CGI-Programme
20.1. HTML und Kollegen
Hier soll keine Einführung in HTML gegeben werden. Eine gute Empfehlung im WWW für die, die
HTML lernen wollen, ist immer noch Self-HTML. 1
Auf den folgenden Seiten wird nur ein kurzer Abriss von HTML gegeben. Für die Programmierung
von dynamischen Seiten mit Python ist das aber ausreichend.

20.2. Allgemeines zu HTML


20.2.1. Was ist HTML?
HTML ist die Abkürzung für Hypertext Markup Language“.

HTML gehört zu den Auszeichnungssprachen. Bei Dokumenten, die in einer Auszeichnungssprache
geschrieben werden, wird nur die Struktur des Textes beschrieben, nicht das tatsächliche Aussehen.
Die Darstellung eines HTML-Dokuments ist die Aufgabe eines Browsers. Da es verschiedene Browser
gibt, kann es vorkommen, dass Dokumente auch verschieden aussehen. Das kann sich auf die Schrift
auswirken: manche Schriften existieren im einen System, im anderen nicht. Unangenehm wird es, wenn
der Hersteller eines Browsers meint, von den festgelegten Standards abweichen zu müssen. (Meistens
stecken da wirtschaftliche Interessen dahinter.)
Es gibt inzwischen nicht nur viele verschiedene Browser, sondern auch verschiedene HTML-Editoren.
Das sind Editoren, mit denen man auf Knopfdruck“ HTML-Code schreiben kann. Warum soll man

dann diese Sprache noch lernen? Dafür gibt es immer noch ein paar Gründe:

• Wenn man keine Vorstellung von der Struktur einer Seite hat, dann bewirkt die Benutzung eines
HTML-Editors meistens, dass eine damit erstellte Seite nicht sehr elegant aussieht.
• Die meisten HTML-Editoren hinken den Browsern hinterher! Nicht alles, was angezeigt werden
kann, beherrscht auch der Editor.
• Die Einbindung von dynamischen Web-Seiten erfordert Programmierung in einer Skript-Sprache;
spätestens hier muß man den HTML-Code zu Fuß“ eingeben.

• Auch die Erstellung einer HTML-Seite, die mit Werten aus einer Datenbank gefüllt wird, benötigt
HTML-Befehle.

20.2.2. Grundlagen
HTML-Code besteht aus dem Inhalt und den Auszeichnungen. Diese Auszeichnungen werden als tag“ be-

zeichnet. Ein HTML-Befehl umschließt einen Bereich und wird von einem Start-tag“ und einem Ende-
” ”
tag“ eingerahmt. Ein solcher Bereich wird auch Tag-Container“ genannt. HTML-tags können geschach-

telt werden. Start-tags sind in größer- und kleiner-Zeichen eingeschlossen. Ende-tags unterscheiden sich
von Start-tags dadurch, dass das erste Zeichen nach dem kleiner-Zeichen ein Schrägstrich ist. Beispiele
siehe nächstes Kapitel.
Einige tags können Attribute haben, die das Verhalten des tags ändern. Die wichtigsten Attribute
werden weiter unten im Kontext genannt.

20.2.3. Obligatorische HTML-Befehle


Jedes HTML-Dokument benötigt wenigstens folgende HTML-tags:

1. <HTML> und </HTML>


1 siehe hierzu: <[Link]

321
KAPITEL 20. CGI-PROGRAMME 20.2. ALLGEMEINES ZU HTML

2. <HEAD> und </HEAD>


3. <TITLE> und </TITLE>
4. <BODY> und </BODY>

Damit sieht ein einfaches HTML-Dokument (ohne jeglichen Inhalt) so aus:

Beispiel 20.2.1
<HTML>
<HEAD>
<TITLE>
</TITLE>
</HEAD>
<BODY>
</BODY>
</HTML>

20.2.4. Struktur eines HTML-Dokuments


Es gibt 6 verschiedene Hierarchiestufen für Überschriften. Die oberste Stufe für Überschriften wird
durch das tag-Paar <H1> </H1>, die unterste entsprechend durch das tag-Paar <H6> </H6> einge-
schlossen.

20.2.5. Absätze und Leerzeichen


Bei der Verarbeitung von HTML-Code werden Leerzeichen und Leerzeilen ignoriert; Aus mehreren
Leerzeichen wird ein einzelnes gemacht. Deswegen sind Absätze und Leerzeichen besonders zu be-
arbeiten. Ein Absatz wird durch <P> begonnen und durch </P> beendet. Absätze dürfen nicht ge-
schachtelt werden.
Sollen Leerzeichen nicht zusammengeschoben werden, kann man das dadurch verhindern, dass man
einen Block dadurch schützt, dass er in den HTML-Container <PRE> . . . </PRE> (für to preserve:

erhalten“) gesteckt wird.
Soll nur eine neue Zeile begonnen werden, ohne dass ein Absatz-Abstand eingefügt werden soll, so
wird das durch den HTML-Befehl <BR> erledigt. Vorsicht: zu diesem tag“ gibt es kein Ende-tag.

20.2.6. Hervorhebungen
Besondere Textstellen können auf verschiedene Art hervorgehoben werden:

• <EM>hebt Text einfach hervor. Dies geschieht durch kursive Schrift.


• <STRONG>hebt Text verstärkt hervor. Dies geschieht durch fette Schrift.
• <CODE> [code] ist für Programmcode gedacht. Dieser Text wird in Schreibmaschinenschrift wie-
dergegeben. [/code]
• <SAMP> Dieser Text wird (auf einer HTML-Seite) in Schreibmaschinenschrift wiedergegeben.
• <KBD>ist für Tastatureingaben gedacht.
• <CITE> für Namen und Titel eines Werkes, das zitiert wird.
• <BLOCKQUOTE> wird benutzt, wenn ein längerer Text zitiert werden soll. Der von diesen tags
eingeschlossene Block wird eingerückt und als Block gesetzt. Das wirkt erst, wenn der Text über
mehrere Zeilen geht.

Wenn man einen ganzen Absatz besonders darstellen will, bietet sich der <DIV>-Container an. Da-
mit wird ein beliebiges Stück Text zusammengefasst, dem man mittels diverser Attribute ein eigenes
Aussehen verpassen kann.

322
KAPITEL 20. CGI-PROGRAMME 20.2. ALLGEMEINES ZU HTML

20.2.7. Listen
1. Geordnete Listen. Geordnete Listen sind durch Numerierung der Listeneinträge gekennzeichnet;
das kann verschiedene Formen haben: 1., 2., 3., usw. oder a), b), c) usw. Geordnete Listen werden
in den <OL>-Container gepackt. Listenelemente werden in den <LI>-Container gepackt.
2. Ungeordnete Listen. Ungeordnete Listen werden durch Rauten, Rechtecke, etc. gekennzeichnet.
Ungeordnete Listen werden in den <UL>-Container gepackt. Listenelemente werden in den <LI>-
Container gepackt.
3. Definitionslisten. Definitionslisten werden haben einen zu definierenden Begriff und eine defi-
nierende Beschreibung. Definitionslisten werden in den <DL>-Container gepackt. Der zu defi-
nierende Begriff wird in den <DT>-Container gepackt. Die definierende Beschreibung wird in
den <DD>-Container gepackt.

20.2.8. Links
Ein Link ist eine Verknüpfung oder Verbindung zu einem anderen Textstück. Zu einem Link gehören
immer zwei Auszeichnungen: erstens die Adresse, zu der gesprungen werden soll, und zweitens der
Sprungbefehl.

1. Interne Links. Ein interner Link ist eine Verbindung zu einem Textstück im selben Dokument. Er
wird häufig benutzt, um auf einer Seite an den Anfang oder an das Ende zu springen.
• Die Adresse, zu der gesprungen werden soll, wird im <A NAME=Adresse>-Container ver-
packt.
• Der Sprungbefehl wird im <A HREF=#Adresse>-Container verpackt.
2. Externe Links. Ein externer Link ist eine Verbindung zu einem HTML-Dokument auf dem eigenen
oder einem entferneten Rechner.
• Die Adresse, zu der gesprungen werden soll, kann hier jede URL sein.
• Der Sprungbefehl wird im <A HREF=Adresse>-Container verpackt. (Der Unterschied zum
internen Link ist das Fehlen des ”Lattenzaunes”.)

20.2.9. Formulare
Ein Formular wird durch das tag-Paar <FORM> und </FORM> eingeschlossen. Dabei benötigt das
<FORM>-tag noch Attribute, damit überhaupt mit dem Formular gearbeitet werden kann. Vollständig
sieht das Attribut so aus: <FORM action= prozedurName“ method= XXX“>. Dabei steht prozedurName
” ”
für den Namen des Programms, das das Formular auswerten soll; XXX steht für die Art, wie die Feld-
inhalte des Formulars an das Programm weitergegeben werden. Es gibt die beiden Methoden GET und
POST. Auf die Unterschiede der beiden Methoden soll hier nicht weiter eingegangen werden. Die Me-
thode POST ist aber aus Sicherheitsgründen vorzuziehen.
Ein Formular muss natürlich neben Text auch noch Eingabefelder enthalten. Eingabefelder werden
durch das tag <INPUT> realisiert. Es gibt verschiedene Typen von Eingabefelder, von denen hier zwei
vorgestellt werden.
Auf jeden Fall sollte ein Formular einen Knopf enthalten, der das Absenden des Formulars bewirkt.
Das ist ein spezielles Eingabe-Feld, das durch den tag <INPUT type= submit“ name= absenden“>
” ”
erzeugt wird, wobei der Text des Attributs name natürlich frei gewählt werden kann. Der type mit
dem Wert submit erledigt das Absenden.
Die wahrscheinlich häufigste Art, in ein Formular Werte einzugeben, ist über ein Textfeld, in das man
mit der Tastatur Text oder Zahlen schreibt. Das geschieht mit dem tag <INPUT type= text“ name= a“
” ”
value= “>. Das Attribut mit dem Wert type=“text” gibt an, dass hier ein Texteingabefeld geöffnet wird.

Damit das weiterverarbeitende Programm auch weiß, welche Variable mit dem in diesem Eingabefeld
eingegebenen Wert belegt werden soll, muss dem Textfeld noch der Name einer Variablen angegeben
werden; dies geschieht durch das Attribut text=“ xxx” . Sofern man dem Texteingabefeld einen Startwert
(den man dann überschreiben kann) mitgeben will, wird der dem Attribut value=“ ” zugewiesen.
Da einem Eingabefeld in einem Formular ein Vortext vorangestellt werden sollte, damit der Benutzer
weiß, was er überhaupt eingeben sollte, sehen Formulare erst einmal zerfleddert aus. Das kann man
glätten, indem man das Formular in eine Tabelle einbettet.

323
KAPITEL 20. CGI-PROGRAMME 20.3. CGI (DAS COMMON GATEWAY . . .

20.3. CGI (Das Common Gateway Interface)


Für den Datenaustausch zwischen einem Webserver und einem Client, also für das, was passiert, wenn
man eine Seite im Internet aufruft, gibt es verschiedene Ansätze. Python benutzt das normierte Verfah-
ren über CGI. Siehe dazu: <[Link]
Hier Bemerkungen über Web-Techniken zu machen ist nichts für die Ewigkeit, denn diese ändern sich
wahrscheinlich noch schneller als die meisten anderen Bereiche der Informatik.
Trotzdem soll hier ein kurz dargestellt werden, wie Internet-Seiten mit Hilfe des CGI erstellt und dar-
gestellt werden. CGI-Skripte, also Programme, die meistens in einer der p-Sprachen (perl, python) ge-
schrieben werden, sind serverseitige Skripte. Das heißt, dass diese Skripte auf einem Web-Server laufen
und das CG-Interface benutzen, um die durch das Programm produzierten Daten mittels eines Browsers
auf dem Bildschirm des Benutzers darstellen. CGI selber ist ein Anwendungsprotokoll, das Eingabeda-
ten und Anwendungsergebnisse vom Client zum Server und zurück transportiert.
Die einzelnen Schritte eines solchen Ablaufs sind die folgenden:

• Der Benutzer empfängt eine HTML-Seite, die ein Formular enthält.


• Die Formulardaten, die der Benutzer eingibt, werden an den Server geschickt.
• Ein HTTP-Server (oft der Apache) läuft ständig auf dem Server und horcht an dem zugeordneten
Port auf eingehende Signale.
• Der HTTP-Server leitet die eingehenden Daten an das betroffene Programm, in unserem Fall den
Python-Interpreter, weiter.
• Aus den eingehenden Daten erstellt ein CGI-Skript eine HTML-Antwortseite. Diese dynamische
Seite besteht aus einem Header und HTML-Code.
• Diese Antwortseite wird an den Client gesendet und dort von einem Browser angezeigt.

20.4. Die Pflicht: hallo, ihr alle da draußen


Wie schon weiter oben gesagt, muss man als Programmierer damit anfangen, dass man seine Umwelt
grüßt: ”hallo world”. Die dazugehörige HTML-Seite ist schnell geschrieben:

Beispiel 20.4.1 HTML-Seite ”Hallo world”


1

3 <html>
4 <head>
5 <title>erste HTML-Seite</title>
6 </head>
7 <body>
8 <p>hello world</p>
9 </body>
10 </html>
11

12

So weit, so gut, aber das soll ja keine Anleitung für HTML sein, und das ist eine einfache HTML-Seite.

20.5. Hello world als dynamische Web-Seite


Also wird jetzt aus dieser statischen Seite eine dynamische. Eine solche dynamische Web-Seite besteht
aus 2 Teilen: dem Header und der eigentlichen Seite. Der Header besteht aus der Zeile ”Content-type:
text/html\n”, die so ausgegeben wird:

324
KAPITEL 20. CGI-PROGRAMME 20.5. HELLO WORLD ALS DYNAMISCHE . . .

Beispiel 20.5.1 Header für dynamische HTML-Seiten


print("Content-type: text/html\n")

Wichtig dabei ist, dass nach dem Header immer eine Zeile freigelassen werden muss. Die ganze dy-
namische Web-Seite wird jetzt folgendermaßen gebaut. Der gesamte HTML-Block von oben wird als
eine Zeichenkette, die sich über mehrere Zeilen erstreckt, in dreifache Anführungsstriche geschrieben
und an eine Variable zugewiesen.

Beispiel 20.5.2 Die HTML-Seite als String


1

3 seite = """
4 <html>
5 <head>
6 <title>erste HTML-Seite</title>
7 </head>
8 <body>
9 <p>hello world</p>
10 </body>
11 </html> """
12

13

Diese Variable wird dann nach der Header-Zeile ausgegeben.

Beispiel 20.5.3 Dynamisches Hello world

seite = """
<html>
<head>
<title>erste HTML-Seite</title>
</head>
<body>
<p>hello world</p>
</body>
</html> """
print("Content-type: text/html\n")

print(seite)

Das war es schon! Leider ist es jetzt nicht für jeden sofort zu überprüfen, ob das auch wirklich wie
gewünscht funktioniert, denn nicht jeder hat einen Webserver auf seinem Rechner. Diejenigen, die unter
Linux arbeiten, haben wahrscheinlich schon den Apache installiert. Dann muss das oben geschriebene
Programm noch gespeichert werden (etwa unter dem Namen [Link]), und in das richtige Ver-
zeichnis verschoben werden, meistens /srv/www/cgi-bin. Jetzt muss man noch bedenken, dass ein
CGI-Skript ein Programm ist, das aufrufbar sein muss. Unter Unix / Linux wird also das Attribut auf
0755 gesetzt werden, und dann kann die Seite mit [Link] im Browser
aufgerufen werden.
Für diejenigen, die keinen Webserver eingerichtet haben, kommt im nächsten Kapitel ein Mini-Webserver,
der in Python geschrieben ist.

325
KAPITEL 20. CGI-PROGRAMME 20.6. EIN EIGENER MINI-WEBSERVER

20.6. Ein eigener Mini-Webserver

Dieser Webserver ist übernommen aus M. Lutz, [Programming Python]. Wie Mark Lutz schreibt, erhebt
er keinen Anspruch auf Komfort und Sicherheit, aber er tut es, um auf seinem eigenen Rechner etwas
schnell zu testen. In der Zeile mit webdir = ’???’ müssen natürlich die Fragezeichen ersetzt werden
durch das Verzeichnis, in dem die CGI-Skripte gespeichert werden. Damit ist man aber auf der anderen
Seite unabhängig von den Standard-Vorgaben über die Speicherung von CGI-Skripten und kann diese
in einem beliebigen Verzeichnis (auch im eigenen home-Verzeichnis) speichern. In der darauffolgen-
den Zeile ist der Standard-Port für HTTP eingetragen, aber auch der kann geändert werden, falls das
benötigt oder gewünscht ist.

Beispiel 20.6.1 Ein Web-Server in Python


1

2 #!/usr/bin/python
3 import os, sys
4 from BaseHTTPServer import HTTPServer
5 from CGIHTTPServer import CGIHTTPRequestHandler
6

7 webdir = ’?????’ ## webdir = ’./wwwDateien’


8 port = 80 ## oder ein anderer Port
9

10 if [Link][:3] == ’win’:
11 CGIHTTPRequestHandler.have_popen2 = False
12 CGIHTTPRequestHandler.have_popen3 = False
13 [Link](’cgi-bin’)
14

15 [Link](webdir)
16 srvaddr = ("", port)
17 srvobj = HTTPServer(srvaddr, CGIHTTPRequestHandler)
18 srvobj.serve_forever()
19

So ein schön kurzes Programm, aber es reicht wirklich als Webserver für den Hausgebrauch.

20.7. Dynamik durch Schleifen

In diesem Teil sollen jetzt erste dynamische Seiten erstellt werden. Dazu lassen wir zuerst einmal eine
Variable eine Schleife durchlaufen, vorwärts und rückwärts, und dann bringen wir das kleine Einmal-
eins auf eine HTML-Seite.

20.7.1. Vorwärtszählen ..

Wie im vorigen Beispiel wird zuerst der HTML-Code aufgebaut. Dieser wird in dreifache Anführungsstriche
geschrieben. An der Stelle, wo durch Python dynamischer Inhalt eingefügt werden soll, wird der Platz-
halter %s geschrieben.

326
KAPITEL 20. CGI-PROGRAMME 20.7. DYNAMIK DURCH SCHLEIFEN

Beispiel 20.7.1 For-Schleife in einer dynamischen HTML-Seite

#!/usr/bin/python

seite = ’’’
<html>
<head>
<title>FOR-Schleife</title>
</head>
<body>
%s
</body>
</html>’’’

zeile = "Ich bin eine for-Schleife und gerade in Durchlauf %d<br/>"


text = ’’

for i in range(5):
text += zeile % i

print("Content-type: text/html\n\n")

print(seite % text)

In der letzten Zeile wird die Seite ausgegeben, wobei durch den Prozentoperator der Inhalt der Varia-
blen text in die Variable seite eingefügt wird.

20.7.2. .. und rückwärtszählen

Wie man sofort sieht, ändert sich nur eine Zeile, nämlich die Schleifenbedingung für das Zählen. Während
vorher nur ein Parameter an die Schleife mitgegeben wurde, nämlich das Ende der Schleife (das ist dort
oben bei 5), werden jetzt drei Parameter mitgegeben: der Start (6), das Ende (0) und die Schrittweite (-1).
Das ist alles.

327
KAPITEL 20. CGI-PROGRAMME 20.7. DYNAMIK DURCH SCHLEIFEN

Beispiel 20.7.2 For-DOWNTO-Schleife in einer dynamischen HTML-Seite

#!/usr/bin/python

seite = ’’’
<html>
<head>
<title>FOR-DOWNTO-Schleife</title>
</head>
<body>
%s
</body>
</html>
’’’

zeile = "Ich bin eine FOR DOWNTO Schleife und bin gerade beim Zaehler %d<br/>"
text = ’’

for i in range(6, 0, -1):


text += zeile % i

print("Content-type: text/html\n\n")

print(seite % text)

20.7.3. Das kleine 1 x 1

Jetzt folgt als nächstes Beispiel eine HTML-Seite, die das kleine Einmaleins anzeigt. Hier ist es sinnvoll,
eine Funktion zu schreiben, die das erledigt. Im ersten Anlauf wird jeweils eine Zeile generiert, die Zeile
mit einem Zeilenvorschub beendet, und dann die nächste Zeile erstellt. Die einzelnen Zeilen werden
aneinandergehängt, und der erzeugte String wieder mit Hilfe der Formatierung von Zeichenketten in
den HTML-Code eingefügt.

328
KAPITEL 20. CGI-PROGRAMME 20.7. DYNAMIK DURCH SCHLEIFEN

Beispiel 20.7.3 Das kleine 1 mal 1 auf einer dynamischen HTML-Seite

#!/usr/bin/python

headerZeile = "Content-type: text/html\n\n"

seite = ’’’
<html>
<head>
<title>Kleines 1 x 1</title>
</head>
<body>
%s
</body>
</html>
’’’

def klEinMalEins():
klEinMalEinsString = ’’ # eine leere Zeichenkette wird
# bereit gestellt
for z in range(1, 11):
for s in range(1, 11):
klEinMalEinsString += str(z*s) + ’ ’ # die nächste Zahl wird nach einem
# Leerzeichen eingefügt
klEinMalEinsString += ’<br/>’ # die Zeile wird mit einem
# Zeilenvorschub beendet
return klEinMalEinsString # die Zeichenkette wird zurück-
# gegeben
# Ende der Funktion
print(headerZeile) # Header ausgeben

print(seite % klEinMalEins()) # Seite ausgeben

Das funktioniert. Aber es sieht wirklich nicht schön aus, das muss man wohl zugeben.

Die Verbesserung ist, dass man das kleine Einmaleins jetzt in einer HTML-Tabelle ausgibt. Die Varia-
ble seite sieht fast genau so aus wie bisher, es sind nur die Tags für die Tabelle dazugekommen. Die
Funktion klEinMalEins hat sich etwas mehr geändert. Die Zeile, die jetzt generiert wird, beginnt und

329
KAPITEL 20. CGI-PROGRAMME 20.7. DYNAMIK DURCH SCHLEIFEN

endet mit den Tags für eine Tabellenzeile, jeder einzelne Eintrag bekommt die Table-Data-Tags, versehen
mit der Option rechtsbündig.

Beispiel 20.7.4 Das kleine 1 mal 1 in einer Tabelle (dynamische HTML-Seite)

#!/usr/bin/python

headerZeile = "Content-type: text/html\n\n"

seite = ’’’
<html>
<head>
<title>Kleines 1 x 1</title>
</head>
<body>
<table border=’1’>
%s
</table>
</body>
</html>
’’’

def klEinMalEins():
klEinMalEinsString = ’’
for z in range(1, 11):
klEinMalEinsString += ’<tr>’
for s in range(1, 11):
klEinMalEinsString += ’<td align="right">’+str(z*s)+ ’</td>’
klEinMalEinsString += ’</tr>’
return klEinMalEinsString

print(headerZeile)

print(seite % klEinMalEins())

Und das sieht schon besser aus.

330
KAPITEL 20. CGI-PROGRAMME 20.8. FORMULAR-EINGABE UND . . .

20.8. Formular-Eingabe und Auswertung

Jeder nur ein Kreuz!

—Monty Python2

In diesem Abschnitt soll jetzt das Zusammenspiel von HTML-Formularen und auswertenden Python-
Programmen bearbeitet werden. Aus diesem Grund wird zuerst einmal ein HTML-Formular entworfen,
in das Vorname, Nachname und Betrieb des Benutzers eingegeben werden können.

Beispiel 20.8.1 Eingabeformular in HTML


1

3 <html>
4 <head>
5 <title>Eingabe</title>
6 </head>
7 <body>
8

9 <form action="./cgi-bin/FranksAufgaben/[Link]" method="POST">


10 <font size="4">Formulareingaben vom Besucher der Website</font>
11 <br>
12

13 Vorname:<br>
14 <input type="text" name="vorname"><br>
15 Nachname:<br>
16 <input type="text" name="nachname"><br>
17 Betrieb:<br>
18 <input type="text" name="betrieb"><br>
19 <br>
20

21 <input type="Submit" value="Daten senden">


22 <input type="Reset" value="Daten zur&uuml;cksetzen">
23 <br>
24 <br><b><font size="4">Vielen Dank!</font></b><br>
25

26 </form>
27 </body>
28 </html>
29

30

2 Das Leben des Brian

331
KAPITEL 20. CGI-PROGRAMME 20.8. FORMULAR-EINGABE UND . . .

Das sieht dann so aus:

Abbildung 20.1. Eingabe-Formular in HTML(Namen)

Die HTML-Tags sollen hier im einzelnen nicht durchgesprochen werden. Erwähnenswert ist hier nur
die Zeile mit form action. Hier muss der Dateiname des Python-Skriptes angegeben werden, das die
Eingabe auswertet. Daten aus Formularen können mit 2 Methoden weitergegeben werden: mittels post
oder mittels get. Der wesentliche Unterschied ist der, dass die mit post geschickten Daten in einem
gesonderten Paket an den Server geschickt werden, während bei der Methode get die Daten an die
URL nach einem Fragezeichen angehängt werden. Das kann man nachher ganz schnell testen, wenn
das Formular und das zugehörige Programm erst einmal funktionieren.

332
KAPITEL 20. CGI-PROGRAMME 20.8. FORMULAR-EINGABE UND . . .

Kommen wir also zum auswertenden Programm.

Beispiel 20.8.2 Auswertung des Eingabeformulars(Namen)


1

3 #!/usr/bin/python
4 # -*- coding: utf-8 -*-
5

6 import cgi
7 formularFelder = [Link]()
8

9 seite = ’’’
10 <html>
11 <head>
12 <title>Formularauswertung</title>
13 </head>
14 <body>
15 Auswertung eines Formulars
16 <br>
17 <br>
18 %s
19 </body>
20 </html>’’’
21

22 zeilen = ’ ... folgende Daten wurden übermittelt:<br><br>’


23 zeilen += ’Vorname: ’+formularFelder[’vorname’].value+’<br>’
24 zeilen += ’Nachname: ’ +formularFelder[’nachname’].value+’<br>’
25 zeilen += ’Betrieb: ’+formularFelder[’betrieb’].value+’<br>’
26

27 print("Content-type: text/html\n\n")
28 print(seite % zeilen)
29

Die wichtigen Zeilen sind die beiden ersten. Um Formulareingaben zu verarbeiten, muss die Biblio-
thek cgi eingebunden werden. Diese Bibliothek enthält die Klasse FieldStorage, die alle übergebenen
Daten enthält, egal wie sie übergeben wurden.
Danach wird wieder eine Seite in HTML aufgebaut, und diese wird in der Variablen seite gespei-
chert. Der von Python generierte dynamische Code beginnt mit der Zuweisung von Text an die Variable
zeilen. Danach wird mittels des Kurzschluss-Additions-Operators += Text angehängt, der aus den
übertragenen Daten aus dem Formular bestehen.
Die Klasse [Link] enthält die Daten in Form eines Dictionary. Das heißt im vorliegenden
Fall, dass die Variable formularFelder so aufgebaut ist:
formularFelder = {’vorname’:’Martin’, ’nachname’:’Schimmels’, ’betrieb’:’BMW’}

Es ist jetzt ganz einfach, die Methode get bei der Übertragung von Daten zu testen. Es muss nur in der
Zeile mit form action im HTML-Formular das post in ein get geändert werden. Das verarbeitende

333
KAPITEL 20. CGI-PROGRAMME 20.9. EINE RECHNUNG

Python-Programm muss nicht geändert werden, weil die Methoden des Moduls cgi die ganze Arbeit
erledigen. Das Modul erkennt, in welcher Form die Daten übermittelt werden und wertet alles richtig
aus. Den Unterschied sieht man aber in der Adresszeile des Browsers. Bei Benutzung der Post-Methode
sieht diese Zeile so aus:

[Link]

bei Benutzung der Get-Methode so:

[Link]
&nachname=Schimmels&betrieb=BMW+Dingolfing

20.9. Eine Rechnung

Im nächsten Beispiel soll eine Rechnung für den Eintritt in eine Sportveranstaltung geschrieben werden.
Es gibt einen Normaltarif, dazu allerdings Ermäßigungen für Kinder, Studenten und Senioren. In ein
HTML-Formular soll die Anzahl Erwachsener, die Anzahl Kinder, Senioren und Studenten eingegeben
werden. Ein Python-Programm berechnet den Rechnungsbetrag, der dann auf der nächsten HTML-Seite
ausgegeben wird.
Das Eingabeformular könnte so aussehen:

Abbildung 20.2. Eingabe-Formular für eine Rechnung in HTML

Der dazugehörende HTML-Code ist im nächsten Bild zu sehen:

334
KAPITEL 20. CGI-PROGRAMME 20.9. EINE RECHNUNG

Beispiel 20.9.1 Eingabeformular für Rechnung


1

3 <html>
4

5 <head>
6 <title>Rechnung Eintritt Sport</title>
7 <meta name="generator" content="Bluefish 2.2.3" >
8 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
9 </head>
10 <body>
11 <h1>Eintrittskarten für Sportveranstaltung</h1>
12 <p>
13 <form action="./cgi-bin/FranksAufgaben/[Link]" method="POST">
14 <br>
15 <table>
16 <tr>
17 <td>Anzahl Erwachsene:</td>
18 <td><input type="text" name="erw"></td>
19 </tr>
20 <tr>
21 <td>Anzahl Kinder:</td>
22 <td><input type="text" name="kind"></td>
23 </tr>
24 <tr>
25 <td>Anzahl Senioren:</td>
26 <td><input type="text" name="sen"></td>
27 </tr>
28 <tr>
29 <td>Anzahl Studenten:</td>
30 <td><input type="text" name="stud"></td>
31 </tr>
32 </table>
33

34 <input type="Submit" value="Daten senden">


35 <input type="Reset" value="Daten zur&uuml;cksetzen">
36 <br>
37 <br><b><font size="4">Vielen Dank!</font></b><br>
38

39 </form>
40 </p>
41

42 </body>
43 </html>
44

45

Für die Berechnung des Rechnungsbetrags erstellen wir eine Klasse Rechnung. Der Konstruktor der
Klasse nimmt die Anzahl der Erwachsenen, Kinder, Senioren und Studenten in Empfang. Die Klasse hat
die Methode rechnungSchreiben, zusätzlich zum Testen auch noch die Methode rechnungAnzeigen.

Um den Test durchzuführen, wird wieder einmal mittels des Konstrukts if name == ’ main ’:
der Test in die Klassen-Datei eingefügt.

335
KAPITEL 20. CGI-PROGRAMME 20.9. EINE RECHNUNG

Beispiel 20.9.2 Klasse Rechnung


1

2 #!/usr/bin/python
3

4 class Rechnung():
5 def __init__(self, anzErw=0, anzKids=0, anzSen=0, anzStud=0):
6 [Link] = anzErw
7 [Link] = anzKids
8 [Link] = anzSen
9 [Link] = anzStud
10 [Link] = 10.0
11 [Link] = 0.5
12 [Link] = 0.3
13 [Link] = 0.4
14

15 def rechnungSchreiben(self):
16 [Link] = [Link] * [Link]
17 + [Link] * [Link]*[Link]
18 + [Link]*[Link]*[Link]
19 + [Link]*[Link]*[Link]
20

21 def rechnungAnzeigen(self):
22 print(’Rechnungsbetrag: ’+ str([Link]))
23

24 if __name__ == ’__main__’:
25 meineRechnung = Rechnung(3, 2, 4, 1)
26 [Link]()
27 [Link]()
28

336
KAPITEL 20. CGI-PROGRAMME 20.9. EINE RECHNUNG

Nachdem der Test erfolgreich war, wird das Skript, das die Auswertung durchführt, geschrieben. Das
sieht so aus:

Beispiel 20.9.3 Auswertung des Eingabeformulars Rechnung


1

3 #!/usr/bin/python
4

5 import cgi
6 formularFelder = [Link]()
7

8 seite = ’’’
9 <html>
10 <head>
11 <title>Rechnung Sportveranstaltung</title>
12 </head>
13 <body>
14 <h1>Rechnung</h1>
15 <br>
16 <br>
17 %s
18 </body>
19 </html>’’’
20

21

22 from clRechnungEinfach import Rechnung


23 try:
24 erw = int(formularFelder[’erw’].value)
25 except:
26 erw = 0
27 try:
28 kind = int(formularFelder[’kind’].value)
29 except:
30 kind = 0
31 try:
32 sen = int(formularFelder[’sen’].value)
33 except:
34 sen = 0
35 try:
36 stud = int(formularFelder[’stud’].value)
37 except:
38 stud = 0
39

40 neueRechnung = Rechnung(erw, kind, sen, stud)


41 [Link]()
42

43 print("Content-type: text/html\n\n")
44

45 print(seite % str([Link]))
46

47

48

Zu beachten in diesem Stück Code sind die 4 try - except-Anweisungen. Damit wird gesichert,
dass das Skript auch dann korrekt arbeitet, wenn im Formular ein Feld nicht gefüllt wird. In diesem Fall
wird angenommen, dass für diese Gruppe Menschen der Wert 0“ gemeint ist.

337
KAPITEL 20. CGI-PROGRAMME 20.9. EINE RECHNUNG

Abbildung 20.3. Ausgabe einer Rechnung in HTML (aber wirklich nicht schön)

Da die Ausgabe des Programms wirklich nicht sehr schön ist, denn mit der alleinigen Angabe des zu
zahlenden Betrags kann man nicht zufrieden sein, wird die Klasse Rechnung verbessert. Die Veränderung
findet in der Methode rechnungSchreiben statt. Von der Logik ändert sich nichts, es handelt sich hier
nur um Änderungen in der Darstellung durch HTML. Die Ausgabe wird hier in eine Tabelle gemacht.

338
KAPITEL 20. CGI-PROGRAMME 20.9. EINE RECHNUNG

Beispiel 20.9.4 Klasse Rechnung (verbessert)


1

3 #!/usr/bin/python
4

5 class Rechnung():
6 def __init__(self, anzErw=0, anzKids=0, anzSen=0, anzStud=0):
7 [Link] = anzErw
8 [Link] = anzKids
9 [Link] = anzSen
10 [Link] = anzStud
11 [Link] = 10.0
12 [Link] = 0.5
13 [Link] = 0.3
14 [Link] = 0.4
15

16 def rechnungSchreiben(self):
17 [Link] = [Link] * [Link]
18 + [Link] * [Link]*[Link]
19 + [Link]*[Link]*[Link]
20 + [Link]*[Link]*[Link]
21 [Link] = ’<table border="1">’
22 # Zeile f. Erwachsene
23 [Link] += ’<tr>’
24 [Link] += ’<td>Erwachsene:</td>
25 <td align="right">’+str([Link])+’</td>’
26 t1 = ’%4.2f’ % [Link]
27 [Link] += ’<td align="right">’+str(t1)+’ Euro</td>’
28 t2 = ’%4.2f’ % ([Link] * [Link])
29 [Link] += ’<td align="right">’+str(t2)+’ Euro</td>’
30 [Link] += ’</tr>’
31 # Zeile f. Kinder
32 [Link] += ’<tr>’
33 [Link] += ’<td>Kinder:</td>
34 <td align="right">’+str([Link])+’</td>’
35 t1 = ’%4.2f’ % ([Link] * [Link])
36 [Link] += ’<td align="right">’+str(t1)+’ Euro</td>’
37 t2 = ’%4.2f’ % ([Link] * [Link] * [Link])
38 [Link] += ’<td align="right">’+str(t2)+’ Euro</td>’
39 [Link] += ’</tr>’
40

41

339
KAPITEL 20. CGI-PROGRAMME 20.9. EINE RECHNUNG

Beispiel 20.9.5 Klasse Rechnung (verbessert) (Forts.)


1

3 # Zeile f. Senioren
4 [Link] += ’<tr>’
5 [Link] += ’<td>Senioren:</td>
6 <td align="right">’+str([Link])+’</td>’
7 t1 = ’%4.2f’ % ([Link] * [Link])
8 [Link] += ’<td align="right">’+str(t1)+’ Euro</td>’
9 t2 = ’%4.2f’ % ([Link] * [Link] * [Link])
10 [Link] += ’<td align="right">’+str(t2)+’ Euro</td>’
11 [Link] += ’</tr>’
12 # Zeile f. Studis
13 [Link] += ’<tr>’
14 [Link] += ’<td>Studenten:</td>
15 <td align="right">’+str([Link])+’</td>’
16 t1 = ’%4.2f’ % ([Link] * [Link])
17 [Link] += ’<td align="right">’+str(t1)+’ Euro</td>’
18 t2 = ’%4.2f’ % ([Link] * [Link] * [Link])
19 [Link] += ’<td align="right">’+str(t2)+’ Euro</td>’
20 [Link] += ’</tr>’
21 # Summen-Zeile
22 [Link] += ’<tr> <td colspan="3">Summe:</td> <td>’
23 t1 = ’%4.2f’ % ([Link])
24 [Link] += str(t1)+’ Euro’+ ’</td> </tr>’
25 # Ende
26 [Link] += ’</table>’
27

28 def rechnungAnzeigen(self):
29 print(’Rechnungsbetrag: ’+ str([Link]))
30

31 if __name__ == ’__main__’:
32 meineRechnung = Rechnung(3, 2, 4, 1)
33 [Link]()
34 [Link]()
35 print([Link])
36

37

In dem CGI-Skript muss dann nur die letzte Zeile ersetzt werden durch

Beispiel 20.9.6 Verbesserung im auswertenden Programm


print(seite % str([Link]))

340
KAPITEL 20. CGI-PROGRAMME 20.10. JETZT ABER WIRKLICHE DYNAMIK

Abbildung 20.4. Ausgabe einer Rechnung in HTML (so kann man das akzeptieren)

20.10. Jetzt aber wirkliche Dynamik


Eine typische Anwendung für eine dynamische Web-Seite ist ein Besucherzähler. Jedesmal, wenn eine
bestimmte Seite aufgerufen wird, wird der Zähler um eins erhöht und dann angezeigt mit einer freund-
lichen Bemerkung wie etwa: Du bist der 35812. Besucher dieser Seite.
Zuerst brauchen wir also eine Klasse Zaehler. Diese Klasse hat zwei Attribute, nämlich einen Initial-
Wert und den eigentlichen Wert, den der Zähler zu einer bestimmten Zeit innehat. Der aktuelle Wert
wird in einer einfachen Textdatei gespeichert, weswegen von Hand eine Datei zaehlerDat angelegt
werden muss, in der einfach eine 0 steht. Der Konstruktor liest die Datei und weist den Inhalt dem
Attribut zWert zu.
Die Klasse Zaehler benötigt dann noch 3 Methoden, nämlich inkrementieren, dekrementieren
und wertZuruecksetzen (die braucht man nicht für den Besucherzähler, aber vielleicht für andere
Dinge). Jede dieser Methoden besteht aus 4 Teilen, dem Öffnen der Textdatei im (Über-)Schreib-Modus,
der Aktion selber, die zWert verändert, dem Schreiben in die Datei und dem Schließen der Datei.

341
KAPITEL 20. CGI-PROGRAMME 20.10. JETZT ABER WIRKLICHE DYNAMIK

Beispiel 20.10.1 Die Klasse Zähler


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4 class Zaehler(object):
5 def __init__(self):
6 [Link](’r’)
7 [Link] = int([Link]())
8 [Link] = 0
9 [Link]()
10

11 def dateiOeffnen(self, modus):


12 [Link] = open("zaehlerDat",modus)
13

14 def dateiSchreiben(self, z):


15 [Link](str(z))
16

17 def dateiSchliessen(self):
18 [Link]()
19

20 def wertZuruecksetzen(self):
21 [Link](’w’)
22 [Link] = [Link]
23 [Link]([Link])
24 [Link]()
25

26 def inkrement(self):
27 [Link](’w’)
28 [Link] = [Link] + 1
29 [Link]([Link])
30 [Link]()
31

32 def dekrement(self):
33 [Link](’w’)
34 [Link] = [Link] - 1
35 [Link]([Link])
36 [Link]()
37

Man kann sich natürlich jetzt ein kleines Programm schreiben, das diese Klasse benützt – und das
sollte man auch tun, um zu testen, ob alles so funktioniert, wie man sich das vorstellt.
Wenn man das gemacht hat und sicher ist, dass alles wie gewünscht tut, schreibt man sich die HTML-
Seite, die den Besucherzähler aufnehmen soll. An der Stelle, wo der Besucherzähler nachher tatsächlich
arbeiten soll, stehen im Moment noch 3 Fragezeichen.

342
KAPITEL 20. CGI-PROGRAMME 20.10. JETZT ABER WIRKLICHE DYNAMIK

Beispiel 20.10.2 Der Besucherzähler (HTML-Teil)


1

3 <html>
4 <head>
5 <title>Martins Test</title>
6 <meta http-equiv="Content-type" content="text/html; charset=latin1" />
7 </head>
8 <body>
9 <h1>Ein Besucherzähler</h1>
10 <p>Hallo Du da!!</p>
11 <p>Du bist der ???. Besucher</p>
12 </body>
13 </html>
14

15

Diese ganzer HTML-Code wird, wie schon weiter oben, in dreifache Anführungszeichen gesetzt. Statt
der 3 Fragezeichen wird jetzt ein Python-Platzhalter, das
%s
, geschrieben. Die Header-Zeile wird geschrieben und es wird die Klasse Zaehler importiert. Eine
Instanz von Zaehler wird erzeugt und der Wert erhöht. Dann wird die vorher in Anführungszeichen
geschriebene Seite geschrieben, wobei der aktuelle Wert des Zählers über die String-Ersetzung des
%s
vorgenommen wird. (Falls Du nicht mehr weißt, wie das mit der Formatierung funktioniert, hier ist der
Link zu dieser Seite.)

Beispiel 20.10.3 Der Besucherzähler (vollständig)


1

3 #!/usr/bin/python
4

5 seite = ’’’
6 <html>
7 <head>
8 <title>Martins Test</title>
9 <meta http-equiv="Content-type" content="text/html; charset=latin1" />
10 </head>
11 <body>
12 <h1>Ein Besucherzähler</h1>
13 <p>Hallo Du da!!</p>
14 <p>Du bist der %s . Besucher</p>
15 </body>
16 </html>
17 ’’’
18

19 print("Content-type: text/html\n\n")
20

21 from cl_zaehler import Zaehler


22 besucherZaehler = Zaehler()
23 [Link]()
24

25 print(seite % [Link])
26

27

343
21. Eine Kreuzung auf meiner Web-Seite
21.1. Die Ampel kommt ins Netz
Weiter oben bei [Ampel auf der Konsole] haben wir eine Ampel und eine Kreuzung realisiert. Nun soll
daraus eine dynamische WEeb-Seite werden. In einem ersten Schritt erstellen wir eine statische Web-
Seite, die in einer Tabelle die Ampel darstellt. Der HTML-Code dazu sieht so aus:

Beispiel 21.1.1 HTML-Code für eine Ampel


1

3 <html>
4 <head>
5 <title>Eine Ampel</title>
6 <meta name="generator" content="Bluefish 2.2.3" />
7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
8 </head>
9 <body bgcolor="#C6C6C6">
10 <h1>Eine Ampel</h1>
11 <table width="120" cellspacing="10" border="10" cellpadding="10"
12 align="center" bgcolor="white">
13 <tbody>
14 <tr>
15 <td></td>
16 </tr>
17 <tr>
18 <td></td>
19 </tr>
20 <tr>
21 <td></td>
22 </tr>
23 </tbody>
24 </table>
25 </body>
26 </html>
27

345
KAPITEL 21. EINE KREUZUNG AUF . . . 21.1. DIE AMPEL KOMMT INS NETZ

Im Browser sieht diese Seite so aus:

Der HTML-Code wird jetzt in eine Variable seite eingebunden. In den 3 Lichtern der Ampel wird als
Attribut die Hintergrundfarbe eingefügt, wobei der Wert der Hintergrundfarbe über den %s-Operator
durch den folgenden Python-Code eingefügt wird. (Das kleine o im Tabellen-Element dient dazu, die
Ampel etwas größer zu machen.)
Der Python-Code bindet zuerst die Klasse Ampel ein, sodann wird ein Objekt dieser Klasse erzeugt
und die Methode umschalten dieses Objekts aufgerufen. Nachdem die Lichter der Ampel umgeschal-
tet wurden, werden die Farben der Lichter in einen Tupel geschrieben, der mit dem %-Operator in die
Variable seite eingefügt wird.

346
KAPITEL 21. EINE KREUZUNG AUF . . . 21.1. DIE AMPEL KOMMT INS NETZ

Beispiel 21.1.2
1

3 #!/usr/bin/python
4

5 seite = ’’’
6 <html>
7 <head>
8 <title>Eine Ampel</title>
9 </head>
10 <body bgcolor="#C6C6C6">
11 <h1>Eine Ampel</h1>
12 <table width="120" cellspacing="10" border="10" cellpadding="10"
13 align="center" bgcolor="white">
14 <tbody>
15 <tr>
16 <td bgcolor="%s">o</td>
17 </tr>
18 <tr>
19 <td bgcolor="%s">o</td>
20 </tr>
21 <tr>
22 <td bgcolor="%s">o</td>
23 </tr>
24 </tbody>
25 </table>
26 <FORM action="[Link]" method="POST">
27 <INPUT type="submit" name="umschalten" value="Umschalten" size="120">
28 </FORM>
29 </body>
30 </html>
31 ’’’
32

33 from clAmpel import Ampel


34

35 meineAmpel = Ampel()
36 [Link]()
37

38 headerZeile = "Content-type: text/html\n\n"


39

40 print(headerZeile)
41 print(seite %
42 tuple([Link][[Link][[Link]]]))
43

44

347
KAPITEL 21. EINE KREUZUNG AUF . . . 21.2. DIE KREUZUNG IM NETZ IST AUCH . . .

21.2. Die Kreuzung im Netz ist auch nicht schwerer

Die Kreuzung ist eine 3x3 - Tabelle, bei der in die mittleren Zellen der äußeren Zeilen und Spalten jeweils
eine 3x1 - Tabelle die Ampel abbildet.

Beispiel 21.2.1 HTML und Python für die Kreuzung


1

3 <html>
4 <head>
5 <title>Eine Ampel</title>
6 <meta name="generator" content="Bluefish 2.2.3" >
7 <meta http-equiv="Content-Type" content="text/html">
8 </head>
9 <body bgcolor="#C6C6C6">
10 <h1>Eine Kreuzung</h1>
11 <table width="720" cellspacing="10" border="10" cellpadding="10"
12 align="center" bgcolor="white">
13 <tr>
14 <td></td>
15 <td>
16 <table width="120" cellspacing="10" border="10" cellpadding="10"
17 align="center" bgcolor="white">
18 <tbody>
19 <tr>
20 <td bgcolor="#FF0000"></td>
21 </tr>
22 <tr>
23 <td bgcolor="#000000"></td>
24 </tr>
25 <tr>
26 <td bgcolor="#000000"></td>
27 </tr>
28 </tbody>
29 </table>
30 </td>
31 <td></td>
32 </tr>
33 <tr>
34 <td>
35 <table width="120" cellspacing="10" border="10" cellpadding="10"
36 align="center" bgcolor="white">
37 <tbody>
38 <tr>
39 <td bgcolor="#FF0000"></td>
40 </tr>
41 <tr>
42 <td bgcolor="#000000"></td>
43 </tr>
44 <tr>
45 <td bgcolor="#000000"></td>
46 </tr>
47 </tbody>
48 </table>
49 </td>
50

348
KAPITEL 21. EINE KREUZUNG AUF . . . 21.2. DIE KREUZUNG IM NETZ IST AUCH . . .

Beispiel 21.2.2 HTML und Python für die Kreuzung (Forts.)


1

3 <td></td>
4 <td>
5 <table width="120" cellspacing="10" border="10" cellpadding="10"
6 align="center" bgcolor="white">
7 <tbody>
8 <tr>
9 <td bgcolor="#FF0000"></td>
10 </tr>
11 <tr>
12 <td bgcolor="#000000"></td>
13 </tr>
14 <tr>
15 <td bgcolor="#000000"></td>
16 </tr>
17 </tbody>
18 </table>
19 </td>
20 </tr>
21 <tr>
22 <td></td>
23 <td>
24 <table width="120" cellspacing="10" border="10" cellpadding="10"
25 align="center" bgcolor="white">
26 <tbody>
27 <tr>
28 <td bgcolor="#FF0000"></td>
29 </tr>
30 <tr>
31 <td bgcolor="#000000"></td>
32 </tr>
33 <tr>
34 <td bgcolor="#000000"></td>
35 </tr>
36 </tbody>
37 </table>
38 </td>
39 <td></td>
40 </tr>
41 </table>
42

43 <FORM action="[Link]" method="POST">


44 <INPUT type="submit" name="umschalten" value="Umschalten" size="120">
45 </FORM>
46 </body>
47 </html>
48

349
KAPITEL 21. EINE KREUZUNG AUF . . . 21.2. DIE KREUZUNG IM NETZ IST AUCH . . .

Im Browser sieht das so aus:

Der Code für die dynamische Web-Seite ist nach dem selben Schema gebaut wie der Code für die
dynamische Web-Ampel. Der HTML-Code wird in die Variable seite eingebunden. In den 3 Lichtern
der 4 Ampeln wird als Attribut die Hintergrundfarbe eingefügt, wobei der Wert der Hintergrundfarbe
über den %s-Operator durch den folgenden Python-Code eingefügt wird. (Das kleine o im Tabellen-
Element dient dazu, die Ampel etwas größer zu machen.)
Der Python-Code bindet zuerst die Klasse clKreuzung ein, sodann wird ein Objekt dieser Klasse
erzeugt und die Methode umschalten dieses Objekts aufgerufen. Nachdem die Lichter der Ampel
umgeschaltet wurden, wird ein Tupel aufgebaut, der von allen 4 Ampeln die Farben der einzelnen
Lichter enthält, insgesamt also 12 Werte. Das ist der einzige etwas lästige Schritt in diesem Programm.
Denn diese 12 Werte werden zuerst in eine Liste, die zustandsListe, geschrieben, die dann beim
Einfügen in die seite in ein Tupel umgewandelt wird.

350
KAPITEL 21. EINE KREUZUNG AUF . . . 21.2. DIE KREUZUNG IM NETZ IST AUCH . . .

Beispiel 21.2.3 Die Kreuzung


1

4 #!/usr/bin/python
5

6 seite = ’’’
7 <html>
8 <head>
9 <title>Eine Kreuzung</title>
10 </head>
11 <body bgcolor="#C6C6C6">
12 <h1>Eine Kreuzung</h1>
13 <table width="720" cellspacing="10" border="10" cellpadding="10"
14 align="center" bgcolor="white">
15 <tbody>
16 <tr>
17 <td></td>
18 <td>
19 <table width="120" cellspacing="10" border="10" cellpadding="10"
20 align="center" bgcolor="white">
21 <tbody>
22 <tr>
23 <td bgcolor="%s">o</td>
24 </tr>
25 <tr>
26 <td bgcolor="%s">o</td>
27 </tr>
28 <tr>
29 <td bgcolor="%s">o</td>
30 </tr>
31 </tbody>
32 </table>
33 </td>
34 <td></td>
35 </tr>
36 <tr>
37 <td>
38 <table width="120" cellspacing="10" border="10" cellpadding="10"
39 align="center" bgcolor="white">
40 <tbody>
41 <tr>
42 <td bgcolor="%s">o</td>
43 </tr>
44 <tr>
45 <td bgcolor="%s">o</td>
46 </tr>
47 <tr>
48 <td bgcolor="%s">o</td>
49 </tr>
50 </tbody>
51 </table>
52 </td>
53

351
KAPITEL 21. EINE KREUZUNG AUF . . . 21.2. DIE KREUZUNG IM NETZ IST AUCH . . .

Beispiel 21.2.4 Die Kreuzung (Forts.)


1

3 <td></td>
4 <td>
5 <table width="120" cellspacing="10" border="10" cellpadding="10"
6 align="center" bgcolor="white">
7 <tbody>
8 <tr>
9 <td bgcolor="%s">o</td>
10 </tr>
11 <tr>
12 <td bgcolor="%s">o</td>
13 </tr>
14 <tr>
15 <td bgcolor="%s">o</td>
16 </tr>
17 </tbody>
18 </table>
19 </td>
20 </tr>
21 <tr>
22 <td></td>
23 <td>
24 <table width="120" cellspacing="10" border="10" cellpadding="10"
25 align="center" bgcolor="white">
26 <tbody>
27 <tr>
28 <td bgcolor="%s">o</td>
29 </tr>
30 <tr>
31 <td bgcolor="%s">o</td>
32 </tr>
33 <tr>
34 <td bgcolor="%s">o</td>
35 </tr>
36 </tbody>
37 </table>
38 </td>
39 <td></td>
40 </tr>
41 </tbody>
42 </table>
43

44

45 <FORM action="[Link]" method="POST">


46 <INPUT type="submit" name="umschalten" value="Umschalten" size="120">
47 </FORM>
48 </body>
49 </html>
50 ’’’
51

52

352
KAPITEL 21. EINE KREUZUNG AUF . . . 21.2. DIE KREUZUNG IM NETZ IST AUCH . . .

Beispiel 21.2.5 Die Kreuzung (2. Forts.)


1

4 from clKreuzung import Kreuzung


5

6 meineKreuzung = Kreuzung()
7 [Link]()
8

9 zustandsListe = []
10 for einZustand in [Link]
11 [[Link][[Link]]]:
12 [Link](einZustand)
13 for einZustand in [Link]
14 [[Link][[Link]]]:
15 [Link](einZustand)
16 for einZustand in [Link]
17 [[Link][[Link]]]:
18 [Link](einZustand)
19 for einZustand in [Link]
20 [[Link][[Link]]]:
21 [Link](einZustand)
22 #print(zustandsListe)
23 headerZeile = "Content-type: text/html\n\n"
24

25 print(headerZeile)
26

27 print(seite % tuple(zustandsListe))
28

353
22. Programme mit grafischer Oberfläche
The empty handed painter from your streets
Is drawing crazy patterns on your sheets
(Bob Dylan1 )

22.1. Tkinter

Das Toolkit von J. Ousterhout, abgekürzt ganz einfach tk“, hat eine Schnittstelle für Python, die sich

tkinter“ nennt. Die Benutzung dieses Toolkits macht deutlich, dass grundsätzlich bei einem Programm

unterschieden werden muss zwischen dem Teil, der das gegebene Problem löst, und dem Teil, der die
Lösung in einer dem Benutzer angenehmen Form präsentiert.
Vor allem Anfänger neigen dazu, das Design einer Schnittstelle zwischen Problemlösung und Be-
nutzer vorrangig zu bearbeiten, weil sich jeder, auch ein Programmieranfänger, zutraut, mit grafischen
Tools eine grafische Oberfläche zu erstellen. Weil dies hier aber ein Programmierkurs ist, wurde das De-
sign, die Benutzerfreundlichkeit, die Bedienbarkeit eines Programms bisher nicht in Angriff genommen.
Den wichtigsten Vorteil von tk (und damit von Tkinter) will ich hier aber auch nicht verschweigen:
auch tk“ ist freie Software und kann aus dem Internet heruntergeladen werden. In den meisten Python-

Distributionen ist Tkinter allerdings sogar eingebaut.

22.2. Problem: Temperaturen umrechnen (zuerst ohne grafische


Oberfläche) . . .

Hier soll keine Einführung in Tkinter gegeben werden, sondern nur an einem Beispiel gezeigt werden,
wie die verschiedenen Komponenten zusammenspielen. Es soll ein kleiner Umrechner für Temperatu-
ren (Celsius nach Fahrenheit und umgekehrt) geschrieben werden.
Dazu wird zuerst eine angemessene Klasse erzeugt:

Abbildung 22.1. Klassendiagramm Temperatur

In Python sieht der dazugehörige Quellcode so aus:

1 It’s all over now, Baby Blue auf: Bringing it all back home

355
KAPITEL 22. PROGRAMME MIT . . . 22.2. PROBLEM: TEMPERATUREN . . .

Beispiel 22.2.1 Klassendefinition: Temperaturen


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4

5 class Temperatur():
6 def __init__(self):
7 [Link] = 0.001
8 [Link] = 0.002
9

10 def leseCelsius(self):
11 [Link] = float(input("Temperatur in Grad Celsius eingeben: "))
12

13 def leseFahrenheit(self):
14 [Link] = float(input("Temperatur in Grad Fahrenheit eingeben: "))
15

16 def celsius2fahrenheit(self):
17 [Link] = 9.0 / 5.0 * [Link] + 32.0
18

19 def schreibeFahrenheit(self):
20 print("Temperatur in Grad Fahrenheit: ",[Link])
21

22 def fahrenheit2celsius(self):
23 [Link] = 5.0 / 9.0 * ([Link] - 32)
24

25 def schreibeCelsius(self):
26 print("Temperatur in Grad Celsius: ",[Link])
27

28 def wertZuruecksetzen(self):
29 [Link] = 0.01
30 [Link] = 0.02
31

Wie immer gehört dazu ein aufrufendes Programm, das wieder einmal in einer While-Schleife Einga-
ben ermöglicht und dann diese bearbeitet.

356
KAPITEL 22. PROGRAMME MIT . . . 22.3. . . . UND JETZT MIT GRAFISCHER . . .

Beispiel 22.2.2 Aufruf der Klasse Temperatur


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4 from cl_Temperatur import Temperatur
5

6 modus = ’x’
7 t1 = temperatur()
8 while modus != ’E’:
9 modus = input(’\nAuswahl: \nCelsius nach Fahrenheit mit C\n
10 Fahrenheit nach Celsius mit F\nEnde mit E: ’)
11 if modus == ’C’:
12 [Link]()
13 t1.celsius2fahrenheit()
14 [Link]()
15 elif modus == ’F’:
16 [Link]()
17 t1.fahrenheit2celsius()
18 [Link]()
19 elif modus == ’E’:
20 pass
21 else:
22 print(’Falsche Eingabe. Nur C, F, E erlaubt’)
23

24 print(’Ciao’)
25

22.3. . . . und jetzt mit grafischer Oberfläche


Auch dazu wird zuerst eine Klasse definiert, nämlich die Klasse der grafischen Oberfläche. Diese benötigt
einige Teile des Tkinter-Moduls und natürlich die Klasse Temperatur. Ein solches grafisches Fenster
leitet sich von der Tkinter-Klasse frame ab. Die Buttons werden mit b1 bis b3 sowie raus bezeichnet,
die Eingabefelder (auf englisch entry) mit en1 bis en2 und die Textfelder (auf englisch label) mit la1
bis la2

Abbildung 22.2. Klassendefinition: GUI für die Temperatur

Der Konstruktor der grafischen Oberfläche erstellt das Objekt und ruft die Methode erstelleWidgets
auf, die dann für die Elemente der Oberfläche zuständig ist. Diese Elemente werden in tk widgets ge-
nannt. Jedes widget ist ein Objekt einer Tkinter-Klasse, so ist zum Beispiel das widget b1 ein Objekt
der Klasse Button. Die Methode grid gibt an, wieviel Platz das Objekt im Gitter haben soll. Mit den
Methoden insert und delete werden Texte in die Entry-Objekte geschrieben. Den Buttons b1 und
b2 werden die Arbeits-Methoden, nämlich die Methoden, die die Umrechnung leisten, zugeordnet.
Diese Methoden der Oberfläche rufen natürlich nur die Methoden der Klasse Temperatur auf.

357
KAPITEL 22. PROGRAMME MIT . . . 22.3. . . . UND JETZT MIT GRAFISCHER . . .

Beispiel 22.3.1 Die Klasse für das Fenster


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4 from Tkinter import *
5 from Tkconstants import *
6 from cl_Temperatur import temperatur
7 import tkMessageBox
8

9 t1 = temperatur()
10

11 class App(Frame):
12 def __init__(self, master = None):
13 Frame.__init__(self, master)
14 [Link](’Temperatur-Rechner’)
15 [Link](padx = 10, pady = 10)
16 [Link]()
17

18 def erstelleWidgets(self):
19 [Link] = Button(self, text="Ende", bg="#C1281F", command=[Link])
20 [Link](row = 1, column = 4, columnspan = 1)
21

22 self.b1 = Button(self, text = "umrechnen Celsius nach Fahrenheit",


23 command = [Link])
24 [Link](row = 1, column = 1, columnspan = 1)
25

26 self.b2 = Button(self, text = "umrechnen Fahrenheit nach Celsius",


27 command = [Link])
28 [Link](row = 1, column = 2, columnspan = 1)
29

30 self.b3 = Button(self, text = "zurücksetzen",


31 command = [Link])
32 [Link](row = 1, column = 3, columnspan = 1)
33

34 self.la1 = Label(self, text=’Grad Celsius’)


35 [Link](row = 2, column = 1, columnspan = 1)
36

37 self.en1 = Entry(self, textvariable = [Link])


38 [Link](0, [Link])
39 [Link](row = 2, column = 2, columnspan = 1)
40

41 self.la2 = Label(self, text=’Grad Fahrenheit’)


42 [Link](row = 2, column = 3, columnspan = 1)
43

44 self.en2 = Entry(self, textvariable = [Link])


45 [Link](0, [Link])
46 [Link](row = 2, column = 4, columnspan = 1)
47

48 def rueckWert(self):
49 [Link]()
50 [Link](0, END)
51 [Link](0,[Link])
52 [Link](0, END)
53 [Link](0,[Link])
54

55 def meldeFenster(self):
56 if [Link](’Quit’, ’Wirklich aufhören?’):
57 k = self.winfo_toplevel()
58 [Link]()
59

358
KAPITEL 22. PROGRAMME MIT . . . 22.3. . . . UND JETZT MIT GRAFISCHER . . .

Beispiel 22.3.2 Die Klasse für das Fenster (Forts.)


1

2 def CnachF(self):
3 [Link] = float([Link]())
4 t1.celsius2fahrenheit()
5 [Link](0, END)
6 [Link](0,[Link])
7

8 def FnachC(self):
9 [Link] = float([Link]())
10 t1.fahrenheit2celsius()
11 [Link](0, END)
12 [Link](0,[Link])
13

Das eigentliche Programm, das aufgerufen wird, ist folglich wieder sehr kurz. Es konstruiert nur
ein Objekt der gerade definierten Klasse der grafischen Oberlfläche und verschwindet in einer Endlos-
Schleife. Diese wird über den Ende-Button verlassen. That’s it!

Beispiel 22.3.3 Aufruf des Fensters


#!/usr/bin/python
# -*- coding: utf-8 -*-
from cl_Gui import *
import tkMessageBox

def callback():
if [Link](’Quit’, ’Wirklich aufhören?’):
[Link]()

if __name__ == "__main__":
root = Tk()
meineTemp = App(root)
[Link](’WM_DELETE_WINDOW’, callback)
[Link]()

Eine nette Kleinigkeit wurde noch eingebaut: ein Zusatzrahmen öffnet sich, wenn man das Programm
beenden will. Dort wird man gefragt, ob man wirklich aufhören will (es geht auch ohne, und dann ist
das Hauptprogramm nochmal 4 Zeilen kürzer).
Das aufgerufene Programm präsentiert sich so:

Abbildung 22.3. Temperaturprogramm

Und das oben erwähnte Zusatzfenster, mit dem man das Programm endgültig beendet, erscheint so:

359
KAPITEL 22. PROGRAMME MIT . . . 22.3. . . . UND JETZT MIT GRAFISCHER . . .

Abbildung 22.4. Beendigung des Temperaturprogramms

360
Teil XI.

Python für Verwaltungsaufgaben

361
23. Python als Sprache für den eigenen
Rechner
23.1. Das Betriebssystem
Für die Arbeit mit dem eigenen Rechner ist Python auch sehr gut geeignet. Man erinnere sich: Batteries
included! Es gibt für alle Betriebssysteme Bibliotheken, die Aufrufe an das Betriebssystem erleichtern.
Das erste Modul ist das sys. Rein ins Vergnügen!
Also gehen wir auf die Python-Shell oder in eine IDE unserer Wahl und geben die Befehle import sys
gefolgt von dir(sys) ein. Jede Menge Informationen können vom Modul sys geliefert werden. Probieren
wir es also aus:

Beispiel 23.1.1 Versuche mit sys


1

2 >>> import sys


3 >>>
4 >>> print([Link])
5 linux2
6 >>> print([Link])
7 3.4.6 (default, Mar 22 2017, 12:26:13) [GCC]
8 >>> print([Link])
9 Copyright (c) 2001-2017 Python Software Foundation.
10 All Rights Reserved.
11

12 Copyright (c) 2000 [Link].


13 All Rights Reserved.
14

15 Copyright (c) 1995-2001 Corporation for National Research Initiatives.


16 All Rights Reserved.
17

18 Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam.


19 All Rights Reserved.
20

Hier wurde das Betriebssystem, die Versionsnummer von Python und die Copyrights für Python
ausgegeben.
Das ist hilfreich, wenn man ein Programm schreibt, von dem man vermutet, dass es auf verschiedenen
Rechnern unter verschiedenen Betriebssystemen laufen soll.

Beispiel 23.1.2 Abfrage des Betriebssystems


1

2 >>> import sys


3 >>> if [Link][:5] == ’linux’:
4 print(’Da hast Du aber Glück gehabt! Hier funktioniert fast alles!’)
5 elif [Link][:3] == ’win’:
6 print(’Na, trotzdem viel Glück!’)
7 else:
8 print(’Exot! Wird schon tun’)
9 Da hast Du aber Glück gehabt! Hier funktioniert fast alles!
10

363
KAPITEL 23. PYTHON ALS SPRACHE FÜR . . . 23.2. VERZEICHNISSE UND DATEIEN

Nicht schlecht. Aber seit einem der vorigen Kapitel wissen wir, dass durchaus noch mehr Informatio-
nen über einen Modul abgefragt werden können, nämlich mit help(sys). Eine Inhaltsangabe des Moduls
sys erhält man durch

Beispiel 23.1.3 Hilfe zum Modul sys


1

2 >>> dir(sys)
3 [’__displayhook__’, ’__doc__’, ’__egginsert’, ’__excepthook__’,
4 ’__interactivehook__’, ’__loader__’, ’__name__’, ’__package__’, ’__plen’,
5 ’__spec__’, ’__stderr__’, ’__stdin__’, ’__stdout__’, ’_clear_type_cache’,
6 ’_current_frames’, ’_debugmallocstats’, ’_getframe’, ’_home’, ’_mercurial’,
7 ’_xoptions’, ’abiflags’, ’api_version’, ’arch’, ’argv’, ’base_exec_prefix’,
8 ’base_prefix’, ’builtin_module_names’, ’byteorder’, ’call_tracing’,
9 ’callstats’, ’copyright’, ’displayhook’, ’dont_write_bytecode’,
10 ’exc_info’, ’excepthook’, ’exec_prefix’, ’executable’, ’exit’, ’flags’,
11 ’float_info’, ’float_repr_style’, ’getallocatedblocks’, ’getcheckinterval’,
12 ’getdefaultencoding’, ’getdlopenflags’, ’getfilesystemencoding’, ’getprofile’,
13 ’getrecursionlimit’, ’getrefcount’, ’getsizeof’, ’getswitchinterval’,
14 ’gettrace’, ’hash_info’, ’hexversion’, ’implementation’, ’int_info’,
15 ’intern’, ’last_traceback’, ’last_type’, ’last_value’, ’lib’, ’maxsize’,
16 ’maxunicode’, ’meta_path’, ’modules’, ’path’, ’path_hooks’,
17 ’path_importer_cache’, ’platform’, ’prefix’, ’setcheckinterval’,
18 ’setdlopenflags’, ’setprofile’, ’setrecursionlimit’, ’setswitchinterval’,
19 ’settrace’, ’stderr’, ’stdin’, ’stdout’, ’thread_info’, ’version’,
20 ’version_info’, ’warnoptions’]
21

Was ist denn die Standard-Kodierung für Dateien in unserem System?

Beispiel 23.1.4 Standardkodierung abfragen


>>> [Link]()
’UTF-8’

23.2. Verzeichnisse und Dateien

23.2.1. Die Grundlagen


Wie schon weiter oben gesehen, besteht die Arbeit mit Dateien aus 3 Schritten:

1. Öffnen der Datei


2. Arbeiten in der Datei
3. Schließen der Datei

Beim Öffnen musste man bereits angeben, was man mit der Datei machen will: Lesen oder Schreiben.
Python hat sich seit den Anfängen enorm weiterentwickelt, und deswegen gibt es in Python jetzt
Iteratoren“, das heißt Methoden, die über eine Datei schleifen. Das erleichtert die Arbeit mit Dateien.

Dabei wird eine Datei als eine Liste von Zeilen gesehen, die man mit einer for-Schleife abarbeiten kann.
Python verwaltet die Struktur selbständig.
Die einfachste Möglichkeit ist dabei,

364
KAPITEL 23. PYTHON ALS SPRACHE FÜR . . . 23.2. VERZEICHNISSE UND DATEIEN

Beispiel 23.2.1 Bearbeiten einer Datei mit Iterator


1

2 >>> datei = open(’[Link]’, ’r’)


3 >>> for zeile in datei:
4 print(zeile)
5 das
6 sind
7 alle
8 Zeilen
9 >>> [Link]()
10

Python stellt aber noch weitere Iteratoren zur Verfügung. Mit readline wird eine Zeile nach der an-
deren gelesen. Am Ende der Datei wird von der Methode readline eine leere Zeichenkette zurückgegeben.
Das ist für die Weiterverarbeitung unter Umständen ein kleines Problem, aber es funktioniert.

Beispiel 23.2.2 Zeilenweises Lesen einer Datei mit Iterator


>>> datei = open(’[Link]’, ’r’)
>>> print([Link]())
das
>>> print([Link]())
sind
>>> print([Link]())
alle
>>> print([Link]())
Zeilen
>>> print([Link]())

>>> [Link]()

Als letzte Möglichkeit gibt es noch den Iterator next. Der arbeitet sehr ähnlich wie readline, der
Unterschied ist, dass am Dateiende eine Exception auftritt.

Beispiel 23.2.3 Zeilenweises Lesen einer Datei mit Iterator


1

2 >>> datei = open(’[Link]’, ’r’)


3 >>> print([Link]())
4 das
5 >>> print([Link]())
6 sind
7 >>> print([Link]())
8 alle
9 >>> print([Link]())
10 Zeilen
11 >>> print([Link]())
12 Traceback (most recent call last):
13 File "<pyshell#69>", line 1, in <module>
14 print([Link]())
15 StopIteration
16 >>> [Link]()
17

Hier sieht man in den letzten Zeilen, dass Python am Dateiende auf einen Fehler läuft.

365
KAPITEL 23. PYTHON ALS SPRACHE FÜR . . . 23.2. VERZEICHNISSE UND DATEIEN

23.2.2. Das Modul os

Das zweite Modul, das mit dem Betriebssystem interagiert, ist das Modul os. Dieses Modul enthält für
fast alle gängigen Betriebssysteme Systemaufrufe, so dass Skripte, die dieses Modul benutzen, oft un-
verändert auf verschiedenen Systemen funktionieren. Schauen wir also auch hier einmal rein, indem wir
zuerst mit import os das Modul importieren und dann mit dir(os) uns den Inhalt des Moduls anzeigen
lassen.

Wichtige Befehle im Zusammenhang mit jedem Betriebssystem sind solche, die sich mit dem Ver-
zeichnisbaum beschäftigen. Zuerst lasse ich das aktuelle Verzeichnis anzeigen, danach wechsele ich im
Verzeichnisbaum eine Stufe hinauf:

Beispiel 23.2.4 Aktuelles Verzeichnis und Verzeichniswechsel (Unix)


1

2 >>> import os
3 >>> [Link]()
4 ’/home/martin/texte’
5 >>> [Link](’./texte’)
6 ’/home/fmartin/texte’
7 >>> [Link](’..’)
8 >>> [Link]()
9 ’/home/martin’
10

Interessant dabei ist [Link]: dieser Befehl wandelt eine relative Pfad-Angabe in einen
absoluten Pfad um.

Im vorigen Absatz sind die Ausgaben auf einem typischen Unix(Linux)-Rechner zu sehen. Unter
Windows sähe das vielleicht so aus:

Beispiel 23.2.5 Aktuelles Verzeichnis und Verzeichniswechsel (Windows)


1

2 >>> import os
3 >>> [Link]()
4 ’c:\\home\\martin\\texte’
5 >>> [Link](’..’)
6 >>> [Link]()
7 ’c:\\home\\martin’
8

Interessant an dem Modul os ist, dass man auch aus Python heraus damit Befehle des Betriebssystems
aufrufen kann. Dazu dient die Methode system. Ich lasse also hier einmal alle Dateien des aktuellen
Verzeichnisses ausgeben. Unter Linux dient dazu der Befehl ls, um eine ausführliche Darstellung zu
erhalten in der Variante ls -lsia

366
KAPITEL 23. PYTHON ALS SPRACHE FÜR . . . 23.3. AUFRUF VON PROGRAMMEN

Beispiel 23.2.6 Dateien des aktuellen Verzeichnisses


>>> import os
>>> [Link](’ls’)
[Link] [Link] [Link] [Link] [Link] [Link]
[Link]
0
>>> [Link](’ls -lsia’)
insgesamt 2900
1867970 4 drwxr-xr-x 2 fmartin users 4096 26. Aug 17:35 .
1867903 4 drwxr-xr-x 5 fmartin users 4096 26. Aug 17:32 ..
1841285 152 -rw-r--r-- 1 fmartin users 155404 26. Aug 17:35 [Link]
1864164 2228 -rw-r--r-- 1 fmartin users 2280472 26. Aug 17:35 [Link]
1864159 132 -rw-r--r-- 1 fmartin users 135013 26. Aug 17:33 [Link]
1864161 88 -rw-r--r-- 1 fmartin users 86937 26. Aug 17:34 [Link]
1864165 84 -rw-r--r-- 1 fmartin users 84142 26. Aug 17:35 [Link]
1864160 24 -rw-r--r-- 1 fmartin users 22257 26. Aug 17:34 [Link]
1864162 184 -rw-r--r-- 1 fmartin users 186444 26. Aug 17:35 [Link]
0

Im vorletzten Beispiel habe ich die unterschiedliche Darstellung des Verzeichnisbaumes unter Unix
und Windows gezeigt. Während unter Unix (und allen Abkömmlingen) das Trennzeichen zwischen
Verzeichnissen oder zwischen Verzeichnis und Datei der einfache Slash / ist, benutzt Windows den
Backslash \. Leider schert Windows nicht nur bei diesem Trennzeichen aus der Reihe, sondern auch bei
anderen Elementen des Verzeichnisbaums und der Darstellung von Dateinamen. Wenn man mit Hilfe
eines Programms also auf Datei- und Verzeichnisebene arbeiten und sein Programm portabel halten
will, muss man beide (oder vielleicht noch mehr?) Möglichkeiten berücksichtigen. Auch hier hilft das
Modul os: es kennt die Variablen

• sep für das Trennzeichen zwischen Verzeichnissen,


• pardir für das übergeordnete Verzeichnis (parent directory)
• curdir für das aktuelle Verzeichnis (current directory)

Ein interessanter Ast des Moduls os ist [Link]. Hierin sind Attribute und Methoden enthalten,
die sich mit dem Dateipfad innerhalb des Verzeichnisbaumes beschäftigen. Als Beispiel benutze ich die
Methoden basename und dirname, die einen voll-qualifizierten Dateinamen in den Verzeichnis- und
den Datei-Teil zerlegen:

Beispiel 23.2.7 Verzeichnisname und Dateiname


1

2 >>> import os
3 >>> dateiVollQualifiziert = ’/home/martin/texte/PythonBuch/XML/[Link]’
4 >>> [Link](dateiVollQualifiziert)
5 ’/home/fmartin/texte/PythonBuch/XML’
6 >>> [Link](dateiVollQualifiziert)
7 ’[Link]’
8

23.3. Aufruf von Programmen


Für Windows-Benutzer ist es ungewöhnlich, für alle anderen der Normalfall: ein Programm wird mit
Parametern aufgerufen. Wir haben das für den Fall von Unterprogrammen, in Python Funktionen ge-
nannt, schon weiter oben bei Funktionen und Parameter kennengelernt. Auch ein Programm kann mit
Parametern aufgerufen werden. Im vorigen Kapitel wurde das Betriebssystem-Programm ls aufgerufen.
Es zeigt ohne Parameter alle Dateien eines Verzeichnisses an:

367
KAPITEL 23. PYTHON ALS SPRACHE FÜR . . . 23.3. AUFRUF VON PROGRAMMEN

Beispiel 23.3.1 Dateien eines Verzeichnisses


1

2 martin@mas-Oberndorf:˜/public_html> ls
3 [Link]
4 [Link]
5 [Link]
6 [Link]
7 [Link]
8

Hier wurde der Unix-Befehl ls benutzt. Unter Windows lautet der entsprechende Befehl dir.
Wenn ich nur die HTML-Dateien, also die, deren Dateiendung .html lautet, angezeigt haben will,
muss ich dem Programm ls diese Information als Parameter mitgeben:

Beispiel 23.3.2 HTML-Dateien eines Verzeichnisses


1

2 martin@mas-Oberndorf:˜/public_html> ls *.html
3 [Link]
4 [Link]
5 [Link]
6

Das ist natürlich auch bei einem Python-Programm möglich, das man auf der Shell (oder für Windows-
Benutzer: in der Eingabeaufforderung) startet. Kurz nachgedacht: da spielt Python doch zusammen mit
dem jeweiligen Betriebssystem! Also benötigt man wieder das Modul sys!
Das folgende Programm, von mir [Link] genannt, begrüßt alle“, wenn es

ohne Parameter aufgerufen wird, und eine einzelne Person, wenn der Name einer einzelnen Person als
Paramter mitgegeben wird:

Beispiel 23.3.3 Programm (mit oder ohne Parameter)


#!/usr/bin/python
# -*- coding: utf8 -*-
import sys

if len([Link]) > 1:
print(’Hallo ’+[Link][1])
else:
print(’Hallo alle!!’)

Ob ein Parameter mitgegeben wird oder nicht, wird mit Hilfe der Länge der Parameterliste überprüft;
dabei ist wichtig zu wissen, dass jedes Programm immer einen Parameter erhält, nämlich den eige-
nen Programmnamen. Erst wenn die Länge der Liste länger als eins ist, wird ein echter“ Parameter

übergeben. Hier kommt als Nachweis, dass das richtig funktioniert, die Ausgabe des Programms bei
zwei Aufrufen:

Beispiel 23.3.4 Programm-Auruf mit oder ohne Parameter


martin@mas-Oberndorf:˜/bin/python/SystemTools> ./[Link]
Hallo alle!!
martin@mas-Oberndorf:˜/bin/python/SystemTools> ./[Link] Martin
Hallo Martin

368
KAPITEL 23. PYTHON ALS SPRACHE FÜR . . . 23.4. WEITER MIT VERZEICHNISSEN: DAS . . .

Nach dem, was wir weiter oben über Fehlerbehandlung gesagt haben, geht das auch ein bißchen
eleganter:

Beispiel 23.3.5 Programm (mit oder ohne Parameter) und Fehlerbehandlung


#!/usr/bin/python
# -*- coding: utf8 -*-
import sys

try:
print(’Hallo ’+[Link][1])
except:
print(’Hallo alle!!’)

Und die Ausgabe sieht genau wie oben aus.


Beide Module, sys und os, will ich jetzt einmal benutzen, um ein Tool zu schreiben, das mir die Um-
gebungsvariablen (das environment“) eines Programms anzeigt. Das brauche ich dringend, denn ich

kann mir das nicht alles merken, vor allem, wenn ich an verschiedenen Rechnern unter verschiedenen
Betriebssystemen arbeite. Dabei will ich manchmal auch nicht alle Umgebungsvariablen ausgegeben
haben, sondern nur den Wert einer Umgebungsvariablen.
Dazu benutze ich

• die Möglichkeit, Parameter an das Programm zu übergeben


• die Fehlerbehandlung mit try - except, falls keine Parameter übergeben werden
• eine Schleife über die Parameter, falls keine Parameter übergeben werden

Das Programm sieht so aus:

Beispiel 23.3.6 Umgebungs-Variable


1

2 #!/usr/bin/python
3 # -*- coding: utf-8 -*-
4 import os, sys
5

6 if len([Link]) > 1:
7 for einArg in [Link][1:]:
8 try:
9 print(einArg, ’\t\t\t==>’, [Link][einArg])
10 except:
11 print(einArg+’ ist keine gültige Umgebungsvariable’)
12 else:
13 for k in [Link]:
14 print(k,’\t\t\t==>’, [Link][k])
15

23.4. Weiter mit Verzeichnissen: das Modul glob


Ein weiteres Modul im Zusammenhang mit Verzeichnissen und den Dateien darin ist glob. Der Na-
me leitet sich her von den Jokern, die es in jedem Betriebssystem gibt und die ihre Anwendung beim
Durchsuchen von Dateibäumen haben. Sie stehen als Platzhalter nicht nur für eine Datei, sondern glo-

balisieren“, das heißt, dass sie ein Muster beschreiben, das auf viele Dateien zutrifft. Ein Beispiel ist ein
paar Absätze weiter oben zu sehen.
Das glob-Objekt besitzt eine Methode glob, die Datei- und Verzeichnisnamen mit Platzhaltern verar-
beiten kann. Lassen wir also mal alle Dateien ausgeben, die als Dateiendung .txt haben.

369
KAPITEL 23. PYTHON ALS SPRACHE FÜR . . . 23.5. DAS MODUL SUBPROCESS

Beispiel 23.4.1 globbing einfach


>>> [Link](’*.txt’)
[’[Link]’, ’[Link]’, ’[Link]’]

und schöner:

Beispiel 23.4.2 globbing einfach


>>> for eineDatei in [Link](’*.txt’):
... print(eineDatei)
...
[Link]
[Link]
[Link]

23.5. Das Modul subprocess


Das Modul subprocess erzeugt einen neuen Unterprozess. Vorteil gegenüber dem Starten mittels
[Link]() ist, dass man diesen Prozess gut behandeln kann. Hier soll das gezeigt werden anhand
einer Diashow:

Beispiel 23.5.1 Diashow mit subprocess


#!/usr/bin/python

import subprocess
import os
from time import sleep

verzeichnis = input(’Welches Verzeichnis? ’)

import glob
bildListe = [Link](verzeichnis+’/*.jpg’)
for bild in bildListe:
x = [Link]([’xv’, bild])
sleep(5)
[Link]("kill " + str([Link]))

Zum Anzeigen der einzelnen Bilder wird hier das Programm xv benutzt. Wem das nicht gefällt, der
kann das einfach ändern. Außerdem ist fest verdrahtet, dass nur Dateien mit der Endung jpg (klein
geschrieben) angezeigt werden.

23.6. Das Modul shutil


Das Modul shutil enthält viele Funktionen, die das Arbeiten mit Dateien und Verzeichnissen verein-
fachen. Als Beispiele seien genannt:

• [Link](alt, neu), das eine Datei kopiert

• [Link](alt, neu)das einen Dateibaum kopiert

• [Link](alt, neu)das eine Datei verschiebt

370
KAPITEL 23. PYTHON ALS SPRACHE FÜR . . . 23.7. DAS MODUL [Link]

• [Link] archive(base name, format, root dir=None, base dir=None, ...) das
eine Archiv erzeugt

23.7. Das Modul [Link]


Wie man am Modulnamen sieht, ist [Link] ein Teil von os. walk geht durch einen Verzeichnisbaum.
Der Aufruf des Walkers“ geschieht (in der alten Version) durch

[Link](Startverzeichnis, Auflist-Funktion, Dateiliste)

Dabei kann die Auflist-Funktion eine selbst geschriebene Funktion sein, im einfachsten Fall kann es
auch die betriebssystem-interne Funktion (unter Unix / Linux: ls) sein. Die Dateiliste ist im Normalfall
None, also die leere Liste. Das sieht so aus:

Beispiel 23.7.1 Walker (alte Version)


for dat in [Link](’./2016-17’, ’ls ’, None):
print(dat)

(’./2016-17’, [’BFW2-M’, ’IFOE-M’, ’BKFH-M’], [’[Link]’])


(’./2016-17/BFW2-M’, [], [’[Link]’, ’[Link]’, ’ue_004.pdf’,
’ue_001.pdf’, ’ue_005.tex’, ’ue_003.pdf’, ’ka_01.tex’, ’ue_004.tex’,
’ue_001.tex’, ’ue_000.tex’, ’ka_03.tex’, ’ka_01.pdf’, ’ka_02.tex’,
’[Link]’, ’[Link]’, ’ka_04.tex’, ’ka_02.pdf’, ’nka_01.tex’,
’ue_006.tex’, ’nka_04.tex’, ’[Link]’, ’nka_04.pdf’, ’ue_006.pdf’,
’ka_05.tex’, ’ka_00.tex’, ’ka_05.pdf’, ’ka_03.pdf’, ’ue_003.tex’,
’[Link]’, ’ue_005.pdf’, ’ue_002.tex’, ’ue_002.pdf’,
’Zweitkorr_2BFW2-[Link]’, ’nka_01.pdf’, ’ka_04.pdf’])
... und noch einige Zeilen mehr

In der neuen Version ist [Link] ein Generator. Das bedeutet, dass eine Auflist-Funktion nicht mehr
als zweiter Parameter angegeben sein muss. Das sieht so aus:

Beispiel 23.7.2 Walker (neue Version)


for root, dirs, files in [Link](’./2016-17’):
for datei in files:
print(datei)

[Link]
[Link]
[Link]
ue_004.pdf
ue_001.pdf
ue_005.tex
ue_003.pdf
ka_01.tex
ue_004.tex
ue_001.tex

Wenn man die vollständigen Angaben, das heißt Pfadnamen plus Dateinamen ausgeben möchte, setzt
man des vollständigen Dateinamen mit Hilfe von [Link] zusammen.

371
KAPITEL 23. PYTHON ALS SPRACHE FÜR . . . 23.7. DAS MODUL [Link]

Beispiel 23.7.3 Walk mit Ausgabe des vollständigen Dateinamen


>>> import os
>>> texte = [Link](’./2017-18’)
>>> for dirPfad, dirNamen, datNamen in texte:
... for datN in datNamen:
... print([Link](dirPfad,datN))
...
./2017-18/Rueckmeldung_Fehlzeiten_Serienbrief_123.docx
./2017-18/[Link]
./2017-18/[Link]
./2017-18/BK1-3INF/ka_01.aux
./2017-18/BK1-3INF/ka_01.tex
... etc.

372
Teil XII.

Texte für Fortgeschrittene

373
24. Texte bearbeiten für Fortgeschrittene
24.1. Natural Language Toolkit (NLTK)
NLTK wird eingebunden durch

Beispiel 24.1.1 Import von NLTK


import nltk

Trennen eines Textes in Sätze:

Beispiel 24.1.2 Text in Sätze aufspalten


>>> from [Link] import sent_tokenize
>>> text = ’Hallo, Welt. Schön, dass Du auch da bist!
Wenigstens ist heute mit dem 12.12.2016 ein schönes Datum’
>>> sent_tokenize(text, language=’german’)
[’Hallo, Welt.’, ’Schön, dass Du auch da bist!’,
’Wenigstens ist heute mit dem 12.12.2016 ein schönes Datum’]

sent tokenize steht für sentence tokenize


Trennen eines Textes in einzelne Wörter:

Beispiel 24.1.3 Text in einzelne Wörter aufspalten


>>> from [Link] import word_tokenize
>>> word_tokenize(text, language=’german’)
[’Hallo’, ’,’, ’Welt’, ’.’, ’Schön’, ’,’, ’dass’, ’Du’, ’auch’, ’da’, ’bist’, ’!’,
’Wenigstens’, ’ist’, ’heute’, ’mit’, ’dem’, ’12.12.2016’, ’ein’, ’schönes’, ’Datum’]

Beachte:

1. Auch ein Satzzeichen ist ein Wort.


2. Ein Datum ist ein Wort, Punkte nach Tag und Jahr sind keine Satzzeichen.

Stopwörter (stopwords) sind Füllwörter, d.h. Wörter, die sehr häufig vorkommen, aber für den Inhalt
des Textes von untergeordneter Bedeutung sind, im Deutschen z.B. die Wörter ist, sind, hat, ein, der,
die, das. Diese Wörter bei der Untersuchung auszuschließen geht so:

375
KAPITEL 24. TEXTE BEARBEITEN FÜR . . . 24.1. NATURAL LANGUAGE TOOLKIT (NLTK)

Beispiel 24.1.4 Stopwörter ausschließen


>>> from [Link] import stopwords
>>> dt_Stopwoerter = set([Link](’german’))
>>> [wort for wort in word_tokenize(text, language=’german’)
if wort not in dt_Stopwoerter]

[’Hallo’, ’,’, ’Welt’, ’.’, ’Schön’, ’,’, ’dass’, ’Du’, ’!’,


gre’Wenigstens’, ’heute’, ’12.12.2016’, ’schönes’, ’Datum’]

Separieren des Wortstammes eines Wortes (Stemming). Für die deutsche Sprache benutze

Beispiel 24.1.5 Import des deutschen NLTK-Stemmers


>>> from [Link] import GermanStemmer

Aufruf:

Beispiel 24.1.6 Suche den Wortstamm einiger Wörter


>>> meinStemmer = GermanStemmer()
>>> [Link](’Untersuchung’)
’untersuch’
>>> [Link](’untersuchen’)
’untersuch’
>>> [Link](’Ableitung’)
’ableit’

376
Teil XIII.

Mathematik (Forts.)

377
25. Mathematik (Forts.)
25.1. Das Paket numpy
numpy ist ein Paket für numerische Mathematik. Speziell beherrscht numpy Matrizen, und das soll hier
als erstes demonstriert werden. Vieles davon ist (vor allem für Mathematiker) selbsterklärend.
Die Komponenten von numpy sind in der Sprache C geschrieben. C ist eine kompilierte Sprache, und
damit sind die Komponenten von numpy sehr effektiv und von der Laufzeit her sehr schnell.
Ein kleiner Tip am Rande: auch wenn ich empfehle, immer zuerst die Hilfefunktion eines Moduls
aufzurufen, wenn man ihn zum ersten Mal benutzt: bei numpy ist das ein zweifelhaftes Vergnügen: der
Hilfetext ist 91000 Zeilen lang!

25.1.1. Matrizen
Eine große Stärke von numpy ist die Bearbeitung von Matrizen. Für den Mathematiker ist der Begriff
der Matrix bekannt. Für den Python-Programmierer ist eine Matrix eine Liste von Listen - solange, bis
er numpy kennenlernt. Und danach denkt er sich: Aha, eine Liste ist also eine (1 x n)-Matrix, eine Matrix
mit einer Zeile und n Spalten.
Weil ich gerade so schön schwitze, nehme ich mir als erstes Beispiel einmal die Temperaturen (in Grad
Celsius) in Tübingen der letzten 15 Tage vor (Juli 2019). Also rein damit in eine Liste (denn noch kenne
ich numpy nicht): tempCels = [18, 20, 21, 21, 23, 25, 26, 28, 27, 32, 27, 30, 33,
35, 37] Jetzt sollen diese Temperaturen in Grad Fahrenheit umgerechnet werden. Dazu schreibe ich
eine Funktion cels2fahr.

Beispiel 25.1.1 Funktion Celsius nach Fahrenheit


>>> def cels2fahr(g):
f = g * 9 / 5 + 32
return f

Und jetzt muss ich in einer Schleife jede Temperatur aus der Liste nehmen, die Funktion darauf los-
lassen und das zurückgelieferte Ergebnis in eine neue Liste schreiben.

Beispiel 25.1.2 Anwendung Funktion Celsius nach Fahrenheit


>>> tempFahr = []
>>> for temp in tempCels:
[Link](cels2fahr(temp))

>>> print(tempFahr)
[64.4, 68.0, 69.8, 69.8, 73.4, 77.0, 78.8, 82.4,
80.6, 89.6, 80.6, 86.0, 91.4, 95.0, 98.6]

Das, was ich im letzten Satz des vorigen Absatzes geschrieben habe, kann durch die Verwendung
von numpy vereinfacht werden; das geschieht dadurch, dass die Liste in eine eindimensionale Ma-
trix umgewandelt wird. Diese eindimensionale Matrix, eine Instanz der Klasse ndarray (das steht
für n-dimensionales Array, also n-dimensionale Matrix), wird erzeugt durch die Methode array und
überlädt die Standard-Operatoren und ermöglicht es damit auch, dass an eine Funktion ein Objekt die-
ser Klasse übergeben wird.

379
KAPITEL 25. MATHEMATIK (FORTS.) 25.1. DAS PAKET NUMPY

Beispiel 25.1.3 das selbe mit NumPy


>>> import numpy as np
>>> tempNP = [Link](tempCels)
>>> cels2fahr(tempNP)
array([64.4, 68. , 69.8, 69.8, 73.4, 77. , 78.8, 82.4, 80.6, 89.6, 80.6,
86. , 91.4, 95. , 98.6])

Es ist ein Standard in der Python-Welt, numpy wie in der ersten Zeile zu importieren.

[Link]. Erzeugung von Matrizen

Matrizen kann man mit numpy auf verschiedene Weisen erstellen; das umfasst auch das Erzeugen von
speziellen Matrizen.

1. Indem man ein array anlegt durch Angabe der Matrix-Werte. Hier wird eine (3 x 4)-Matrix und
eine (4 x 2)-Matrix angelegt und danach angezeigt.

Beispiel 25.1.4 Matrizen anlegen mit array


import numpy as np
a1 = [Link]([[1,2,1,2],[0,1,0,-1],[2,3,-3,-2]])
a2 = [Link]([[0,2],[3,1],[2,0],[1,1]])
## Darstellung
>>> a1
array([[ 1, 2, 1, 2],
[ 0, 1, 0, -1],
[ 2, 3, -3, -2]])
>>> a2
array([[0, 2],
[3, 1],
[2, 0],
[1, 1]])

Das Format einer Matrix sollte natürlich auch ausgegeben werden können.

Beispiel 25.1.5 Format einer Matrix


>>> [Link]
(3, 4)
>>> [Link]
(4, 2)

Die Matrix a1 hat 3 Zeilen und 4 Spalten.

2. matrix ist eine Unterklasse von array, mit der nur maximal zweidimensionale Felder erzeugt
werden können.

380
KAPITEL 25. MATHEMATIK (FORTS.) 25.1. DAS PAKET NUMPY

Beispiel 25.1.6 Matrixen mit matrix


>>> m1 = [Link]([[1,0],[0,1]])
>>> m1
matrix([[1, 0],
[0, 1]])
>>> m2 = [Link]([[1,0]])
>>> m2
matrix([[1, 0]])

Für Objekte der Klasse matrix sind alle Rechenoperationen definiert, die man aus der Oberstufe
des Gymnasiums oder aus der Vorlesung Lineare Algebra 1“ kennt.

3. Mit array können auch drei- (oder höher-)dimensionale Felder angelegt werden. Ein zweidimen-
sionales Feld besitzt eine Länge und eine Breite; ein dreidimensionales Feld besitzt eine Länge, eine
Breite und eine Höhe. Gut darstellen ließe sich das durch einen Quader, aber nicht hier auf Papier

Beispiel 25.1.7 Dreidimensionales Feld


>>> dreiDimMatrix = [Link]([[[1,1,1],[2,2,2],[3,3,3]],
[[4,4,4],[5,5,5],[6,6,6]],
[[7,7,7],[8,8,8],[9,9,9]]]
)
>>> print(dreiDimMatrix)
[[[1 1 1]
[2 2 2]
[3 3 3]]

[[4 4 4]
[5 5 5]
[6 6 6]]

[[7 7 7]
[8 8 8]
[9 9 9]]]
>>> print([Link])
(3, 3, 3)

4. Im Gegensatz zu array erlaubt die Klasse Matrix


5. Dabei kann man den Datentyp der Elemente angeben.

381
KAPITEL 25. MATHEMATIK (FORTS.) 25.1. DAS PAKET NUMPY

Beispiel 25.1.8 Matrizen anlegen mit vorgegebenem Datentyp


import numpy as np
a1 = [Link]([[1,2,1,2],[0,1,0,-1],[2,3,-3,-2]], dtype = float)
a2 = [Link]([[0,2],[3,1],[2,0],[1,1]], dtype = complex)
## Darstellung
>>> a1

array([[ 1., 2., 1., 2.],


[ 0., 1., 0., -1.],
[ 2., 3., -3., -2.]])
>>> a2

array([[0.+0.j, 2.+0.j],
[3.+0.j, 1.+0.j],
[2.+0.j, 0.+0.j],
[1.+0.j, 1.+0.j]])

Alles klar, oder?


6. Eine Matrix kann erzeugt werden, indem man einen Datenbereich angibt. Auch das ist schon von
range bei der Arbeit mit Zählschleifen bekannt.

Beispiel 25.1.9 Bereiche bei der Erzeugung von Matrizen


>>> m1 = [Link](16)
>>> m1

array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])

>>> m2 = [Link](4,20)
>>> m2

array([ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])

>>> m3 = [Link](1,23, 3)
>>> m3

array([ 1, 4, 7, 10, 13, 16, 19, 22])

7. Eine Einheitsmatrix ist eine quadratische Matrix, in der die Elemente der Hauptdiagonalen (der
Diagonalen von links oben nach rechts unten) den Wert 1 haben, alle anderen Elemente den Wert
0. Eine Möglichkeit, sie zu erzeugen, ist die Methode identity. Sie benötigt als Parameter die
Anzahl der Zeilen.

382
KAPITEL 25. MATHEMATIK (FORTS.) 25.1. DAS PAKET NUMPY

Beispiel 25.1.10 Einheitsmatrix der Größe 5


>>> einhMatr5 = [Link](5)

>>> print(einhMatr5)

[[1. 0. 0. 0. 0.]
[0. 1. 0. 0. 0.]
[0. 0. 1. 0. 0.]
[0. 0. 0. 1. 0.]
[0. 0. 0. 0. 1.]]

identity kann auch einen Datentyp als Parameter erhalten. Eine Einheitsmatrix mit ganzen Zah-
len folgt:

Beispiel 25.1.11 Einheitsmatrix der Größe 5 mit ganzen Zahlen


>>> einhMatr5 = [Link](5, dtype=int)

>>> print(einhMatr5)

[[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]]

Eine zweite Möglichkeit, Einheitsmatrizen zu erzeugen, ist die Methode eye. Auch sie benötigt
als Parameter die Anzahl der Zeilen:

Beispiel 25.1.12 Einheitsmatrix mit eye


>>> einhMatr5 = [Link](5, dtype=int)

>>> print(einhMatr5)

[[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]]

Und eye beherrscht auch, etwas ähnliches wie eine Einheitsmatrix zu bauen, die nicht quadratisch
ist. In diesem Fall benötigt eye zwei Parameter, nämlich die Anzahl der Zeilen und die Anzahl
der Spalten. Dabei muss angegeben werden, welche ”Diagonale”die Einsen enthalten soll. Die
Beschreibung ist lästig und sprachlich unschön, darum sollen 3 Beispiele genügen; in eine 3x7 -
Matrix wird die 0., die 2. und die (-2). Diagonale mit Einsen gefüllt:

383
KAPITEL 25. MATHEMATIK (FORTS.) 25.1. DAS PAKET NUMPY

Beispiel 25.1.13 Etwas ähnliches wie Einheitsmatrix


>>> matrix_3x7 = [Link](3,7, k=0)

>>> print(matrix_3x7)

[[1. 0. 0. 0. 0. 0. 0.]
[0. 1. 0. 0. 0. 0. 0.]
[0. 0. 1. 0. 0. 0. 0.]]
>>> matrix_3x7 = [Link](3,7, k=2)

>>> print(matrix_3x7)

[[0. 0. 1. 0. 0. 0. 0.]
[0. 0. 0. 1. 0. 0. 0.]
[0. 0. 0. 0. 1. 0. 0.]]
>>> matrix_3x7 = [Link](3,7, k=-2)

>>> print(matrix_3x7)

[[0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0.]
[1. 0. 0. 0. 0. 0. 0.]]

8. Eine Nullmatrix ist eine Matrix, die nur Nullen enthält, eine Einsmatrix enthält nur Einsen.

Beispiel 25.1.14 Nullmatrix und Einsmatrix


>>> nullM = [Link]((2,4), dtype=int)

>>> einsM = [Link]((2,5), dtype=int)

>>> print(nullM)

[[0 0 0 0]
[0 0 0 0]]
>>> print(einsM)

[[1 1 1 1 1]
[1 1 1 1 1]]

9. Eine Diagonalmatrix ist eine Matrix, die in der Hauptdiagonalen von 0 verschiedene Werte hat,
alle restlichen Elemente sind 0.

Beispiel 25.1.15 Diagonalmatrix


## Diagonalmatrix
>>> diagonalmatrix = [Link]([Link]([1,-1,1,-1]))
>>> diagonalmatrix
array([[ 1, 0, 0, 0],
[ 0, -1, 0, 0],
[ 0, 0, 1, 0],
[ 0, 0, 0, -1]])

384
KAPITEL 25. MATHEMATIK (FORTS.) 25.1. DAS PAKET NUMPY

[Link]. Matrizen umformen


1. Arrays können teilweise ausgegeben werden. Dabei funktioniert alles, was auch bei Listen funk-
tioniert. Speziell kann man durch Slicing beliebige Untermatrizen auswählen.

Beispiel 25.1.16 Matrizen slicen


>>> dm = [Link]([Link]([1,-2,3,-4]))

>>> print(dm)

[[ 1 0 0 0]
[ 0 -2 0 0]
[ 0 0 3 0]
[ 0 0 0 -4]]
>>> print(dm[:2,:2])

[[ 1 0]
[ 0 -2]]
>>> print(dm[:2,2:])

[[0 0]
[0 0]]
>>> print(dm[1:3,1:3])

[[-2 0]
[ 0 3]]
>>> print(dm[:2,3:])

[[0]
[0]]

2. Wie schon oben bei den Listen gezeigt kann auch eine Matrix umgekehrt werden.

Beispiel 25.1.17 Matrizenzeilen umkehren


import numpy as np
a1 = [Link]([[1,2,1,2],[0,1,0,-1],[2,3,-3,-2]])
>>> a1[::-1]
array([[ 2, 3, -3, -2],
[ 0, 1, 0, -1],
[ 1, 2, 1, 2]])

385
KAPITEL 25. MATHEMATIK (FORTS.) 25.1. DAS PAKET NUMPY

3. Das Format einer Matrix kann mit Hilfe der Methode arange verändert werden.

Beispiel 25.1.18 Format ändern


>>> m2 = [Link](16)
>>> m2

array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])


>>> m2

array([ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
>>> [Link](2,8)

array([[ 4, 5, 6, 7, 8, 9, 10, 11],


[12, 13, 14, 15, 16, 17, 18, 19]])
>>> m2

array([ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
>>> [Link](4,4)

array([[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19]])

4. Zwei oder mehr Matrizen können zusammengefasst werden durch die Methode concatenate.
Dabei müssen die entsprechenden Formate der Einzelmatrizen passen. Das heißt genau: wenn
ich die Matrizen in der Horizontalen zusammenfassen will, müssen sie in der Anzahl der Zeilen
übereinstimmen. Sollen die Matrizen in der Vertikalen zusammengefasst werden, müssen sie in
der Anzahl der Spalten übereinstimmen.

386
KAPITEL 25. MATHEMATIK (FORTS.) 25.1. DAS PAKET NUMPY

Beispiel 25.1.19 Zusammenfassung von Matrizen


>>> m1 = [Link](range(1,7))
>>> m1
array([1, 2, 3, 4, 5, 6])
>>> m1_2x3 = [Link](2,3)
>>> print(m1_2x3)
[[1 2 3]
[4 5 6]]

>>> m2 = [Link](range(11,17))
>>> m2_2x3 = [Link](2,3)
>>> print(m2_2x3)
[[11 12 13]
[14 15 16]]

>>> m3_hintereinander = [Link]((m1_2x3, m2_2x3), axis=1)


>>> print(m3_hintereinander)
[[ 1 2 3 11 12 13]
[ 4 5 6 14 15 16]]

>>> m4_untereinander = [Link]((m1_2x3, m2_2x3), axis=0)


>>> print(m4_untereinander)
[[ 1 2 3]
[ 4 5 6]
[11 12 13]
[14 15 16]]

>>> m5 = [Link](range(21,25))
>>> m5_2x2 = [Link](2,2)
>>> print(m5_2x2)
[[21 22]
[23 24]]

>>> m6_hintereinander = [Link]((m1_2x3,m5_2x2), axis = 1)


>>> print(m6_hintereinander)
[[ 1 2 3 21 22]
[ 4 5 6 23 24]]

[Link]. Elementare Zeilenumformungen

In der linearen Algebra wird eine Matrix oft umgeformt, um sie einer besser handhabbaren Form zu
bearbeiten. Das bedeutet oft, sie mit dem Gauss-Verfahren auf Zeilenstufenform zu bringen. Zulässige
Operationen dazu sind

1. Multiplikation einer Zeile mit einer Zahl

2. Addition der j-ten Zeile zur i-ten Zeile

3. Vertauschen von j-ter und i-ter Zeile

4. Addition des Vielfachen der j-ten Zeile zur i-ten Zeile

387
KAPITEL 25. MATHEMATIK (FORTS.) 25.1. DAS PAKET NUMPY

Beispiel 25.1.20 Elementare Zeilenumformungen


## an dieser Matrix werden die obigen Umformungen vorgenommen
>>> a1 = [Link]([[1,2,1,2],[0,1,0,-1],[2,3,-3,-2]])
>>> print(a1)

[[ 1 2 1 2]
[ 0 1 0 -1]
[ 2 3 -3 -2]]
## 1.) Multiplikation von Zeile 1 mit 5
>>> a_umf1 = [Link]([5*a1[0],a1[1],a1[2]])

>>> print(a_umf1)

[[ 5 10 5 10]
[ 0 1 0 -1]
## 2.) Addition von Zeile 2 zu Zeile 1 (Zeilen 2 und 3 bleiben unverändert)
>>> a_umf2 = [Link]([a1[0]+a1[1], a1[1], a1[2]])

>>> print(a_umf2)

[[ 1 3 1 1]
[ 0 1 0 -1]
[ 2 3 -3 -2]]
## 3.) Vertauschen von Zeile 2 und Zeile 3
>>> a_umf3 = [Link]([[a1[0], a1[2], a1[1]]])

>>> print(a_umf3)

[[[ 1 2 1 2]
[ 2 3 -3 -2]
[ 0 1 0 -1]]]
## 4.) Addition der negativen Hälfte von Zeile 3 zu Zeile 1
>>> a_umf4 = [Link]([a1[0]+(-0.5)*a1[2],a1[1],a1[2]])

>>> print(a_umf4)

[[ 0. 0.5 2.5 3. ]
[ 0. 1. 0. -1. ]
[ 2. 3. -3. -2. ]]

388
KAPITEL 25. MATHEMATIK (FORTS.) 25.1. DAS PAKET NUMPY

[Link]. Rechnen mit Matrizen


1. Die Addition von 2 Matrizen ist nur definiert für Matrizen des selben Formats. In diesem Fall
werden die Matrizen elementeweise addiert.

Beispiel 25.1.21 Addition von Matrizen


>>> m1 = [Link]([[1, 2, 3],
[4, 5, 6]])
>>> m1
matrix([[1, 2, 3],
[4, 5, 6]])
>>> m2 = [Link]([[11, 12, 13],
[14, 15, 16]])
>>> m2
matrix([[11, 12, 13],
[14, 15, 16]])
>>> print(m1 + m2)
[[12 14 16]
[18 20 22]]

2. Bei der Multiplikation von Matrizen wird zuerst das Skalarprodukt betrachtet. Das Skalarprodukt
zweier Vektoren (das sind (n x 1)-Matrizen) ist eine Zahl (ein Skalar). Voraussetzung dafür ist, dass
beide Vektoren die selbe Anzahl Zeilen haben.
In Python, genauer in numpy, wird das Skalarprodukt durch die Methode dot berechnet und ist
auch auf Matrizen anwendbar. Anders als in der Analytischen Geometrie in der Schule ist hier die
Voraussetzung, dass beide Vektoren Zeilenvektoren mit der selben Anzahl Elemente sind, oder
dass der erste Vektor ein Zeilenvektor und der zweite Vektor ein Spaltenvektor ist, wobei der erste
Vektor soviele Spalten haben muss wie der zweite Vektor Zeilen hat. Umständliche Erklärung,
oder? Also schau auf das Beispiel:

389
KAPITEL 25. MATHEMATIK (FORTS.) 25.1. DAS PAKET NUMPY

Beispiel 25.1.22 Skalarprodukt


### 1. Fall
>>> v1 = [Link]([1,-2,4])
>>> v1
array([ 1, -2, 4])

>>> v2 = [Link]([[1],[2],[0]])
>>> v2
array([[1],
[2],
[0]])
>>> print([Link](v1,v2))
[-3]

### 2. Fall
>>> v1 = [Link]([1,-2,4])
>>> v1
array([ 1, -2, 4])

>>> v2 = [Link]([1,2,0])
>>> v2
array([1, 2, 0])
>>> print([Link](v1,v2))
-3

### 3. Fall
>>> v1 = [Link]([[1],[-2],[4]])
>>> v1
array([[ 1],
[-2],
[ 4]])

>>> v2 = [Link]([1,2,0])
>>> v2
array([1, 2, 0])
>>> print([Link](v1,v2))

Traceback (most recent call last):


File "<pyshell#63>", line 1, in <module>
print([Link](v1,v2))
ValueError: shapes (3,1) and (3,) not aligned: 1 (dim 1) != 3 (dim 0)

### 4. Fall
>>> v1 = [Link]([[1],[-2],[4]])
>>> v1
array([[ 1],
[-2],
[ 4]])

>>> v2 = [Link]([[1],[2],[0]])
>>> v2
array([[1],
[2],
[0]])
>>> print([Link](v1,v2))

Traceback (most recent call last):


File "<pyshell#71>", line 1, in <module>
print([Link](v1,v2))
ValueError: shapes (3,1) and (3,1) not aligned: 1 (dim 1) != 3 (dim 0)
390
KAPITEL 25. MATHEMATIK (FORTS.) 25.1. DAS PAKET NUMPY

Wenn man die Vektoren als matrix definiert, sieht das ein wenig anders aus:

Beispiel 25.1.23 Skalarprodukt(?) mittels matrix


### 1. Fall: 2 Zeilenvektoren
>>> m3 = [Link]([2,-1,3])
>>> m3
matrix([[ 2, -1, 3]])
>>> m4 = [Link]([3,4,-1])
>>> m4
matrix([[ 3, 4, -1]])
>>> print([Link](m3,m4))
Traceback (most recent call last):
File "<pyshell#27>", line 1, in <module>
print([Link](m3,m4))
ValueError: shapes (1,3) and (1,3) not aligned: 3 (dim 1) != 1 (dim 0)

### 2. Fall: Zeilenvektor mal Spaltenvektor


>>> m4 = [Link]([[3],[4],[-1]])
>>>
>>> m4
matrix([[ 3],
[ 4],
[-1]])
>>> print([Link](m3,m4))
[[-1]]

### 3. Fall: Spaltenvektor mal Spaltenvektor


>>> m3 = [Link]([[2],[-1],[3]])
>>> print([Link](m3,m4))
Traceback (most recent call last):
File "<pyshell#33>", line 1, in <module>
print([Link](m3,m4))
ValueError: shapes (3,1) and (3,1) not aligned: 1 (dim 1) != 3 (dim 0)

Aus der Schule kennt man nur die dritte Variante: Spaltenvektor mal Spaltenvektor ergibt Zahl.
Das funktioniert hier nicht, sondern hier muss die Bedingung für die Multiplikation von Matrizen
gelten: Anzahl der Spalten der 1. Matrix muss gleich sein der Anzahl der Zeilen der 2. Matrix. Die
geliebte Kippregel“!!

Das ist im obigen Beispiel die zweite Variante. Aber Vorsicht! Hier ist das Ergebnis kein Skalar
(keine Zahl), sondern eine 1x1-Matrix. Das Skalarprodukt wird richtig nur berechnet wie im 2.
Fall bei der Multiplikation mit dot von arrays.
3. Zwei Matrizen können miteinander multipliziert werden, wenn die Anzahl der Spalten der ersten
Matrix gleich ist der Anzahl der Zeilen der zweiten Matrix. Das Ergebnis der Multiplikation ist
eine Matrix des Formats ((Anzahl Zeilen der 1. Matrix) x (Anzahl der Spalten der 2. Matrix)), als
Formel (m x n) ∗ (n x p) = (m x p)

391
KAPITEL 25. MATHEMATIK (FORTS.) 25.1. DAS PAKET NUMPY

Beispiel 25.1.24 Matrizen multiplizieren


import numpy as np
a1 = [Link]([[1,2,1,2],[0,1,0,-1],[2,3,-3,-2]])
a2 = [Link]([[0,2],[3,1],[2,0],[1,1]])
## Darstellung
>>> a1
array([[ 1, 2, 1, 2],
[ 0, 1, 0, -1],
[ 2, 3, -3, -2]])
>>> a2
array([[0, 2],
[3, 1],
[2, 0],
[1, 1]])
## Matrizen-Multiplikation
>>> [Link](a1,a2)
array([[10, 6],
[ 2, 0],
[ 1, 5]])

4. Die Länge eines Vektors berechnet sich als Wurzel aus dem Skalarprodukt des Vektors mit sich
selbst, also

Beispiel 25.1.25 Länge eines Vektors


>>> vektor1 = [Link]([3,0,4])
>>> laengeVektor1 = [Link]((vektor1**2).sum())
>>> print(laengeVektor1)
5.0

5. Ein nettes Beispiel zur Matrizenmultiplikation: Bei einem Skatturnier wird an 5 Tischen gespielt.
Die Ergebnisse werden am Ende in einer Liste festgehalten.

Tabelle 25.1. Skatturnier


Spieler Tische
1 2 3 4 5
A 128 -34 -276 179 305
B 12 -420 123 -589 78
C 75 -374 248 -318 -792

Diese Ergebnisse kommen jetzt in eine (3 x 5)-Matrix. Um die Verluste bzw. Gewinne je Tisch zu
berechnen, wird die Gewinn-Verlust-Matrix gv Matr mit dieser Matrix multipliziert. Das ergibt
wieder eine (3 x 5)-Matrix, in der dann in der jeweiligen Spalten steht, was die einzelnen Spieler
eines Tisches erhalten bzw. bezahlen müssen.

392
KAPITEL 25. MATHEMATIK (FORTS.) 25.2. SYMBOLISCHE MATHEMATIK (UND . . .

Beispiel 25.1.26 Skatturnier


>>> gv_Matr = [Link]([[2,-1,-1],[-1,2,-1],[-1,-1,2]])
>>> gv_Matr
matrix([[ 2, -1, -1],
[-1, 2, -1],
[-1, -1, 2]])

>>> ergMatr = [Link]([[128,-34,-276,179,305],


[12,-420,123,-589,78],
[75,-374,248,-318,-792]])
>>> ergMatr
matrix([[ 128, -34, -276, 179, 305],
[ 12, -420, 123, -589, 78],
[ 75, -374, 248, -318, -792]])

>>> zuZahlen = [Link](gv_Matr, ergMatr)


>>> zuZahlen
matrix([[ 169, 726, -923, 1265, 1324],
[ -179, -432, 274, -1039, 643],
[ 10, -294, 649, -226, -1967]])

Das bedeutet, dass z.B. am Tisch 1 Spieler A 169 Geldeinheiten(GE) bekommt, Spieler B 179 GE
zahlt und Spieler C 10 GE bekommt. (Die Summe in jeder Spalte muss 0 betragen!!)

[Link]. Matrizengleichungen
Auch Matrizengleichungen, also lineare Gleichungssysteme (LGS), löst numpy.

Beispiel 25.1.27 LGS lösen


import numpy as np
## Gleichungen lösen
>>> a3 = [Link]([[1,0],[2,1]])
>>> a3
array([[1, 0],
[2, 1]])
>>> b3 = [Link]([[3],[5]])
>>> b3
array([[3],
[5]])

# a * x = b <=> [Link](a,b)
>>> [Link](a3,b3)
array([[ 3.],
[-1.]])

25.2. Symbolische Mathematik (und andere schöne Dinge)


In diesem Kapitel soll ein schönes Paket für Python ein wenig untersucht werden: das Paket sympy.
sympy steht für symbolische Mathematik in Python.
Mit sympy ist es möglich, Variable nicht als Platzhalter für einen Wert zu behandeln, sondern mit
diesen Variablen zu rechnen. Eine einfache Rechnung ist etwa
x4 : x3 = x

393
KAPITEL 25. MATHEMATIK (FORTS.) 25.3. PANDAS

Ein anderes Beispiel für symbolisches Rechnen ist das Bilden einer Ableitungsfunktion. So gilt, wie
jeder weiß,
Also schauen wir mal, was Python mit Hilfe von sympy daraus macht:

Beispiel 25.2.1 sympy kann auch Ableiten


>>> import sympy
>>> x = [Link](’x’)
>>> print([Link](3*x**4),x)
12*x**3 x
>>> print([Link](1/2*x**5+ 3*x**4-2*x),x)
2.5*x**4 + 12*x**3 - 2 x

Aber auch so eine Kleinigkeit wie Kürzen von Termen oder Polynomdivision oder das lösen von
quadratischen Gleichungen beherrscht sympy:

Beispiel 25.2.2 sympy:Terme kürzen etc.


>>> import sympy
>>> x = [Link](’x’)
>>> print([Link]((x**4 + x**2)/(x**2)) )
x**2 + 1
>>> print([Link]((x**3 - x**2 + 4*x - 4)/(x-1)))
x**2 + 4
>>> print([Link](x**2 - 5*x + 6,x))
[2, 3]

25.3. Pandas
Pandas ist ein weiterer Python-Modul, der auf numpy basiert und dazu dient, Daten aufzubereiten, zu
analysieren und darzustellen. Pandas wird mit import pandas as pd importiert.

25.3.1. Series
Das erste Objekt aus Pandas, das ich hier vorstelle, ist die Series (Vorsicht!! Großbuchstabe!!). Eine
Series ist eine Struktur, die eine andere Struktur indiziert (also mit einem Index versieht). Eine Series
ist manchmal so ähnlich wie eine Python-Liste, und manchmal so ähnlich wie ein Python-Dictionary;
sie kann aber mehr!!
Gibt man Series ein einziges Objekt mit, so werden die Elemente des Objektes mit den natürlichen
Zahlen 0 bis (Länge des Objektes - 1) indiziert. Hier wird eine Series erstellt, die eine Liste enthält.
Diese Liste wird ausgegeben.

394
KAPITEL 25. MATHEMATIK (FORTS.) 25.3. PANDAS

Beispiel 25.3.1 Series einer Liste


>>> import pandas as pd
>>> pandaSerie = [Link]([9,17,29,8,13,21])
>>> print(pandaSerie)
0 9
1 17
2 29
3 8
4 13
5 21
dtype: int64

Wollte man das mit Python-Bordmitteln erledigen, sähe das so aus:

Beispiel 25.3.2 Liste indiziert ausgeben


>>> liste = [9,17,29,8,13,21]
>>> for i in range(len(liste)):
print(i,’\t’,liste[i])

0 9
1 17
2 29
3 8
4 13
5 21

1
Series werden defaultmäßig mit dem natürlichen“ Index ausgegeben: es wird einfach gezählt!

Das kann man dadurch ändern, dass man einen Index ausdrücklich angibt: 2

Beispiel 25.3.3 Series mit einem Index


>>> getraenkeMasse = [Link]([’Viertele’,’Halbe’, ’Maß’],
index=[0.25, 0.5, 1.0])
>>> getraenkeMasse
0.25 Viertele
0.50 Halbe
1.00 Maß

Als Dictionary, ohne Verwendung von Pandas, sähe das wie im folgenden Beispiel aus. Hier kann
man auch Schlüssel und Werte separat anzeigen lassen, zudem die Einträge als Liste von Tupeln.

1 Nicht vergessen: man fängt bei 0 an zu zählen.


2 In dem Beispiel geht es um Maße. Da aber in Python-Bezeichnern keine Sonderzeichen benutzt werden sollen (Python ak-
zeptiert sie zwar, aber das geht nur so lange gut, wie man sich in einem Sprachraum bewegt.), mussten die Maße zu Massen
werden. Pardon.
Während die beiden ersten Maßeinheiten vor allem in Baden-Württemberg keine Verständnisprobleme aufwerfen, ist die
letzte Maßeinheit für jeden Wiesn- oder Wasnbesucher wohl bekannt. Und auch das ist keine Masse.

395
KAPITEL 25. MATHEMATIK (FORTS.) 25.3. PANDAS

Beispiel 25.3.4 Getränkemaße als Dictionary


>>> massDic = {0.25:’Viertele’,0.5:’Halbe’,1.0:’Maß’}
>>> massDic
{0.25: ’Viertele’, 0.5: ’Halbe’, 1.0: ’Maß’}
>>> [Link]()
dict_keys([0.25, 0.5, 1.0])
>>> [Link]()
dict_values([’Viertele’, ’Halbe’, ’Maß’])
>>> [Link]()
dict_items([(0.25, ’Viertele’), (0.5, ’Halbe’), (1.0, ’Maß’)])

Das geht auch mit Series, allerdings muss man ein bißchen aufpassen:

Beispiel 25.3.5 Schlüssel und Werte des Dictionary


>>> [Link]
<bound method [Link] of 0.25 Viertele
0.50 Halbe
1.00 Maß
dtype: object>

>>> [Link]()
Float64Index([0.25, 0.5, 1.0], dtype=’float64’)

>>> [Link]
array([’Viertele’, ’Halbe’, ’Maß’], dtype=object)

>>> [Link]
<bound method [Link] of 0.25 Viertele
0.50 Halbe
1.00 Maß
dtype: object>

Series vereinheitlichen“ die Datentypen der enthaltenen Daten.


396
KAPITEL 25. MATHEMATIK (FORTS.) 25.3. PANDAS

Beispiel 25.3.6 Verschiedene Datentypen


>>> pandaSerie2 = [Link]([9,17.5,29,8,13,21])
>>> pandaSerie
0 9.0
1 17.5
2 29.0
3 8.0
4 13.0
5 21.0
dtype: float64
>>> pandaSerie3 = [Link]([9,17.5,29,’Martin’,13,21])
>>> pandaSerie3
0 9
1 17.5
2 29
3 Martin
4 13
5 21
dtype: object
>>> pandaSerie4 = [Link]([9,17.5,29,[17,12],13,21])
>>> pandaSerie4
0 9
1 17.5
2 29
3 [17, 12]
4 13
5 21
dtype: object

In der pandaSerie2 werden alle Zahlen in float umgewandelt, weil 17.5 eine Fließkommazahl ist
(siehe die dtype-Angabe float). In pandaSerie3 ist der dtype object, da das die Oberklasse von String
und Float ist, ebenso in der pandaSerie4.
Im nächsten Beispiel ist das Pandas-Objekt eine von Hand erzeugte Matrix. Die Elemente, die indiziert
werden, sind folglich die Zeilen der Matrix.

Beispiel 25.3.7 Series einer Matrix


>>> pandaMatrix2 = [Link]([[9,17],[29,8],[13,21]])
>>> print(pandaMatrix2)
0 [9, 17]
1 [29, 8]
2 [13, 21]
dtype: object

Series kann auch eine list comprehension übergeben werden.

397
KAPITEL 25. MATHEMATIK (FORTS.) 25.3. PANDAS

Beispiel 25.3.8 Series durch list comprehension


>> brueche = [Link]([1/z for z in range(1,11)])

>>> print(brueche)

0 1.000000
1 0.500000
2 0.333333
3 0.250000
4 0.200000
5 0.166667
6 0.142857
7 0.125000
8 0.111111
9 0.100000
dtype: float64

Das ganze kann natürlich noch schöner ausgegeben werden, indem man als zweiten Parameter von
Series durch das Schlüsselwort index eingeleitet eine Liste von Schlüsselwerten mitgibt.

Beispiel 25.3.9 Series durch list comprehension (schöne Ausgabe)


>>> brueche = [Link]([1/z for z in range(1,11)],
index=[’1/’+str(z) for z in range(1,11)])

>>> print(brueche)

1/1 1.000000
1/2 0.500000
1/3 0.333333
1/4 0.250000
1/5 0.200000
1/6 0.166667
1/7 0.142857
1/8 0.125000
1/9 0.111111
1/10 0.100000
dtype: float64

Schlüssel und Werte können auch separat ausgegeben werden.

Beispiel 25.3.10 Schlüssel und Werte von Series


>>> [Link]

Index([’1/1’, ’1/2’, ’1/3’, ’1/4’, ’1/5’,


’1/6’, ’1/7’, ’1/8’, ’1/9’, ’1/10’], dtype=’object’)
>>> [Link]

array([1. , 0.5 , 0.33333333, 0.25 , 0.2 ,


0.16666667, 0.14285714, 0.125 , 0.11111111, 0.1 ])

398
KAPITEL 25. MATHEMATIK (FORTS.) 25.3. PANDAS

Wird der Series als Daten ein Dictionary übergeben, werden die Schlüssel des Dictionary die Indi-
zes, die sortiert werden.

Beispiel 25.3.11 Series eines Dictionary


>>> noten = [Link]({’Karl’:3.5,’Ina’:2.8,’Lisa’:2.1,
’Sepp’:3.2, ’Lena’:1.4,’Adam’:2.0})

>>> print(noten)

Adam 2.0
Ina 2.8
Karl 3.5
Lena 1.4
Lisa 2.1
Sepp 3.2
dtype: float64

Aber Vorsicht: man muss hierbei darauf achten, bei Dictionaries habe ich das schon einmal geschrie-
ben, dass die Schlüssel eindeutig sind. Wird ein Schlüssel doppelt verwendet, wird der erst zu diesem
Schlüssel gehörende Wert durch den zweiten Wert überschrieben:

Beispiel 25.3.12 Series eines Dictionary mit doppeltem Schlüssel


>>> noten = [Link]({’Karl’:3.5,’Ina’:2.8,’Lisa’:2.1,
’Sepp’:3.2, ’Lena’:1.4,’Adam’:2.0, ’Ina’:5.0})
>>> noten
Adam 2.0
Ina 5.0
Karl 3.5
Lena 1.4
Lisa 2.1
Sepp 3.2
dtype: float64

399
KAPITEL 25. MATHEMATIK (FORTS.) 25.3. PANDAS

Mit apply kann man eine Funktion auf die Series loslassen. Hier wird das gezeigt mit einer Serie
von Temperaturen.

Beispiel 25.3.13 Umrechnung von Series von Temperaturen


>>> def celsius2fahrenheit(c):
return 9.0/5.0 * c + 32

>>> temp = {’Wessling’:18, ’Rottenburg’:21, ’Berlin’:22,


’Paris’:21, ’Colmar’:20}

>>> tempSeries = [Link](temp)

>>> print(tempSeries)

Berlin 22
Colmar 20
Paris 21
Rottenburg 21
Wessling 18
dtype: int64

>>> [Link](celsius2fahrenheit)

Berlin 71.6
Colmar 68.0
Paris 69.8
Rottenburg 69.8
Wessling 64.4
dtype: float64

Weil es so schön ist, folgt hier die Berechnung des Bruttopreises (also inklusive Mehrwertsteuer) einer
Liste von Waren.

400
KAPITEL 25. MATHEMATIK (FORTS.) 25.3. PANDAS

Beispiel 25.3.14 Berechnung von MwSt und Bruttopreis


>>> def mwstBerechnen(p):
return p*0.19

>>> def bruttoPreisBerechnen(p):


return p+mwstBerechnen(p)

>>> warenDic = {’D530’:58.80, ’D830’:63.86, ’D532’:65.54, ’D555’:67.22}

>>> warenSeries = [Link](warenDic)

>>> [Link](mwstBerechnen)

D530 11.1720
D532 12.4526
D555 12.7718
D830 12.1334
dtype: float64

>>> [Link](bruttoPreisBerechnen)

D530 69.9720
D532 77.9926
D555 79.9918
D830 75.9934
dtype: float64

Aber Vorsicht! Das ist noch keine Veränderung der Werte in der Series!!
Das nächste Beispiel: ein Metallwarenhändler verkauft Schrauben in den Größen M2 bis M6. Wenn
der Bestand in einer Größe unter 150 sinkt, sollen 100 Stück nachbestellt werden.

401
KAPITEL 25. MATHEMATIK (FORTS.) 25.3. PANDAS

Beispiel 25.3.15 Schrauben-Nachbestellung


>>> import pandas as pd

>>> def nachbestellen(z):


if z < 150:
return z + 100
else:
return z

>>> schrauben = [Link]([412, 83, 312, 532, 130],


index = [’M’+str(i) for i in range(2,7)])
>>> schrauben
M2 412
M3 83
M4 312
M5 532
M6 130
dtype: int64

>>> [Link](nachbestellen)
M2 412
M3 183
M4 312
M5 532
M6 230
dtype: int64

Das selbe Problem soll jetzt objektorientiert angegangen werden. Hier kommt zuerst die Klassendatei
mit dem Manko, dass die Waren des Unternehmens vorläufig fest in der Klassendatei festgeschrieben
sind. Das muss also noch geändert werden.

402
KAPITEL 25. MATHEMATIK (FORTS.) 25.3. PANDAS

Beispiel 25.3.16 Nachbestellung objektorientiert


#!/usr/bin/python

import pandas as pd

class Warenlager():
def __init__(self):
[Link] = [Link]([412, 83, 312, 532, 130],
index = [’M’+str(i) for i in range(2,7)])

def verkaufen(self):
[Link] = input(’Bezeichnung der Ware: ’)
[Link] = int(input(’Menge: ’))
[Link][[Link]] -= [Link]

def nachbestellen(self, z):


if z < 150:
return z + 100
else:
return z

def bestandAnzeigen(self):
print(’===========\n’, [Link], ’===========\n’)

Und so sieht das Aufrufprogramm aus:

Beispiel 25.3.17 Aufruf Nachbestellung


#!/usr/bin/python

from cl_Warenlager import Warenlager

meineWaren = Warenlager()
print(’vor Aktionen’)
[Link]()
for i in range(2):
[Link]()
print(’nach Verkauf’)
[Link]()
[Link] = [Link]([Link])
print(’ nach Nachbestellung’)
[Link]()

403
KAPITEL 25. MATHEMATIK (FORTS.) 25.3. PANDAS

Und es funktioniert:

Beispiel 25.3.18 Ausgabe der Nachbestellung


vor Aktionen
===========
M2 412
M3 83
M4 312
M5 532
M6 130
dtype: int64 ===========

Bezeichnung der Ware: M4


Menge: 200
nach Verkauf
===========
M2 412
M3 83
M4 112
M5 532
M6 130
dtype: int64 ===========

nach Nachbestellung
===========
M2 412
M3 183
M4 212
M5 532
M6 230
dtype: int64 ===========

Bezeichnung der Ware: M5


Menge: 450
nach Verkauf
===========
M2 412
M3 183
M4 212
M5 82
M6 230
dtype: int64 ===========

nach Nachbestellung
===========
M2 412
M3 183
M4 212
M5 182
M6 230
dtype: int64 ===========

404
KAPITEL 25. MATHEMATIK (FORTS.) 25.3. PANDAS

25.3.2. Dateien, die Pandas lesen kann

Pandas beherrscht folgende Dateitypen:

• csv-Dateien (comma separated values) (Dateiendung: .csv)

• xml-Dateien (extended markup language) (Dateiendung: .xml)

• Stata-Dateien (Dateiendung: .dta)

• Von Tabellenkalkulationsprogrammen erzeugte Dateien (Dateiendung: z.B. .xls)

Hier wurde eine csv-Datei vom Statistischen Bundesamt heruntergeladen, der monatlicher Verbrau-
cherpreisindex. Die Datei enthält die monatlichen Daten der Jahre 2017 bis 2019. Hier wurde einge-
schränkt auf den Januar der angegebenen Jahre; diese Daten stehen in den Spalten 2, 14 und 26. Außer-
dem wurden die ersten 7 Zeilen ignoriert, in denen nur eine Beschreibung der Datei mit zusätzlichen
Informationen steht. Aus der gelesenen csv-Datei wurde dann ein DataFrame gemacht und dieser aus-
gegeben. Bei der Ausgabe sind nur die ersten 18 Datenzeilen hierhin kopiert.

Beispiel 25.3.19 Verbraucherpreisindex


>>> verbrInd = pd.read_csv(’/home/fmartin/bin/python3/DatenStatBundesamt/
[Link]’,
sep=’;’,header=7, usecols=[1,2,14,26])
>>> verbrIndDataFrame = [Link](verbrInd)
>>> print(verbrIndDataFrame)
Unnamed: 1 2017 2018 2019
0 NaN Januar Januar Januar
1 Nahrungsmittel und alkoholfreie Getränke 103,2 105,9 106,6
2 Nahrungsmittel 103,5 106,3 107,2
3 Brot und Getreideerzeugnisse 100,7 101,7 103,4
4 Reis, einschließlich Reiszubereitungen 99,4 99,9 103,8
5 Mehl und andere Getreideerzeugnisse 100,6 101,4 105,8
6 Brot und Brötchen 102,1 103,4 105,3
7 Andere Backwaren 99,7 101,2 103,7
8 Pizza, Quiches und Ähnliches 97,9 99,5 98,8
9 Teigwaren 98,7 97,8 98,0
10 Frühstückszubereitungen 102,0 102,6 102,9
11 Andere Getreideprodukte 98,9 96,7 96,0
12 Fleisch und Fleischwaren 101,3 103,8 105,1
13 Rind- und Kalbfleisch 101,8 103,5 105,2
14 Schweinefleisch 101,8 104,4 105,0
15 Lamm- und Schaffleisch, Ziegenfleisch 107,4 110,2 115,5
16 Geflügelfleisch 100,6 102,2 104,8
17 Andere Fleischprodukte 102,9 106,8 110,2
18 Innereien und andere Schlachtnebenprodukte 101,7 105,4 108,4

Dann habe ich hier noch das Literaturverzeichnis dieses Skriptes mit Pandas bearbeitet. Sämtliche
Dateien dieses Skriptes sind docbook-xml-Dateien. Ein Eintrag im Literaturverzeichnis sieht so aus:

405
KAPITEL 25. MATHEMATIK (FORTS.) 25.3. PANDAS

Beispiel 25.3.20 Eintrag im Literaturverzeichnis XML


<biblioentry id="biblio.grass02">
<abbrev>Freie Software</abbrev>
<author>
<firstname>Volker</firstname>
<surname>Grassmuck</surname>
</author>
<copyright>
<year>2002</year>
<holder>Bundeszentrale für politische Bildung Bonn</holder>
</copyright>
<isbn>3-89331-432-6</isbn>
<title>Freie Software</title>
<subtitle>Zwischen Privat- und Gemeineigentum</subtitle>
</biblioentry>

Diese Datei wird jetzt mit folgendem Programm gelesen und bearbeitet:

Beispiel 25.3.21 XML-Datei lesen


#!/usr/bin/python

import [Link] as et
import pandas as pd

def knotenWertHolen(knoten):
if knoten is not None:
return [Link]
else:
return None
# if knoten is not None else None

geparsteDatei = [Link]("/home/fmartin/texte/Python3Buch/XML/[Link]")
ausgabeSpalten = [’Name’, ’Vorname’, ’Titel’]
biblioDataFrame = [Link](columns=ausgabeSpalten)

for node in [Link]():


nn = [Link](’author/surname’)
vn = [Link](’author/firstname’)
titel = [Link](’title’)

biblioDataFrame = [Link](
[Link]([knotenWertHolen(nn), knotenWertHolen(vn),
str(knotenWertHolen(titel)).strip()], index=ausgabeSpalten),
ignore_index=True)

print(biblioDataFrame)

Und so sieht die Ausgabe aus:

406
KAPITEL 25. MATHEMATIK (FORTS.) 25.3. PANDAS

Beispiel 25.3.22 Ausgabe der Literatur


Name Vorname Titel
0 Grassmuck Volker Freie Software
1 Jones Christopher A. Python and XML
2 Swaroop C.H. A Byte of Python
3 None None None
4 Henscheid Eckard Dummdeutsch
5 Lutz Mark Einführung in Python
6 Lutz Mark Programming Python
7 Lutz Mark Programming Python
8 Eckel Bruce Thinking in Java
9 Schraitle Thomas DocBook-XML
10 None None
11 None None
12 Walerowski Peter Python
13 Lusth John C. The Alchemy of Programming: Python
14 Friedl Jeffrey E.F. Mastering Regular Expressions
15 Evans David Introduction to Computing
16 Briggs Jason Schlangengerangel für Kinder
17 Severance Charles Python for Informatics
18 Lubanovic Bill Introducing Python

25.3.3. Data Frames

Mehrdimensionale Datenfelder (oft Matrizen) beherrscht bereits das Standard-Python. Weiter oben wur-
de dann das ndarray von numpy angesprochen. Die DataFrames von pandas sind auch mehrdimen-
sionale Felder, bei denen noch zusätzlich Zeilen- und Spaltenbezeichnungen angegeben werden können.
Außerdem sind die DataFrames in der Lage, mit fehlenden Einträgen in den Feldern umzugehen.

25.3.4. Indizierung und andere Möglichkeiten der Auswahl

[Link]. Series

Wenn die Series als Dictionary angelegt wurde, kann man auf einzelne Elemente und auf eine Teil-
menge der Elemente auf 2 Arten zugreifen:

1. über den / die Schlüssel

2. über den Index

Zu beachten dabei ist, dass beim Zugriff über den Index die altbekannte Regel von Listen gilt: Anfangs-
element inklusive, Endelement exklusive. Beim Slicen über die (explizit angegebenen) Schlüssel werden
sowohl Anfangs- als auch Endelement ausgegeben.

407
KAPITEL 25. MATHEMATIK (FORTS.) 25.3. PANDAS

Beispiel 25.3.23 Series als Dictionary: Auswahl


>>> noten = [Link]({’Karl’:3.5,’Ina’:2.8,’Lisa’:2.1,
’Sepp’:3.2, ’Lena’:1.4,’Adam’:2.0})
>>> noten
Adam 2.0
Ina 2.8
Karl 3.5
Lena 1.4
Lisa 2.1
Sepp 3.2
dtype: float64

>>> noten[’Karl’]
3.5

>>> noten[’Ina’:’Lisa’]
Ina 5.0
Karl 3.5
Lena 1.4
Lisa 2.1
dtype: float64

>> noten[2]
3.5

>>> noten[1:3]
Ina 5.0
Karl 3.5
dtype: float64

408
KAPITEL 25. MATHEMATIK (FORTS.) 25.3. PANDAS

Der Wirrwarr mit den verschiedenen Arten der Indizierung wird im folgenden Beispiel hoffentlich
klar:

Beispiel 25.3.24 Wirrwarr bei der Indizierung


>>> datenWirrwarr = [Link]({1:3.5,2:2.8,3:2.1})
>>> datenWirrwarr
1 3.5
2 2.8
3 2.1
dtype: float64
>>> datenWirrwarr[1]
3.5

>>> datenWirrwarr2 = [Link]([3.5,2.8,2.1], index=[1,2,3])


>>> datenWirrwarr2
1 3.5
2 2.8
3 2.1
dtype: float64
>>> datenWirrwarr2[1]
3.5

>>> datenWirrwarr3 = [Link]([3.5,2.8,2.1])


>>> datenWirrwarr3
0 3.5
1 2.8
2 2.1
dtype: float64
>>> datenWirrwarr3[1]
2.8

Um diese Widersprüchlichkeiten zu umgehen3 sind in Pandas weitere Möglichkeiten eingeführt, die


Daten indizieren:

1. loc

2. iloc

3. ix

loc benutzt immer den explizit angegebene Index ... wenn er existiert. Das kann also auch noch zu
Verwirrung führen.

Beispiel 25.3.25 loc


>>> datenWirrwarr2 = [Link]([3.5,2.8,2.1], index=[1,2,3])
>>> [Link][1]
3.5

>>> datenWirrwarr3 = [Link]([3.5,2.8,2.1])


>>> [Link][1]
2.8

3 Ich
weiß nicht, ob das pythonisch ist. In Python liegt ja vieles in der Verantwortung des Programmierers, von dem man an-
nimmt, dass er weiß, was er tut.

409
KAPITEL 25. MATHEMATIK (FORTS.) 25.3. PANDAS

Im datenWirrwarr3, in dem keine expliziter Schlüssel angegeben ist, wird der natürliche Schlüssel
genommen, und das erwartet man nicht.
iloc hingegen benutzt immer den natürlichen Schlüssel, auch wenn explizit ein Schlüssel angegeben
wird.

410
Teil XIV.

Glossar

411
Glossar
A

Algorithmus Ein Algorithmus ist eine Vorschrift, die aus einzelnen Anweisungen besteht. Diese Vor-
schrift dient dazu, ein gegebenes Problem zu lösen. Das Wort Algorithmus ist eine Verballhor-
nung des Namens Muhammed al-Chwarizmi, eines arabischen Gelehrten aus dem 9. Jahrhundert
n. Chr.
In der Programmierung dient ein Algorithmus dazu, ein Programm zu schreiben, das ein Pro-
blem löst. Dabei werden die Anweisungen des Algorithmus in Befehle einer Programmiersprache
übersetzt.

C C ist eine Programmiersprache, die sehr eng mit dem Betriebssystem Unix verbunden ist. Beim Ent-
wurf von Unix war ein Ziel, den Code des Betriebssystems rechnerunabhängig und besser wart-
bar zu schreiben. Das war in Maschinensprache oder Assembler, wie es bis dahin üblich war, nicht
gut möglich. Die Entwickler von Unix entwarfen zu diesem Zweck eine Programmiersprache, die
auf alle möglichen Probleme anwendbar war, strukturierte Programmierung ermöglichte, aber
trotzdem systemnah arbeitet. Ein wesentliches Sprachelement von C ist der Pointer (auf deutsch:
Zeiger), ein Verweis auf einen Speicherplatz. C-Programme zeichnen sich dadurch aus, dass sie
schnell sind, weil sie (unter anderem) Speicherplätze nicht über deren Namen, sondern über die
Adresse ansprechen.

CGI Common Gateway Interface. Eine standardisierte Schnittstelle zwischen einem Programm (meis-
tens in einer P-Sprache, also PHP, perl, oder Python) und einem Web-Server.

COBOL COBOL steht für Common Business Oriented Language. Diese Sprache ist geeignet für die Pro-
grammierung von wirtschaftlichen Anwendungen. Was sich die Entwickler dieser Sprache dabei
gedacht haben? Ob sie Wirtschaftswissenschaftler und Kaufleute für unfähig, eine formale Spra-
che zu lernen, gehalten haben? Stellen wir einfach einmal gegenüber, wie ein kleineres Problem in
Python und in COBOL gelöst wird. Zuerst in Python:

a = 3
b = 5
c = a + b

und jeder wird verstehen, dass c danach den Wert 8 hat. Jetzt das selbe in COBOL:

MOVE 3 TO a.
MOVE 5 TO b.
ADD b TO a GIVING c.

Okay, das kann man auch lesen. Vor allem wegen der schönen Punkte am Ende jedes Statements.
Aber wer will so etwas schreiben???

Compiler Ein Compiler ist ein Programm, das einen Quelltext in eine vom jeweiligen Computer ausführbare
Datei umwandelt. Dabei wird der gesamte Quelltext genommen, auf Syntax-Fehler, semantische
Fehler und auch auf Schreibfehler untersucht, in der Regel mit den benötigten Bibliotheken ver-
knüpft und in Maschinensprache übersetzt. 4

Corba Common Object Request Broker Architecture

CSS Cascading Style Sheets sind Dateien, die Formatierungsanweisungen für verschiedene Auszeich-
nungssprachen (HTML, XML) enthalten
4 siehe auch [Compiler]

413
GLOSSAR GLOSSAR

DCOM Distributed Component Object Model

DBMS Database Management System. Ein DBMS ist eine Kombination von Datenbanken mit ihren
Tabellen, ihren Zugriffsrechten, ihren Zugriffsbefehlen und manchmal noch mit eine grafischen
Oberfläche.

Default ist das, was standardmäßig vorgegeben ist, sprachlich taucht es meistens als Defaultwert auf.

DTD Document Type Definition. Hier wird ein Modell eines XML-Dokuments beschrieben.

Dummy Ein Dummy ist ein Stellvertreter für irgendetwas. Er zeichnet sich dadurch aus, dass er sich gar
nicht auszeichnet: ein Dummy hat nichts und kann nichts von dem, was das Original auszeichnet.

Fortran Fortran ist die Zusammenschreibung der ersten Silben von Formular translator“. Daraus geht

schon hervor, dass diese Programmiersprache sich in Mathematik, Physik und den Ingenieurwis-
senschaften zu Hause fühlt. Fortran-Compiler sind meistens recht teuer, aber die Sprache ist nicht
vergnügungssteuerpflichtig. Nein, es macht nicht unbedingt Spaß, Fortran zu programmieren,
aber die Sprache kann mit Zahlen dafür sehr gut umgehen.

HTML Hypertext Markup Language. Die Sprache des Internet. HTML ist eine Seitenbeschreibungsspra-
che, die sich als Standard für Internet-Seiten durchgesetzt hat.

IDE IDE, Abkürzung für Integrated Development Environment.

Interpreter Ein Interpreter wandelt (im Gegensatz zum Compiler) einen Quelltext nicht als Ganzes in
Maschinensprache um, sondern zeilenweise. Das bedeutet, dass der Quelltext erst zur Laufzeit des
Programms auf Korrektheit untersucht wird. Ist der Maßstab für ein Programm die Ausführungsgeschwindigkeit,
so sind interpretierte Programme langsamer als compilierte, weil vor der Ausführung eines Be-
fehls dieser erst in Maschinensprache übersetzt werden muss. 5

Monty Python Englische Komikertruppe. Hier sind einige Internet-Seiten zu Monty Python:
• <[Link]
• <[Link]
• Welcome to the completely unauthorized, completely silly, and completely useless Monty
Python web site! <[Link]

ODBC Open Database Connectivity. Standardisierte Schnittstelle zwischen Programmen in verschiede-


nen Programmiersprachen und Datenbanken verschiedener DBMS.
5 siehe auch [Interpreter]

414
GLOSSAR GLOSSAR

perl perl ist eine der drei P-Sprachen, die bei der Erstellung dynamischer Internet-Seiten benutzt wird.
perl wird interpretiert und hat seine Stärken in der Behandlung von Texten.
perl ist die eierlegende Wollmilchsau. In perl kann man alles machen, vor allem kann man alles
kaputt machen. Böse Menschen behaupten, das Motto von perl sei write once, never read again“,

und das ist durchaus ernst zu nehmen: oft versteht der perl-Programmierer schon nach einer Wo-
che nicht mehr, was er da geschrieben hat.
Pseudocode Pseudocode ist kein Programmcode in irgendeiner Programmiersprache, sondern die
Formulierung eines Algorithmus in Umgangssprache, wobei aber die logische Struktur program-
miersprachenähnlich abgebildet wird. So werden in Pseudocode etwa die typischen reservierten
Wörter für Alternativen und Iterationen (if - then - elseif - else bzw. while . . . bzw. for . . . ) benutzt,
die Aktionen, die auf diese Strukturierungsmittel folgen, in Umgangssprache beschrieben.

Quelltext, auch Quellcode Der Quelltext eines Programms ist das, was der Programmierer schreibt.
Dazu benutzt er eine Programmiersprache. Den Quelltext versteht der Computer noch nicht; er
muss erst in Maschinensprache umgewandelt werden.

SGML Standard Generalized Markup Language.


SQL Structured Query Language. Die Datenbank-Sprache. Der kleinste gemeinsame Nenner.
Source siehe Quelltext

UML UML ist die Abkürzung für Unified Modelling Language, die Softwaresysteme, Geschäftsprozesse,
aber auch Unternehmensmodelle veranschaulichen soll. Gleichzeitig ist UML auch Basis für die
Konstruktion von Software auf der Basis dieser Modelle und für deren Dokumentation. UML hat
viele Unter-“Sprachen, die verschiedene Diagrammarten hervorbringen. Diese ergeben sich aus

den verschiedenen Perspektiven, unter denen man Geschäftsprozesse, die beteiligten Objekte und
die Akteure betrachtet. Die wichtigsten Diagrammarten von UML sind:
• Klassendiagramme
• Anwendungsfalldiagramme
• Zustandsdiagramme
• Aktivitätsdiagramme
Die Sprache hat begonnen, sich durchzusetzen, als Software immer komplexer wurde und die
Wiederverwertbarkeit von Software für Unternehmen ein wichtiges Kriterium wurde.
Für die Programmierung — also für den vorliegenden Text — sind nur Klassendiagramme von
Bedeutung.
URL URL ist die Abkürzung für Uniform Resource Locator. Es handelt sich hier um eine Adress-
Angabe im WWW, zusammen mit einer Angabe, mit welchem Protokoll die Daten übermittelt
werden, z.B. http oder ftp.

W3C World Wide Web Consortium

415
GLOSSAR GLOSSAR

XML XML ist die Abkürzung für Extensible Markup Language. In einer Markup Language werden
— anders als in einem Textverarbeitungsprogramm — keine Eigenschaften des Aussehens wie
Schriftgröße oder Schriftstil festgelegt, sondern Textstellen wird eine Klasse zugeordnet, etwa die
Klasse Kapitelüberschrift“. Erst in einem weiteren Schritt wird dann allen mit Kapitelüberschrift

ausgezeichneten Elementen ein Aussehen verpasst. Es handelt sich dabei um eine logische Aus-
zeichnung, die aber auch eine semantische Bedeutung zum Inhalt hat. So erwartet XML etwa,
dass nach einer Kapitelüberschrift ein Absatz kommen muss, sicher aber keine Buchüberschrift
kommen darf. XML erwartet also sauber strukturierte Dokumente.

416
A. Arbeitsblätter zu Klassen (Danke, Jens!)

A.0.1. UML-Diagramme und Python-Code

417
ANHANG A. ARBEITSBLÄTTER ZU . . .

A.0.2. Vererbung

418
ANHANG A. ARBEITSBLÄTTER ZU . . .

A.0.3. Objektvariable vs. Klassenvariable

419
ANHANG A. ARBEITSBLÄTTER ZU . . .

A.0.4. Polymorphie

420
ANHANG A. ARBEITSBLÄTTER ZU . . .

A.0.5. Übungsaufgabe

421
ANHANG A. ARBEITSBLÄTTER ZU . . .

A.0.6. Assoziationen Teil 1

422
ANHANG A. ARBEITSBLÄTTER ZU . . .

A.0.7. Klassenarbeit

423
ANHANG A. ARBEITSBLÄTTER ZU . . .

A.0.8. Assoziationen Teil 2

424
ANHANG A. ARBEITSBLÄTTER ZU . . .

A.0.9. Liste von Objekten

425
427
ANHANG B. ARBEITSBLÄTTER ZU . . .

B. Arbeitsblätter zu Python (Danke, Frank!)

Datum
Informatik WG12-1
Python
Objektorientierte Systementwicklung

Arbeitsauftrag 1
Python Shell testen
1. Starten Sie die Python Shell über Start - Programme – Python
a) Geben Sie nach dem Prompt folgende Anweisung ein:
„Wie viel ist eins und eins?“
Wie lautet das Ergebnis des Python-Interpreters?
SyntaxFehler, da der Python Interpreter kein Deutsch versteht,
sondern nur Python kann
b) Geben Sie nach dem Prompt folgende Anweisung ein:
2*3+6
Warum versteht der Python Interpreter diese Anweisung?
Die Sprache der Mathematik ist international und sie ist Teil der
Python Sprache

428
ANHANG B. ARBEITSBLÄTTER ZU . . .

Datum
Informatik WG12-1
Python
Objektorientierte Systementwicklung

Arbeitsauftrag 2
Python als Taschenrechner
1. Rufen Sie die Entwicklungsumgebung IDLE auf. Ermitteln Sie die Ergebnisse der
folgenden 4 Aufgaben:

429
ANHANG B. ARBEITSBLÄTTER ZU . . .

Datum
Informatik WG12
Python
Objektorientierte Systementwicklung

Arbeitsblatt 3
Python als Taschenrechner (Variablen und Zuweisung)
1. Aufgabe: Die Umsatzsteuer in Deutschland beträgt 19%. Berechnen Sie
mithilfe von Python für die folgenden (Netto-)Rechnungsbeträge die
Umsatzsteuer. Vereinfachen Sie Ihre Berechnungen, indem Sie den
Umrechnungsfaktor zunächst in einer Variablen mit sinnvoller Bezeichnung
speichern.
a) 100€
b) 12.500,00€
2. Zusatzaufgabe: Sie haben bei Sportscheck Laufschuhe eingekauft und
bekommen eine Rechnung über 178,50€ (Bruttobetrag inklusive 19%
Umsatzsteuer) zugesandt. Berechnen Sie die Höhe des Nettobetrags Ihrer
Rechnung mithilfe einer Formel in Python. Verwenden Sie hierzu Ihre Variable
für die Umsatzsteuer aus Aufgabe 1.

430
ANHANG B. ARBEITSBLÄTTER ZU . . .

Datum
Informatik WG12
Python
Objektorientierte Systementwicklung

Arbeitsblatt 4
Erstes Python Programm mit PyScripter als IDLE
1. Schreiben Sie mithilfe des PyScripter ein Python Programm mit der Ausgabe
„Mein erstes Python Programm!“. Speichern Sie das Programm unter dem
Namen AB_4.py in Ihrem Verzeichnis.

431
ANHANG B. ARBEITSBLÄTTER ZU . . .

Datum
Informatik WG12
Python
Objektorientierte Systementwicklung

Arbeitsblatt 5
Variablen, Operatoren und Zeichenketten
1. Lösen Sie mithilfe der folgenden Angaben die Aufgaben auf der Rückseite
dieses Arbeitsblatts.

432
ANHANG B. ARBEITSBLÄTTER ZU . . .

Datum
Informatik WG12
Python
Objektorientierte Systementwicklung

Arbeitsblatt 6
Einfache Verzweigungen mit IF….ELSE…
1. Lösen Sie mithilfe der folgenden Angaben die Aufgaben auf der Rückseite dieses
Arbeitsblattes.

a) Ein Programm (eine Applikation) soll erstellt werden, die einen Warnhinweis
(„Bitte nachbestellen“) ausgibt, wenn der Lagerbestand einen vorab gesetzten

433
ANHANG B. ARBEITSBLÄTTER ZU . . .

Datum
Informatik WG12
Python
Objektorientierte Systementwicklung

Arbeitsblatt 7
Mehrfache Verzweigungen mit IF….ELSE…
1. Lösen Sie mithilfe der folgenden Angaben die Aufgaben auf der Rückseite dieses
Arbeitsblattes.

a) Die Bit and Byte GmbH erhebt für Bestellungen unter 100,- Euro einen Porto-
und Verpackungsanteil von 5,50 Euro, von 100,- bis 200,- Euro einen Betrag von

434
ANHANG B. ARBEITSBLÄTTER ZU . . .

Datum
Informatik WG12
Python
Objektorientierte Systementwicklung

Arbeitsblatt 8
Schleifen als Kontrollstrukturen (for-Schleife)
1. Lösen Sie mithilfe der folgenden Angaben die Aufgaben auf der Rückseite dieses
Arbeitsblattes.

a) Schreiben Sie ein Programm zur Berechnung der Quadratzahlen für die Zahlen
von 1-10. Verwenden Sie die for-Schleife.

435
ANHANG B. ARBEITSBLÄTTER ZU . . .

Datum
Informatik WG12
Python
Objektorientierte Systementwicklung

Arbeitsblatt 8b
Verschachtelte for-Schleife
1. Lösen Sie die folgenden Aufgaben mithilfe Ihrer Kenntnisse zu Schleifen
a) Schreiben Sie ein Programm mittels einer Schleife, welches folgende Ausgabe
erzeugt.

Speichern Sie das Programm unter AB8b_AufgabeA.py.

b) Schreiben Sie ein Programm mittels zweier Schleifen, welches obige Ausgabe
erzeugt. Speichern Sie das Programm unter AB8b_AufgabeB.py.
c) Schreiben Sie ein Programm mittels einer Schleife, welches folgende Ausgabe
erzeugt.

d) Speichern Sie das Programm unter AB8b_AufgabeC.py.

Zusatzaufgabe: Überlegen Sie selbst eine kaufmännische Problemstellung, bei der Sie
die for-Schleife sinnvoll in Ihre Programmstruktur einbinden können. Speichern Sie
das Programm unter AB8_Zusatzaufgabe.py.

436
ANHANG B. ARBEITSBLÄTTER ZU . . .

Aufgaben in Einzelarbeit zum Thema Schleifen


(Klasse E1IT2)
Aufgabe 1a Schreiben Sie ein Programm mittels einer Schleife, welches
folgende Bildschirmausgabe erzeugt:
xxxxxxxxxx
xxxxxxxxxx
xxxxxxxxxx
xxxxxxxxxx
xxxxxxxxxx
xxxxxxxxxx

Aufgabe 1b
Schreiben Sie ein Programm mittels zweier Schleifen, welches folgende
Bildschirmausgabe erzeugt:
xxxxxxxxxx
xxxxxxxxxx
xxxxxxxxxx
xxxxxxxxxx
xxxxxxxxxx
xxxxxxxxxx

Aufgabe 1c
Schreiben Sie ein Programm mittels Schleifen, welches folgende
Bildschirmausgabe erzeugt:
x
xx
xxx
xxxx
xxxxx
xxxxxx
xxxxxxx
xxxxxxxx
xxxxxxxxx
xxxxxxxxxx
xxxxxxxxxxx
xxxxxxxxxxxx
xxxxxxxxxxxxx

Aufgabe 1d
Schreiben Sie ein Programm mittels Schleifen, welches folgende
Bildschirmausgabe erzeugt:
x
xxx
xxxxx
xxxxxxx
xxxxxxxxx
xxxxxxxxxxx
xxxxxxxxxxxxx

Aufgabe 1e
Schreiben Sie ein Programm mittels Schleifen, welches folgende
Bildschirmausgabe erzeugt:
xxxxxxxxxxxxx
xxxxxxxxxxx
xxxxxxxxx
xxxxxxx
xxxxx
xxx
x

437
ANHANG B. ARBEITSBLÄTTER ZU . . .

Datum
Informatik WG12
Python
Objektorientierte Systementwicklung

Arbeitsblatt 9
Schleifen als Kontrollstrukturen (while-Schleife)
1. Lösen Sie mithilfe der folgenden Angaben die Aufgaben auf der Rückseite dieses
Arbeitsblattes.

a) Schreiben Sie ein Programm zur Berechnung des jährlichen Kontostands. Das
Startguthaben soll 1500€ betragen. Der Zinssatz liegt bei jährlich 5,5%. Das

438
ANHANG B. ARBEITSBLÄTTER ZU . . .

Datum
Informatik WG12
Python
Objektorientierte Systementwicklung

Arbeitsblatt 10
Funktionen
1. Lösen Sie mithilfe der folgenden Angaben die Aufgaben auf der Rückseite dieses
Arbeitsblattes.

a) Schreiben Sie ein Programm das folgende Ausgabe im Interpreter über eine
Funktion gruss() erzeugt.

439
ANHANG B. ARBEITSBLÄTTER ZU . . .

Datum
Informatik WG12
Python
Objektorientierte Systementwicklung

Arbeitsblatt 11a
Zeichenketten und Operatoren
1. Lösen Sie mithilfe der folgenden Angaben die Aufgaben auf der Rückseite dieses
Arbeitsblattes.

440
ANHANG B. ARBEITSBLÄTTER ZU . . .

Datum
Informatik WG12
Python
Objektorientierte Systementwicklung

Arbeitsblatt 11b
Zeichenketten und Funktionen
1. Lösen Sie mithilfe der folgenden Angaben die Aufgaben auf der Rückseite dieses
Arbeitsblattes.

441
ANHANG B. ARBEITSBLÄTTER ZU . . .

Datum
Informatik WG12
Python
Objektorientierte Systementwicklung

Arbeitsblatt 12a
Einführung in die objektorientierte Systementwicklung
1. Lösen Sie mithilfe nachfolgender Angaben die Aufgaben von AB12b.

442
ANHANG B. ARBEITSBLÄTTER ZU . . .

Datum
Informatik WG12
Python
Objektorientierte Systementwicklung

Arbeitsblatt 13
Unified Modelling Language
1. Lösen Sie mithilfe der folgenden Angaben die Aufgaben auf der Rückseite
dieses Arbeitsblattes.

443
ANHANG B. ARBEITSBLÄTTER ZU . . .

Datum
Informatik WG12
Python
Objektorientierte Systementwicklung

Arbeitsblatt 14
Erzeugung von Klassen und Objekten
Aufgabe:
a) Schreiben Sie in Python eine Klasse mit Konstruktor zu Ihrem UML-
Diagramm von Arbeitsblatt 13 - Aufgabe 1b).
b) Erzeugen Sie 2 verschiedene Instanzen (Objekte) der Klasse Auto.

444
ANHANG B. ARBEITSBLÄTTER ZU . . .

Datum
Informatik WG12
Python
Objektorientierte Systementwicklung

Arbeitsblatt 15
Erweiterung von Klassen
Aufgabe:
a) Erweitern Sie die Klasse Auto von AB14 um eine Methode fahren. Die
Methode fahren soll z.B. ausgeben: Auto x faehrt y km/h!
b) Instanziieren Sie ein Objekt, das anschließend durch Aufruf der Methode
fahren folgende Ausgabe erzeugt: VW Golf faehrt 40 km/h
c) Finden Sie weitere Methoden zur Klasse Auto und nutzen Sie diese Methoden
bei der Instanziierung von Objekten.

445
ANHANG B. ARBEITSBLÄTTER ZU . . .

Datum
Informatik WG12
Python
Objektorientierte Systementwicklung

Arbeitsblatt 15 (Zusatzaufgabe)
Erweiterung von Klassen

Aufgabe:
a) Modellieren Sie mithilfe von UML eine Klasse Fahrzeug unter folgenden
Bedingungen. Ein Fahrzeug hat unter anderem die Eigenschaften
Bezeichnung und Geschwindigkeit. Außerdem kann man ein Fahrzeug
beschleunigen. Dadurch erhöht sich die Geschwindigkeit. Die aktuelle
Geschwindigkeit soll jederzeit angezeigt werden können.
b) Programmieren Sie die Klasse Fahrzeug aus Aufgabe a) in Python. Speichern
Sie die Klasse unter dem Dateinamen AB15_cl_Fahrzeug.py in Ihrem
Schuelerverzeichnis ab.
c) Erzeugen Sie innerhalb dieser Datei eine Instanz (ein Objekt) der Klasse
Fahrzeug mit der Bezeichnung audi. Die Ausgangsgeschwindigkeit des Audi
beträgt 0 km/h. Beschleunigen Sie das Objekt audi auf 120km/h. Geben Sie
die aktuelle Geschwindigkeit aus. Speichern Sie das Objekt unter dem
Dateinamen AB15_o1_Fahrzeug.py in Ihrem Schuelerverzeichnis ab.

Zusatzaufgabe:
Ergänzen Sie die Klasse Fahrzeug um weitere Eigenschaften und Methoden Ihrer
Wahl.

446
ANHANG B. ARBEITSBLÄTTER ZU . . .

Datum
Informatik WG12
Python
Objektorientierte Systementwicklung

Arbeitsblatt 16
Import von Klassen
Aufgabe:
a) Modellieren Sie mithilfe von UML eine Klasse Konto unter folgenden
Bedingungen. Ein Konto verfügt über eine Kontonummer, eine Bankleitzahl,
einen Zinssatz, einen Kontostand und einen Kontoinhaber. Es kann Geld auf
das Konto eingezahlt werden bzw. Geld vom Konto abgehoben werden.
Außerdem soll der aktuelle Kontostand angezeigt werden können.
b) Programmieren Sie die Klasse Konto aus Aufgabe a) in Python. Beachten Sie
dass bei der Einzahlung der Kontostand erhöht wird und bei der Abhebung
der Kontostand verringert wird. Speichern Sie die Klasse unter dem
Dateinamen AB16_cl_Konto.py in Ihrem Schuelerverzeichnis ab.
c) Importieren Sie die Klasse in eine neue Datei. Erzeugen Sie innerhalb dieser
Datei eine Instanz (ein Objekt) der Klasse Konto mit der Bezeichnung
meinKonto. Die Wertausprägung der Attribute ist frei wählbar. Sie können
beispielsweise die Angaben Ihres eigenen Kontos nehmen. Speichern Sie das
Objekt unter dem Dateinamen AB16_o1_Konto.py in Ihrem
Schuelerverzeichnis ab.
d) Programmieren Sie verschiedene Einzahlungen und Auszahlungen Ihres
Kontos mit anschließender Anzeige des aktuellen Kontostands.

447
C. Lösungen zu Aufgaben
C.1. aus Kapitel 7: Programmstrukturen
Wochentagsberechnung.

#!/usr/bin/python
#-*- coding: utf-8 -*-
# berechnet zu einem Datum den Wochentag

wochentage = ["Sonntag", "Montag", "Dienstag", "Mittwoch",


"Donnerstag", "Freitag", "Samstag"]

tag = int(input("Tag eingeben: "))


monat = int(input("Monat eingeben(als Zahl): "))
jahr = int(input("Jahr eingeben: "))
monat_r = monat

if (monat > 2):


monat_r = monat_r - 2
else:
monat_r = monat_r + 10
jahr = jahr - 1

(c, a) = divmod(jahr, 100)


# d.h. a = jahr % 100, c = jahr / 100

b = (13 * monat_r - 1) / 5 + a / 4 + c / 4
wotag = (b + a + tag - 2 * c) % 7

print("Der ",tag,".", monat,".",jahr, " ist ein ", wochentage[wotag])

C.2. aus Kapitel 8: Schleifen


Sternchen-Pyramide.

#!/usr/bin/python
for i in range(1,40,2):
z = ’*’*i
print([Link](40,’ ’))

Quadratzahlen.

#!/usr/bin/python
# -*- coding: utf-8 -*-

endZahl = int(input(’bis zu welcher Zahl: ’))

449
ANHANG C. LÖSUNGEN ZU AUFGABEN C.2. AUS KAPITEL 8: SCHLEIFEN

for i in range(endZahl+1):
print("%i*%i = %i" % (i, i, i*i))

Sieb des Eratosthenes.

#!/usr/bin/python

schranke = int(input("Bis zu welcher Zahl sollen Primzahlen berechnet werden? "))

alleZahlen = range(1,schranke+1)

alleZahlen[0] = ’x’

start = alleZahlen[1]
while start*start < schranke:
n = 2
while start*n <= schranke:
alleZahlen[start*n - 1] = ’x’
n += 1
k = 0
while type(alleZahlen[start+k]) != int:
k +=1
start = alleZahlen[start+k]
print("\n\nSo! Das sind jetzt alle Primzahlen bis ",schranke,"!!")

primz = []
for x in alleZahlen:
if type(x) == int:
[Link](x)

print(primz)

Größter gemeinsamer Teiler und kleinstes gemeinsames Vielfaches mit dem Euklidschen Algo-
rithmus.

#!/usr/bin/python
# -*- coding: utf-8 -*-
# berechnet ggT und kgV zweier Zahlen mit dem Euklidschen Algorithmus

zz1 = int(input("erste Zahl eingeben "))


zz2 = int(input("zweite Zahl eingeben "))
z1 = zz1
z2 = zz2

while (z1 != z2):


while (z1 > z2):
z1 = z1 - z2
while (z2 > z1):
z2 = z2 - z1

print("ggT von ",zz1," und ",zz2," ist ",z1)

print("kgV von ",zz1," und ",zz2," ist ",zz1 * zz2 / z1)

450
ANHANG C. LÖSUNGEN ZU AUFGABEN C.2. AUS KAPITEL 8: SCHLEIFEN

Stellenwertsysteme.

#!/usr/bin/python

zahl = int(input("Zahl im Dezimalsystem eingeben: "))


modus = int(input("Basis des Stellenwertsystems,
in das die Zahl umgerechnet werden soll: "))
if modus > 10:
mehrAlsHex = [’0’,’1’,’2’,’3’,’4’,’5’,’6’,’7’,’8’,’9’,
’A’,’B’,’C’,’D’,’E’,’F’,’G’,’H’,’I’,’J’,’K’,’L’]

restliste = []
while(zahl > 0):
(zahl,rest) = divmod(zahl, modus)
if modus > 10:
restAlpha = mehrAlsHex[rest]
[Link](restAlpha)
else:
[Link](rest)

[Link]()

for i in restliste:
print(i,end=’,’)

Mit Uhrzeiten rechnen.

#!/usr/bin/python
z1 = [15, 38, 46]
z2 = [12, 47, 58]
sum = [0,0,0]

uebertrag = 0
for i in range(len(z1)-1,-1,-1):
if i > 0:
sum[i] = (z1[i] + z2[i] + uebertrag) % 60
uebertrag = (z1[i] + z2[i]) / 60
else:
sum[i] = (z1[i] + z2[i] + uebertrag) % 60
print(sum)

Drucker - Abrechnung.

#!/usr/bin/python
# -*- coding: utf-8 -*-

print(’Druckkosten-Berechnung’)

print(’Menge\tGesamtkosten\tKosten je Blatt’)

fixkosten = 840.34
stueckkosten = 0.038
mindestAbnahme = 2000
mwstSatz = 0.19

451
ANHANG C. LÖSUNGEN ZU AUFGABEN C.2. AUS KAPITEL 8: SCHLEIFEN

for i in range(0, 10001, 500):


if i == 0:
print(’%-10d %-17.2f’ % (i, fixkosten * (1 + mwstSatz)))
elif i <= mindestAbnahme:
print(’%-10d %-17.2f %-12.4f’ %
(i, fixkosten * (1 + mwstSatz), fixkosten * (1 + mwstSatz) / i))
else:
kosten = (fixkosten + (i - mindestAbnahme)*stueckkosten) * (1 + mwstSatz)
print(’%-10d %-17.2f %-12.4f’ % (i, kosten, kosten / i))

Sierpinski - Pfeilspitze. Zuerst ein Modul, das die Fakultäten und den Binomialkoeffizienten berech-
net:

#!/usr/bin/python
# -*- coding: utf-8 -*-

def fak(zahl):
fakultaet = 1
for i in range(zahl, 0, -1):
fakultaet *= i
return fakultaet

def binko(n, k):


return fak(n) / (fak(n-k) * fak(k))

if __name__ == ’__main__’:
z = int(input(’Fakultät bis ... ’))
print(fak(z))

print(’n über k’)


n = int(input(’n = ’))
k = int(input(’k = ’))
print(binko(n, k))

Und hier das Programm für die Pfeilspitze (es ist wieder peinlich kurz!):

#!/usr/bin/python
from fakultaet import binko
for i in range(0,30,1):
z = ’’
for j in range(i+1):
if binko(i, j)%2 == 0:
z += ’ ’
else:
z += ’x’
print(z)

Staaten mit Hauptstädten (selbstlernend). Hier zuerst das Programm, das die ganze Intelligenz zum
Inhalt hat:

#!/usr/bin/python
""" Dokumentation von [Link]
Ein Dictionary Land -> Hauptstadt wird eingerichtet.

452
ANHANG C. LÖSUNGEN ZU AUFGABEN C.2. AUS KAPITEL 8: SCHLEIFEN

Das gesamte Dictionary wird ausgegeben.


Dann wird ein kleines Raetsel veranstaltet.
"""

def initialisiere():
global LaHa
global neuLaHa
neuLaHa= {}
LaHa = {’Italien’:’Rom’,
’Frankreich’:’Paris’,
’Deutschland’:’Berlin’,
’Belgien’:’Bruessel’,
’Spanien’:’Madrid’}

def hilfe():
for land in LaHa:
print(land, ’\t’, LaHa[land])

def raetsel():
punkte = 0
fehler = 0
for land in LaHa:
frageHText = ’Wie heisst die Hauptstadt von ’+land+’?’

stadt = input(frageHText)
if LaHa[land] == stadt:
punkte += 1
print("Gut!!")
else:
print(’so nicht’)
print(’schau im Lexikon nach!’)
tippfText = ’(falls Deine Eingabe "’+stadt
+ ’" nur ein Tippfehler war, gib jetzt das Wort "Tippfehl

frageLText = ’von welchem Land ist ’+stadt+’ die Hauptstadt?’


+ tippfText

neuesLand = input(frageLText)
if neuesLand == ’Tippfehler’:
pass
else:
neuLaHa[neuesLand] = stadt
fehler += 1

print("Du hast ", punkte, " von ",punkte+fehler," richtige Antworten")


if fehler > 0:
print("also nochmal!!!")
[Link](neuLaHa)
return (fehler)

Und hier das aufrufende Programm:

#!/usr/bin/python
import LandHauptst

print(LandHauptst.__doc__)

453
ANHANG C. LÖSUNGEN ZU AUFGABEN C.2. AUS KAPITEL 8: SCHLEIFEN

LaHa = {}
neuLaHa = {}
[Link]()
while [Link]() > 0:
1

Caesar-Verschlüsselung.

#!/usr/bin/python
# -*- coding: utf-8 -*-

dateiName = input(’Welche Datei soll verschlüsselt werden? ’)


schlBuchst = input(’Schlüssel-Buchstabe, um den verschoben werden soll? ’)
ausDatName = dateiName+’ver’
leseDat = open(dateiName,’r’)
schreibDat = open(ausDatName,’w’)

for zeile in [Link]():


ausZeile = ’’
for zeichen in zeile:
if zeichen == ’ ’:
ausZeile += ’#’
elif zeichen == ’\n’:
ausZeile += zeichen
else:
ausZeile += chr(((ord(zeichen) - ord(’A’) + ord(schlBuchst))%26)+ord(’A’))
[Link](ausZeile)
[Link]()
[Link]()

. . . und auch Entschlüsseln.

#!/usr/bin/python
# -*- coding: utf-8 -*-

dateiName = input(’Welche Datei soll entschlüsselt werden? ’)


schlBuchst = (’Schlüssel-Buchstabe, um den verschoben werden soll? ’)
ausDatName = dateiName+’ent’
leseDat = open(dateiName,’r’)
schreibDat = open(ausDatName,’w’)

for zeile in [Link]():


ausZeile = ’’
for zeichen in zeile:
if zeichen == ’#’:
ausZeile += ’ ’
elif zeichen == ’\n’:
ausZeile += zeichen
else:
ausZeile += chr(((ord(zeichen) - ord(’A’) - ord(schlBuchst))%26)+ord(’A’))
print(ausZeile)
[Link]()
[Link]()

Monoalphabetische Verschlüsselung mit Schlüsselwort.

454
ANHANG C. LÖSUNGEN ZU AUFGABEN C.3. AUS KAPITEL 10: FUNKTIONEN

#!/usr/bin/python
# -*- coding: utf-8 -*-

dateiName = input(’Welche Datei soll verschlüsselt werden? ’)


schlWort = input(’Schlüsselwort? ’)
ausDatName = dateiName+’ver’
leseDat = open(dateiName,’r’)
schreibDat = open(ausDatName,’w’)

zz = 0
for zeile in [Link]():
ausZeile = ’’
for zeichen in zeile:
ausZeile += chr((ord(zeichen) + ord(schlWort[zz % len(schlWort)]))% 255)
zz += 1
[Link](ausZeile)
[Link]()
[Link]()

C.3. aus Kapitel 10: Funktionen


Newton’sches Näherungsverfahren.

#!/usr/bin/python

# Funktion fest eingebaut


def f(x):
fwert = x**3 - 2
return fwert

def ableitung(x):
abl = 3 * x**2
return abl

fwert = 100
startwert = 1.0
schwelle = 0.0000001
x = startwert

while abs(fwert) > schwelle:


fwert = f(x)
abl = ableitung(x)
print(x,’\t’,fwert,’\t’,abl)
x = x - fwert / abl

Römische Zahlen.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

roemZahlen = [{1:’I’, 5:’V’, 10:’X’},


{1:’X’, 5:’L’, 10:’C’},
{1:’C’, 5:’D’, 10:’M’}]

455
ANHANG C. LÖSUNGEN ZU AUFGABEN C.3. AUS KAPITEL 10: FUNKTIONEN

def einsFuenfZehn(zehnerPotenz, zahl):


global roZa
if zahl == 9:
roZa += roemZahlen[zehnerPotenz][1]+roemZahlen[zehnerPotenz][10]
elif zahl == 4:
roZa += roemZahlen[zehnerPotenz][1]+roemZahlen[zehnerPotenz][5]
elif zahl >= 5:
roZa += roemZahlen[zehnerPotenz][5]+(zahl-5)*roemZahlen[zehnerPotenz][1]
else:
roZa += zahl*roemZahlen[zehnerPotenz][1]

decZahl = int(input(’Natürliche Zahl im Dezimalsystem eingeben: ’))


roZa = ’’
while decZahl > 1000:
decZahl -= 1000
roZa += roemZahlen[2][10]

(decHun, decHunRest) = divmod(decZahl, 100)


(decZeh, decEin) = divmod(decHunRest, 10)

einsFuenfZehn(2, decHun)
einsFuenfZehn(1, decZeh)
einsFuenfZehn(0, decEin)

print(roZa)

456
D. Literatur zu Python

Literatur
[ABOP] A Byte of Python, C.H. Swaroop, Copyright c 2003-2005 Creative Commons Attribution-
NonCommercial-ShareAlike License 2.0, .
[Compiler] <[Link] , , Copyright c , . 4
[DocBook-XML] DocBook-XML, Thomas Schraitle, Copyright c 2004 SuSE Press, 3-89990-078-2. (docu-
ment)
[Evans] Introduction to Computing , David Evans, Copyright c
[Link] . 17, 19
[FSF] <[Link] , Copyright c , . 10
[Freie Software] Freie Software, Volker Grassmuck, Copyright c 2002 Bundeszentrale für politische Bil-
dung Bonn, 3-89331-432-6. 9
[Friedl] Mastering Regular Expressions , Jeffrey E.F. Friedl, Copyright c 2002 O’Reilly, 0-596-
00289-0. 5.5
[Interpreter] <[Link] , , Copyright c , . 5
[Java] Thinking in Java, Bruce Eckel, Copyright c 2003 Prentice Hall, 3-8272-6896-6. (docu-
ment)
[Lubanovic] Introducing Python , Bill Lubanovic, Copyright c 2015 O’Reilly, 978-1-449-35936-2.
[Lusth] The Alchemy of Programming: Python <[Link]
[Link]> , John C. Lusth, Copyright c 2012 , . 3.3.5
[Lutz/Ascher] Einführung in Python, Mark LutzDavid Ascher, Copyright c 2007 O’Reilly, Köln, 3-
89721-488-0.
[Programming Python] Programming Python, Mark Lutz, Copyright c 2006 O’Reilly, Sebastopol, CA
95472, USA, 0-596-00925-9. 3, 5, 5, 2.6.1, 4, 20.6
[Programming Python2] Programming Python, Mark Lutz, Copyright c 1996 O’Reilly, Sebastopol, CA
95472, USA, 1-56592-1975-6. 13
[Python] Python, Peter Walerowski, Copyright c 2009 Addison-Wesley, 978-3-8273-2517-4. 6
[Python and XML] Python and XML, Christopher A. JonesFred L. Jr. Drake, Copyright c 2002 O’Reilly,
Köln, 3-89721-175-0. (document)
[SWFK] Schlangengerangel für Kinder , Jason Briggs, Copyright c
[Link] .
[Severance] Python for Informatics , Charles Severance, Copyright c
[Link] .
[VdP] Python Data Science Handbook , Jake VanderPlas, Copyright c 2017 O’Reilly, 978-1-491-
91205-8.
[dummdeutsch] Dummdeutsch, Eckard Henscheid, Copyright c 1993 Reclam, Stuttgart, 3-15-008865-8.
14

457
E. Index

Algorithmus, 33, 139 Caesar-Verschlüsselung, 128


Alternative, 40, 141, 146 capitalize, 298
Anweisung, 33, 52 CC BY-NC-SA, 18
Anweisungsblock, 147 Cleese, John, 27
append, 110 COBOL, 36
Array, 84 Compiler, 35
Attribut, 213 Creative Commons, 18
Aufgaben
Dateien, 261
zu Alternative, 154
zu Auswahl, 154 Dateisystem, 39
zu Dateien, 270 Datenbank, 271
zu Dictionaries, 134 MySQL, 271
zu doctest, 203
Datenstrukturen
zu Funktionen, 195
Dictionary, 123
zu Klassen, 244
Liste, 105
zu Listen, 134
Tupel, 130
zu Programmierung allgemein, 47
zu Schleifen, 177 Datentyp
zu Sequenzen, 140 isinstance, 66
zu Texten, 103 Debugger, 47
zu Variablen, 63
Dekorator, 228
Ausdrücke
Dezimalpunkt, 56
reguläre, 97
Dictionary, 123
Ausdruck, 56
Comprehension, 129
Ausgabe defaultdic, 126
mit print, 57 get, 124
Ausnahme, 253 set, 125
sortiert ausgeben, 127
Auswahl, 141
divmod, 57
Bedingung, 148 DocBook-XML, 18
Bedingungen, 142 docstring, 41
Kurzschluß-Verfahren, 145
verknüpfte, 143 Editor, 37
Befehl, 33, 52 Syntax highlighting, 37
Wortvervollständigung, 37
Betriebssystem, 39
Befehle, 39 eingebaute Funktionen, 180
binäre Suche, 109 Entscheidung, 40
Block, 147 Entscheidungen
Einrückung, 147 verschachtelte, 153
Boole’sche Variable enumerate, 165
False, 141 environment, Siehe Umgebungsvariable 369
True, 141
exception, 253
C, 36 Expression, 56

459
ANHANG E. INDEX

expression Idle, Eric, 27, 51


regular, 97 Import, 205
extend, 111 input, 78
False, 141 int, 55
Fehler, 45 Interpreter, 35
Debugger, 47 isinstance, 66
Fehlerarten Iteration, 40, 141
Laufzeitfehler, 46
Kamel-Schreibweise, 213
semantischer Fehler, 46
Syntaxfehler, 46 Klasse
Attribut, 213
Feld, 84
Funktion super, 232
Filtern von Listen, 109 Methode, 213
float, 55 new style, 230
for-Schleife, 158 Kodierung, 88
Formatierung Kommentar, 41
im C-Stil, 90 komplexe Zahlen, 65
im Python-Stil, 92 Konstruktor, 217
mit format, 92
Konventionen, 43
Fortran, 36
Kryptographie
Freie Software, 36 Caesar-Verschlüsselung, 128
Funktionen, 180
eingebaute, 180 lambda-Funktionen, Siehe Funktionen 195
lambda, 195 Leerzeichen, 87
rekursive, 193 LGS, 393
Gültigkeitsbereich, 186 Lineares Gleichungssystem, 393

ganze Zahlen, 65 list comprehension, 168


Listen, 105
glob, 369
comprehension, 107
globale Variable, 187 Einträge mit Namen, 118
GUI Element löschen, 113
Tkinter, 355 erzeugen, 106
fester Typ der Daten, 122
help, Siehe auch Hilfe 207, 208 Filterfunktion, 109
Hilfe, 42, 207, 208 filtern, 109
dir, 208 flache Kopie, 121
help, 207 Generator, 106
Hausnummer, 105
Hilfetext, 41
Index, 105, 109
HTML, 321 kopieren, 120
Überschrift, 322 Listenelement, 105
Absatz, 322 Matrix, 116
Formular, 323 pop, 113
Geordnete Liste, 323 Position eines Elements, 109
Hervorhebungen, 322 Shortcut, 110
Leerzeichen, 322 slicen, 114
Link, 323 sortieren, 114
Liste, 323 sortieren (groß oder klein), 115
Spiegelstrich-Liste, 323 sortierte Kopie, 115
Strukturierung, 321 umkehren, 114
tag, 321 Verkettung, 108
verlängern, 110, 111
IDE, 38 Verlängerung, 113
idle, 51 zip, 120

460
ANHANG E. INDEX

lokale Variable, 186 Operatoren


arithmetische, 57
Maskieren, 81 Shortcut, 73
Mathematik Vergleichs-, 66
LGS, 393 Verschiebe-, 69
lineares Gleichungssystem, 393 os, 366
numpy, 379 [Link], 371
sympy, 393
Matrix, 116 packages, 210
Nullmatrix, 116 Paket
numpy, 379
Matrizen, 379
sympy, 393
Addition, 389
Diagonal-, 384 Pakete, 210
Einheits-, 382 Palin, Michael, 27
Eins-, 384
Parameter, 180
Erzeugung von, 380
invertieren, 385 PEP 8, 45
Multiplikation von, 391 pickle, 267
Null-, 382, 384 print, 57
Skalarprodukt, 389
umkehren, 385 private, 221

Mehrfach-Entscheidungen, 151 Programmaufruf, 77


aus Python-Programm, 367
Menge, 131
Programmierrichtlinien, 45
Operationen, 131
Programmiersprachen
Methode, 213
C, 36
Aufruf, 85
COBOL, 36
statisch, 227 Fortran, 36
Methoden überschreiben, 233 Programmierung
Modul, 205 strukturierte, 139
Module protected, 221
glob, 369 Pseudocode, 145
os, 366
public, 221
[Link], 371
pickle, 267 Quellcode, 30, 75
shutil, 370
Quelltext, 35
sys, 363
Modulus, 56 range, 106, 160
Monty Python, 27 rationale Zahlen, 65
MySQL, 271 raw strings, 87
reelle Zahlen, 65
Namensraum, 186
Regeln für Bezeichner
natürliche Sprache, 375 Klassen und Objekte, 214
natürliche Zahlen, 65 Variablen, 61
new style, 230 reguläre Ausdrücke, 97

NLTK, 375 regular expression, 97

numpy, 379 Rekursion, 193


Reservierte Wörter, 45
objektorientierte Programmierung Rest, 56
Vererbung, 214
Rundungsfehler, 57
OOP
Vererbung, 214 Schlüsselwörter, 45

461
ANHANG E. INDEX

Schleife, 40, Siehe auch strukturierte Programmie- Text


rung 158, 158 capitalize, 298
Zähl-, 158 Tkinter, 355
Schleifen True, 141
Überspringen eines Elements, 176
Tupel, 130
Abbruch, 176
benannte, 130
weiter mit dem nächsten Element, 176
type, 55
Schleifen-Beispiele, 167
Typisierung
Selbstreferenz, 217 dynamisch, 59
self, 217 statisch, 59
Sequenz, 40, 139 überschreiben
sha-bang, 77 von Methoden, 233
Shortcut Umgebungsvariable, 369
Listen, 110 Umkehrung
Shortcut-Operatoren, 73 Liste, 114
shutil, 370 Umkehrung (beliebige Objekte), 114
Sichtbarkeit UML, 217
private, 221 Umbrello, 217
protected, 221 Variable, 58
public, 221 globale, 187
Skalarprodukt, 389 lokale, 186
Slicing, 84 Wertzuweisung, 62
Variablenname, 60
Sprache
natürliche, 375 Variablennamen, 61
Statement, 52 Vererbung, 214
statement, 33 Vergleichsoperatoren, 66

statische Methode, 227 Verschiebeoperatoren, 69

Steuerzeichen, 82 Wahrheit, 141


Stil, 43 Wahrheitswerte, 148
False, 143
String-Methoden
True, 143
[Link], 86
[Link], 86 Wertzuweisung, 62
[Link], 86 while-Schleife, 158
[Link], 86 whitespace, Siehe Leerzeichen 87
strings, 81 Wiederholung, 141
strukturierte Programmierung, 139 Wortvervollständigung, 37
Alternative, 40, 141, 146
Entscheidung, 40 XML
For-Schleife, 158 DocBook, 18
Iteration, 40, 141
Zählschleife, 158
Schleife, 40
mitzählen, 165
Sequenz, 40, 139, 141
While-Schleife, 166 Zahlen, 52
binäre, 70
Suche
ganze, 65
binäre, 109
hexadezimale, 70
super, 232 komplexe, 65, 69
sympy, 393 natürliche, 65
rationale, 65
Syntax highlighting, 37 reelle, 65
sys, 363 Zahlsysteme, 70

462
ANHANG E. INDEX

Zeichenketten, 81, Siehe auch String 86, Siehe auch Zeilenvorschub, 82


Text 86 Zuweisungsmuster, 63
Teilbereiche von, 84 Zuweisungsoperator, 52, 58, 62

463

Das könnte Ihnen auch gefallen