You are on page 1of 436

Bernd KLEIN

EINFÜHRUNG IN

PYTHON
IN EINER WOCHE PROGRAMMIEREN LERNEN

3

Im Internet: Musterlösungen zu den Übungen

Klein

Einführung in Python 3

CHV Newsletterhinweis Computer
Bleiben Sie auf dem Laufenden! Der Hanser Computerbuch-Newsletter informiert Sie regelmäßig über neue Bücher und Termine aus den verschiedenen Bereichen der IT. Profitieren Sie auch von Gewinnspielen und exklusiven Leseproben. Gleich anmelden unter www.hanser-fachbuch.de/newsletter

 

Bernd Klein

Einführung in Python 3
In einer Woche programmieren lernen

 

Der Autor: Bernd Klein, bernd@python-kurs.eu

Alle in diesem Buch enthaltenen Informationen, Verfahren und Darstellungen wurden nach bestem Wissen zusammengestellt und mit Sorgfalt getestet. Dennoch sind Fehler nicht ganz auszuschließen. Aus diesem Grund sind die im vorliegenden Buch enthaltenen Informationen mit keiner Verpflichtung oder Garantie irgendeiner Art verbunden. Autor und Verlag übernehmen infolgedessen keine juristische Verantwortung und werden keine daraus folgende oder sonstige Haftung übernehmen, die auf irgendeine Art aus der Benutzung dieser Informationen – oder Teilen davon – entsteht. Ebenso übernehmen Autor und Verlag keine Gewähr dafür, dass beschriebene Verfahren usw. frei von Schutzrechten Dritter sind. Die Wiedergabe von Gebrauchsnamen, Handelsnamen, Waren­ be­ ­­ zeich­­ nungen usw. in diesem Buch berechtigt deshalb auch ohne besondere Kennzeichnung nicht zu der Annahme, dass solche Namen im Sinne der Warenzeichen- und MarkenschutzGesetzgebung als frei zu betrachten wären und daher von jedermann benutzt werden dürften.

Bibliografische Information der Deutschen Nationalbibliothek: Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen National­ biblio­ grafie; detaillierte bibliografische Daten sind im Internet über http://dnb.d-nb.de abrufbar. Dieses Werk ist urheberrechtlich geschützt. Alle Rechte, auch die der Übersetzung, des Nachdruckes und der Vervielfältigung des Buches, oder Teilen daraus, vorbehalten. Kein Teil des Werkes darf ohne schriftliche Genehmigung des Verlages in irgendeiner Form (Fotokopie, Mikrofilm oder ein anderes Verfahren) – auch nicht für Zwecke der Unterrichtsgestaltung – reproduziert oder unter Verwendung elektronischer Systeme verarbeitet, vervielfältigt oder verbreitet werden. © 2013 Carl Hanser Verlag München, www.hanser-fachbuch.de Lektorat: Brigitte Bauer-Schiewek Herstellung: Irene Weilhart Fachlektorat: Stefan Günther, Hanau Copy editing: Jürgen Dubau, Freiburg/Elbe Layout: le-tex publishing services, Leipzig Umschlagdesign: Marc Müller-Bremer, www.rebranding.de, München Umschlagrealisation: Stephan Rönigk Druck und Bindung: Kösel, Krugzell Ausstattung patentrechtlich geschützt. Kösel FD 351, Patent-Nr. 0748702 Printed in Germany

print-ISBN: 978-3-446-43547-6 e-book-ISBN: 978-3-446-43717-3

Inhalt

Vorwort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XVII Danksagung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XIX 1
1.1 1.2 1.3 1.4 1.5 1.6

Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Programmieren lernen in einer Woche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Aufbau des Buches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zielgruppe des Buches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Programmieren lernen „interaktiv” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Download der Beispiele und Hilfe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Anregungen und Kritik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1
1 2 3 4 4 5

Teil I 2
2.1

Einführung in Python 3 – Für Ein- und Umsteiger . . . . . . . . . . . . . . . . . . . . . . Kommandos und Programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Erste Schritte mit Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1 2.1.2 Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Erste Schritte in der interaktiven Shell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7 9
9 9 10 11 11 13 13 14 14

2.2 2.3 2.4 2.5 2.6

Herkunft und Bedeutung des Begriffes interaktive Shell . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.1 Verlassen der Python-Shell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Benutzung von Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mehrzeilige Anweisungen in der interaktiven Shell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Programme schreiben oder schnell mal der Welt “Hallo” sagen . . . . . . . . . . . . . . . . . . .

3
3.1 3.2 3.3

Bytecode und Maschinencode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Unterschied zwischen Programmier- und Skriptsprachen . . . . . . . . . . . . . . . . . . . . . . . . . Interpreter- oder Compilersprache. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 17 17

VI

Inhalt

4
4.1 4.2 4.3 4.4

Datentypen und Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Statische und dynamische Typdeklaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Typumwandlung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Datentyp ermitteln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 22 24 25

5
5.1

Sequentielle Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Übersicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1.1 5.1.2 5.1.3 5.1.4 Zeichenketten oder Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Listen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tupel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sequenz von Binärdaten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 27 28 28 28 28 30 31

5.2 5.3 5.4

Indizierung von sequentiellen Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Slicing oder Ausschneiden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Aufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6
6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 6.10

Dictionaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Dictionaries und assoziative Felder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Definition und Benutzung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fehlerfreie Zugriffe auf Dictionaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zulässige Typen für Schlüssel und Werte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Verschachtelte Dictionaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Methoden auf Dictionaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zip. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dictionaries aus Listen erzeugen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Aufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 34 36 37 37 38 41 42 43 44

7
7.1 7.2

Mengen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
Übersicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mengen in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.2.1 7.2.2 Sets erzeugen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mengen von unveränderlichen Elementen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 47 48 48 49 49 49 50 50 50

7.3 7.4

Frozensets. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Operationen auf „set”-Objekten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.4.1 7.4.2 7.4.3 7.4.4 add(element). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . clear() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . copy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . difference() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Inhalt

VII

7.4.5 7.4.6 7.4.7 7.4.8 7.4.9

difference_update() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . discard(el) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . remove(el) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . intersection(s) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . isdisjoint() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

51 51 52 52 52 53 53 53

7.4.10 issubset() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.4.11 issuperset() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.4.12 pop() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8
8.1 8.2 8.3 8.4 8.5

Verzweigungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
Verzweigungen im Allgemeinen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Bedingte Anweisungen in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Beispiel Hundejahre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Wahr oder falsch: Bedingungen in Verzweigungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Aufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 55 56 57 58

9
9.1 9.2 9.3 9.4 9.5

Schleifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
Übersicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . while-Schleife . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . die Alternative im Erfolgsfall: else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . For-Schleife . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Aufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 60 61 62 65

10
10.1 10.2 10.3 10.4 10.5

Dateien lesen und schreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Text aus einer Datei lesen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Schreiben in eine Datei . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . In einem Rutsch lesen: readlines und read . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Aufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 69 71 71 72

11
11.1 11.2 11.3 11.4 11.5 11.6 11.7 11.8

Listen und Tupel im Detail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
Stapelspeicher . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Stapelverarbeitung in Python: pop und append. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . extend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Entfernen eines Wertes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Prüfen, ob ein Element in Liste enthalten ist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Finden der Position eines Elementes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Einfügen von Elementen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Besonderheiten bei Tupel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 76 77 77 78 78 79 79

. . . . . . . . . . . . . . . . 109 14. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 Lokale und globale Variablen in Funktionen. . . . . . . . 106 Mehrere Rückgabewerte . 104 Optionale Parameter . . . . . . 13 13. . . . . . . . . . . 103 Allgemein . . . . . . . . . . . . . . . . . . . . . . . . .1. . . . . . . . . . . . . . . .5 14. . . . . . . . 12. . . . . . . . . . . . . . . .10. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11. . . . . . . . . . . . . . . . . . . . . . . . . . .1.1 14. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 14.7 14. . . . . . . . . . . . . . . . . . . . . . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . .4 Suchpfad für Module . . . . . . . . . . . . . . . . . .3 Mehrfachzuweisungen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 13. . . . . . . . . . . . . . . 11. . . . . . .8 14. . . . . . . . . . . . 12. .10 Sortieren von Listen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6 14. . . . . 110 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 14. . . . . . .1. . . . . . . . . . . . . . 108 Beliebige Anzahl von Parametern . . . . . . . . . . . . . . . . . . . . . . . . .3 13. . . . . . . . . . . . . . . . . . . . . 11. . . . . . . . . . . . .2 13. . . . . . . . . . . . 106 Schlüsselwortparameter . . . . . . . . . . 101 14 14. . . . 89 90 91 91 92 93 93 94 95 12. . . . . . . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 99 Kopie mit Teilbereichsoperator . . . . . . . . . . . . . . . . . . .1 Leere Tupel . . . . . . . . . . . . 12. 11. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 Namensräume von Modulen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12. . . . . . . . . . . . . . . . . . . . . . .10. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 Deepcopy für Dictionaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 Umkehrung der Sortierreihenfolge . . . .2 Pakete. . . . . . . . . . . . . . . . . . . . . . . . .3 Modularten. 105 Docstring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 Modularisierung . . . . . . . . . . . . . . . . . . . . . . . . . . 12. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1. . . . . . . . . . . . . . . . . . . . .1 „sort” und „sorted” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8. . . . . . . . . . . . . .9 Die veränderliche Unveränderliche . . . . . . . . . . . . . . . . 12. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .VIII Inhalt 11. . . . . . . . . . . . . . . . . .4 14. . . . . . . . . . . . . . . . . . . . . . . . . . . .10 Parameterübergabe. . . . . . . . . . . . . . . . . . . .11 Aufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6 Eigene Module . . . . . . . . . . . . . . . . . . . . . .3 Eigene Sortierfunktionen . .2 1-Tupel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9 Funktionen . . . . . . . . . . . . . . . .8. . . . . . . . . . . . . . . . . . 103 Funktionen in Python . . . . . . . . . . . . . . . . . . . . . . . . . .8. . . . . 80 80 81 81 82 82 83 83 86 12 12. . . . . . . . . . . . . . . . . . . . Kopieren einer Liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11. . . . . . . . . . . . . . . . . . . . . 11. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10. . . . . . . . . . . . . . . . . . . . . . . . . .5 Inhalt eines Modules. . . . . . . . . . . . . . .1. . . . . . . . . . . . . . . . . . . . . . . .7 Dokumentation für eigene Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 Namensräume umbenennen . . . . . . . . . . . . . . . . . . . . . . 100 Kopieren mit deepcopy aus dem Modul copy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 13. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 Rückgabewerte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5 Flaches und tiefes Kopieren . . . . . . . . . . . 11. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Packing und Unpacking . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .4. . . . . . . . . . 120 Aufgaben . . .11 Nebeneffekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 14. . . 127 Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . start[. . . . . . . . . . . . . . . .2 Globale und lokale Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 Standardverhalten und „maxsplit” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5 splitlines . . . . . . . . . . . . . . . . . . . . . . . . . .1 „in” oder „not in” . . . . . . . . . . . . . . . . . 140 17. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 15 15. . . . . . . . . . . .4 Zusammenfügen von Stringlisten mit join . . . . . . . . . . . . . . . . . . . 131 Aufspalten von Zeichenketten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 16. . . . . . . . . . . . . . . . . . . . . . . . . . . 132 17. . . . . .5 15. . . . . . . . . . . . . . . . . .6 partition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . end]]). . . . . . . . . . . . . . . . . . . .5 s. . . . . . . . . . . . . . . . . . . . 113 14. . . . . . . . . . . . . . . . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . end]]) . . . . .2 15. . . . . . . . . . . . . . . . . 118 Die Tücken der Rekursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 17. . . . . . . . .6 s. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 17. . . . . . . . . . . start[. . . . 143 capitalize und title . . . . . . . . . . . . . . end]]) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6 Rekursive Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 s. . . . .6 17. . . . . .Inhalt IX 14. . . . . . . . . . . . . . . . . 136 17. . . . . . . . . . . 127 Globale und lokale Variablen in Funktionen . . . . . . . . . . . . .12 Kommandozeilenparameter . .3 s. . . . . . . . . . . . . . 140 17. . 134 17. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 17. . . . . . . . . . .3 15. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 Definition der Rekursion. . . . . . . 140 17.4. . . . . 138 17. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 split . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 15. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 17 17. . . . . . . . . . . . . . . . . . . .. 142 Nur noch Kleinbuchstaben oder Großbuchstaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 17. . . . . . . . . . . . . . . . . . . . . . 124 16 16. . . . . . . . . . . . . . . . . . .4. . . . . . 132 17. . . . . . . . . .16 Doppeltes Sternchen im Funktionsaufruf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 rsplit . . . . . . . . . . . . . . . . . . . . . . . . . . . .2. . . . . . . . . . . 118 rekursive Funktionen in Python . end]]) . . . . . . . . . . . .4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .rfind(substring[. . . . .2. . . . . . . . . . . . . .2. . . . . . . . . . . . . . .1 17. . . . . . . . . . . . . . . . . . . 142 17. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5 17. . .14 * in Funktionsaufrufen . . . . . .13 Variable Anzahl von Parametern. . . . . . . . . . . . . . .4. . . . . . . . . . . . 112 14. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .count(substring[. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . start[. . . . . . . . . . . . . . . . . . . . . . . . . . . .1 15.7 Suchen und Ersetzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 . . . . . . . . . . . . . . . . . . . . . . . start[. . . . . . . 139 Suchen von Teilstrings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 Folge von Trennzeichen . . . . . . . . . . . . . . . . . . . .index(substring[. . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 Definition und Herkunft des Begriffs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 14. . . . . . . . . . . . . start[. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .rindex(substring[. . . . . . . . . .4 s. . .2. . . . . . . . . . . . 119 Fibonacci-Folge in Python. . . . . . . . . . . . end]]) . . .4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 14. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . 141 17. . . . . . . . . . . . . . . . . . . 131 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 Alles über Strings . . . . . . . . . . . . . . fast alles . . . . 137 17. . . . . . . .find(substring[. . . .15 Beliebige Schlüsselwortparameter . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 Finalisierungsaktion . . . .3 18. . . . . . . . . . . . . . . . . . . . . . 162 19. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 19. . . . . 161 19. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177 . . . . . . . . . . . .4 18. . . . . . . . . . . . . . . . .5 18. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 except mit mehrfachen Ausnahmen . . . . . . . . . . . . . 163 19. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 19 19. . . . . . . . . . . . . . 160 19. . . . . . . . . . . . . . . . . . . . . . . . . . .2 Diamand-Problem oder „deadly diamond of death” . . . . . . . . . . . . . . . . . . 156 Kapselung von Daten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 17. . . . . . . . . . . . . . . . . . . . 151 Abfangen mehrerer Exceptions . . . . 155 Einführung . . . . . . . . . . . . . . . . . . . . . . . 164 19. 174 19. . . . . . . . . . .10 Destruktor .13 Datenkapselung und die Benutzung von Public. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 Vererbung . .14 Statische Member . . . . . . . . . . . . . . . . . . . . . . . . .12 „Öffentlicher Schönheitsfehler” oder Public-Attribute . . . . . . . . . . . . . . . . . . . 168 19. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8 17. . . . . . . . . . . . . . . . . . .3 Beispiel: CalendarClock . . . . . . . . . . . . . . . . . . . .18. . . . . . . . . . . .17. . . . . . . . . . . . . . . . .11 Lauffähige Version der Kontoklasse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 18. . . . . . . . . . . . . . . . 144 Strings ausrichten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 19. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 __del__ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .X Inhalt 17. . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 Theorie. . . . . . . . . . . . . . .exc_info . . . . . . . . . . . . . . . . . . 176 19. . . . . . . . . . . . . . . . 156 Klasse . . . . . . . . . . . . . . . . . . . . . . . . . .1 Oberbegriffe und Oberklassen . . . . . . . . . . . . . 156 Objekte . . . . . . . . . . . . . . . . . . . . . . . . .2 Vererbung in Python . . .11 Aufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 19. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .und PrivateAttributen . . . . . . . . . . . . . . . . . . . . . . . . 155 Die Kuchenklasse . . . . 169 19. . . .15 Properties . . . . . . . . . . . . . . . . . . 150 Fehlerinformationen über sys. . . . .14. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 19. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170 19. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8 19.10 String-Tests . . . . . . . . . . . . . . . . . . 158 Klassen in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 Exceptions generieren. . . . . . . . . . . . . . . . 147 18 18. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 18. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .16 Dynamische und statische Attribute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6 19. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 19. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Protected. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5 19. . . . . . . . . . . . . . . . . . . . . . . . 159 Konstruktor .9 Stripping Strings . . . . . . . .7 19. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 19. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9 Objektorientierte Programmierung . . . . . . 145 17. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 Vererbung . . . . . .3 19. . . . . . . . . .2 19. . . . . . . . . . . . . . . . . . . . . . . .17. . . . . . . . .18. . . . . . . 169 19. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 Die optionale else-Klausel . .18 Mehrfachvererbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6 Ausnahmebehandlung . . . . . . . . . . . . . . . .18. . . .

. . . . . . . . . . . . . . . .8 Weiterführende Themen . . . . . . . . . . . . 249 22 22. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3. 187 19. . . . . . . . . . . . . . . . . . . . . .7 20. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .21 Standardklassen als Basisklassen . . . . . . . . . . . . . . . . . . . 255 Fork in Python . . . . . . . . . . . . 211 os-Modul . . . . . . . . . . . . . . . . . . . . . . . .22 Aufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 21. . . . . . . . . . . . . . . . . . . 211 Häufig falsch verstanden: Shell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 Systemprogrammierung . . . . . . . . . . . . . . . . . . . . . . . . . . .3 20. . . . . . . . . .4 20. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209 21 21. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 21. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6 os. . . . .4 shutil-Modul . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 Tests und Fehler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 19. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5 20. . . . . . . . . . . . . . . . .6 20. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 doctest-Modul . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212 21. 188 19. . . . . . . 206 Aufgaben . . . . . . . . .Inhalt XI 19. . . . . 195 Modultests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .19 Polymorphie . . . . . . . . .2 21. . . . . . . . . . . . . . . . 226 21. . . . . . . . . . . . . . 197 Modultests unter Benutzung von __name__ . . . . . . . . . . . . . . . . . . . .20 Operator-Überladung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 21. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215 21. . . . . . . . . . . . . . . 213 21. . . . . . . . . . . . . . . . 200 Testgetriebene Entwicklung oder „Im Anfang war der Test” . . . . . . . . . .3. .1 23. . . . . . . . .path . . . . . . . . . . . . . . . . . . . . . . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213 21. . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 Das Modul „pickle” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255 Fork . . . . . . . . . . . . . . . . . . . . . . .2 Forks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255 23 23. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .load . . . . . . . . . . . . . . . 195 Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5 Weitere Funktionen im Überblick. . . . . . . . 189 Teil II 20 20. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Arbeiten mit Pfaden . . . . . . . .3. . . . . . . . . . . . . . . .1 Vorbemerkungen . . . . . . . . . . . . . . . . . . .2 Umgebungsvariablen . . . . . . . . . . . . . . . . . . . . . . . 260 . . . . . . . . 259 Daten „einpökeln” mit pickle. . . . . . . . . . . . . . . . . .1 22. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 20. . . . . . . . . . . . . . . . . . . . . . . . . . 204 Methoden der Klasse TestCase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202 unittest . . . . . . . . . . . . . . . . . . .4 Die exec-„Familie” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 pickle. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .dump . . .3 Dateiverarbeitung auf niedrigerer Ebene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211 Systemprogrammierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 20. . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . .18. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 Endliche Automaten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .13 Gruppierungen und Rückwärtsreferenzen . . . . . . . . . . . . . . filter und reduce . . . . . . . . . . 261 Überlappungen und Teilstrings . . . 294 reduce . . . . . . 296 26 26. . . . . . . . . . . . . . . . . . . . .9 Reguläre Ausdrücke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267 Vordefinierte Zeichenklassen . . . . . . . . . . . . . . . . . . . .5 24. . . . 261 Stringvergleiche . . . . . . . . . . .16 Alternativen . . . . . .1 Beliebiges Zeichen . . . . . . . . . . . . .1 26. . . . . . . . . . . . 279 24. . . . 263 Matching-Problem. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .19 Suchen und Ersetzen mit sub . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10 Anfang und Ende eines Strings. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .XII Inhalt 24 24. . . . . . . . . . . . .5 lambda. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .11 Optionale Teile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .14 Umfangreiche Übung . . . . . . . .7 24. . . . . . . . . . . . . . . . . . . 282 24. . . . . . . . . . . . . . . . . . . . .2 24. . . . . 297 Die Alternative zu Lambda und Co. . . . .17 Kompilierung von regulären Ausdrücken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .12 Quantoren . . . 285 24. . . . . . . . . . . . . . . . . . . . . . . . 268 24. . . . . .1 split-Methode der String-Klasse. . 289 map . . . . . . . . . . . . . . . . . . . 286 24. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6 24. . . . . . . . . . . . .20 Aufgaben . . . . . . . 272 24. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261 Ursprünge und Verbreitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .13. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286 25 25. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 24. . . . . . . . . . . . . . .2 26. . . . . . 297 Einführung in die Listen-Abstraktion . . . . . . . . . . . . . . . . . . . . . . . . . 283 24. . . . . . . . . . . . . . . . . . 274 24. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280 24. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289 lambda . . . . . . . . . . . .4 25. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8 24. 282 24. . . . . . . . . .2 25. . . . . . . . . . . . . 264 Syntax der regulären Ausdrücke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274 24. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298 Weitere Beispiele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6. . . . . . . . . . . . . . . 299 . . . . .1 25. . . . . . . . . . . . . . . . . . . . . . . .3 26. . . . . . . . . . . . .4 Listen-Abstraktion/List Comprehension . . . . . . .2 split-Methode des re-Moduls .1 24. . . . . . . . . . . . . . . . . . . . . .18. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .18. . . . . . . . . . 276 24. . . . . . . . . . . . . . . . . . . 278 24. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 25. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271 24. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . map. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 Zeichenauswahl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 24. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .15 Alles finden mit findall . . . . . . . . . . . . . . . . . 297 Syntax. . . . . . . . .3 Wörter filtern . . . 294 Aufgaben . . . . . . . . . . . . . . . . . . . . 269 24. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 Das re-Modul . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292 Filtern von sequentiellen Datentypen mittels „filter” . . . . .18 Aufspalten eines Strings mit oder ohne regulären Ausdruck . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 Match-Objekte . .4 24. . . .

. . . . .5 Memoisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 Generatoren und Iteratoren . . . . . . . . . . . . . . . . . 321 29 29.7 26. . . . . . . . . . . . . . . . neue Dimension hinzufügen . . . . . . . . . . . 305 Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333 Vektoraddition und Vektorsubtraktion . 317 Memoisation mit Dekorateur-Funktionen . .9 Die zugrunde liegende Idee . . . . . . . . . . . . . . . . . . . . . . . 302 26. . . . . . . . . . . . . .1 Permutationen . . . . . . . . .7 29. 323 Übersicht . . . . . . . . . . . . 317 Bedeutung und Herkunft des Begriffes . . . . . . 300 Mengen-Abstraktion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313 Aufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299 Anspruchsvolleres Beispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319 Dekorateure in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 27. . . . . . .2 Eine einfache praktische Anwendung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 29. . . . . . . . . . . . . . . . . . . . . . . . . .3 27. . . . . . . . . . . . . . . . . . . . . . . 309 27. . . . . . . . . . .2 27. 318 Memoize in einer Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 29. . . . . . . . . . . . . . . . . . . . . . . . . .3 28. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7 27. . . . . . . . . . . . . . . . . . . 301 Generator Comprehension/ Generatoren-Abstraktion. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323 Arrays in NumPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9 NumPy . . . . . . . . . . . . . . 312 Generator-Ausdrücke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 Variationen und Kombinationen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332 Matrizenarithmetik . . . . . . . . . . . . . . . . . . .5 27. . . . . . . . . . . . . . . . . . . . . . . . .6 26. . . . . . . . . . . . . . . . . . . .2 28. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4. . . . . . . 327 Arrays umdimensionieren . . . . . . . . . . . . . . . . . . . . . . . .Inhalt XIII 26. . 312 send-Methode . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309 27. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4. . 314 28 28. . . . . . . . . . . . . . . . . . .1 Matrix-Produkt . . . . . . . . . . . . . 303 27 27. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 28. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 28. . . . . . . . . . . . . . . . . . . . . . . . . . 334 29. . . . . . . . . . . .8 29. . . . . . . . . . .8 Generatoren zähmen mit firstn und islice. . . . . . . . 305 Generatoren . . . . . . . . . .5 26. . . . . . . . . . . . . . . . . . . . . . . . .4 29. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337 29. . . . . . . . . . . . 319 Überprüfung von Argumenten durch Dekorateure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325 Arrays flach machen . . . . . . . . . . . . . . . . . . . . . . . . . . .10 Aufgaben . . .10. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301 Rekursive Funktion zur Berechnung der Primzahlen . . . . . . . . . . . . . . . . . . . . .5 29. . . . . . . . . . . . . . . . . . . . . . . . 336 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330 Array. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305 Iteration in for-Schleifen . . . . . . . . . . . . . . . . . . . . . . . . 328 Arrays konkatenieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10 Matrix-Klasse . . . . . . . . . . . . . . . . . . . .10. . . .8 26. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307 Beispiele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6 29. . . . .6 27. . . . . . . . . . . . . . . . . . . . 338 29. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332 Array mit Nullen und Einsen initialisieren . . . . . . . . . . . . . . . . . . . . . . .3 29. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310 27. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . 352 30. . . . . . . . . . . . . . . . . . . . . 360 32 32. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357 Die Spielregeln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353 30. .12 Kreuzprodukt / Vektorprodukt . . 340 29. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 Document-Klasse . . . . . . . . . . . . . . . . . . . . . . . . .3 Umfassende Beispiele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .15 Aufgaben . .3. . . . . . . . . . . . . . . . . . . . . . . . . . .2. . . . . . . . . . . . . . . . . . . 368 Textklassifikation in Python . 370 32. . . . . .2 Mastermind . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 30. . . . . . . . . . . . .2 Bayes-Theorem . . . . . . . . . . . . 340 29. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367 Naive-Bayes-Klassifikator. . . . . 370 32. . . . . . . . . . . . . . . . . . . . . . . . .5. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 BagOfWords-Klasse . . . .14 Polynome . . . . . . . . . . . . . . . . . . . . .2 Division von Brüchen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3. . . . . . . . .1 „Bulls and Cows” . . . . . . . . . . . . .2 Mastermind . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371 32. . . . . . 367 32. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374 . . . . . . . . . . .13 Lineare Gleichungssysteme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358 31. . . . . . . .2 32. . . . . . . . . . . . . . . . . . . . . . . . . . . . .5. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 32. . . . . . . . . .5 Die Bruchklasse im Überblick . . . . . . . . . . . . . . . . . . . . . . .4 Pool-Klasse . . . . . . . . . . . . . . . . . . . . . . . . . . . 342 29. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358 31. . . . . . . . . . . 339 29. . . . . . . . . . . . . . 358 31. . 367 32. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5 Formale Herleitung der Naive-Bayes-Klassifikation . . . 354 31 31. . . . . . . . . . . . . . . . . 348 Rechenregeln . . . . . . . . . . . . . . . .3 Textklassifikation . . . . . . . . . . . . . . . . . . . . . .1 Multiplikation von Brüchen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 30. . . . . . . . . . . . . . . . . . . . . . . . . . . 365 Einführung in die Textklassifikation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367 32. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 DocumentClass-Klasse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 Addition von Brüchen . . . . . . . . . . . . .3. . . .1 Definition. . . . . . . . . . . . . . . . . 353 30. . . . . 347 Brüche à la 1001 Nacht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . .5. . . . . . 359 Mastermind in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 31. . . . . . . . . . . . . . . .3. . . . . . . . . . . . . . . . . . . . . .3. . . . .5. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 Subtraktion von Brüchen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365 Textklassifikation: Aufgabe . . . . . . . . . . . .XIV Inhalt 29. . . . . . . . . . . . . . . . . 347 Zurück in die Gegenwart . . . . . . . . . . . 351 30. . . . . . . . .1 31. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 32. . . . . . . . . . . . . 351 30. . . . . . . . . . . . . . . . . . . . . . . .11 Inverse Matrix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343 Teil III 30 30. . . . . . . . . . . . . 345 Bruchklasse . . . . 357 Die Ursprünge des Spiels . . . . . . 373 32. . . . .3. . . . . . . . . . . . . . . . . .4 Kombinatorikmodul . . . . . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410 33. . . . . . . . . . . . .5 33. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6 33. . . . . . . . . . . . . . . . . . . .12 Lösungen zu Kapitel 25 (lambda. . 405 33. . . . . . . . 411 33. . . . . . . . . . . . . 383 Lösungen zu Kapitel 9 (Schleifen) . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) . . . . . . . . . . . . . . . . . . 385 Lösungen zu Kapitel 10 (Dateien lesen und schreiben) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388 Lösungen zu Kapitel 11 (Listen und Tupel im Detail) . . . . . . . . . 379 Lösungen zu Kapitel 5 (Sequentielle Datentypen) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 33. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379 Lösungen zu Kapitel 6 (Dictionaries) . . . . . . . . . . . . . . . . . . . . . . .Inhalt XV 33 33. . . . . . . . . . . . . .7 33. 417 . . . . . . . . . . . . . . .15 Lösungen zu Kapitel 29 (NumPy) . . 381 Lösungen zu Kapitel 8 (Verzweigungen) . . . . . . . . . . . . . . . . . . . 400 33. . .9 Lösungen zu den Aufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415 Stichwortverzeichnis . . . . . . . . . . 390 Lösungen zu Kapitel 15 (Rekursive Funktionen) . . . . . . . . . . filter und reduce) . . . . . . . . . .8 33. . . . . . . .3 33. . . . . . . . . . . . . . . . 397 Lösungen zu Kapitel 19 (Objektorientierte Programmierung) . . 393 Lösungen zu Kapitel 17 (Alles über Strings . . . . . . . . . . . 412 33. . . . . . . . . . . . . . . . .10 Lösungen zu Kapitel 20 (Tests und Fehler) . . . . . . . . . . . . .4 33. . . . . . . . . . . . . . . . . . . . . . . map. . . . . . . . . . . . . . . .1 33. 405 33. . . . . . . . . . . . .11 Lösungen zu Kapitel 24 (Reguläre Ausdrücke) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .14 Lösungen zu Kapitel 27 (Generatoren und Iteratoren) . . . . . . .13 Lösungen zu Kapitel 26 (Listen-Abstraktion/List Comprehension) . . . . . .

.

Brigitte Bauer-Schiewek. auf Übersichtlichkeit optimiert ist. Auch Programme in anderen Sprachen lassen sich einfach als Module in Python einbetten. Gerade für Programmieranfänger besteht die Schwierigkeit darin. Ein weiterer Unterschied zu Java besteht darin. d. dass in Python Mehrfachvererbung möglich ist. So kann man beispielsweise zeitkritische Algorithmen in C programmieren und sie dann in Python einbinden.h. also der Aufbau der Sprache. Zusammenfassend kann man sagen. Lektorin . In diesem Sinne finden Sie in diesem Buch den idealen Einstieg. es gibt keine primitiven Typen. Das war bereits beim anfänglichen Design der Sprache eines der wesentlichen Ziele ihres „Erfinders” Guido van Rossum. dass es sich bei Python um eine Programmiersprache handelt. als er Python Anfang der 1990er Jahre am Zentrum für Mathematik und Informatik (Centrum voor Wiskunde en Informatica) in Amsterdam entwarf.Vorwort Bedingt durch den traumhaften Anstieg der Bedeutung von Python in der Wissenschaft und Wirtschaft in den letzten Jahren gibt es auch ein wachsendes Interesse an geeigneten Python-Büchern. Dies ist besonders schade. So sind in Python alles Objekte. was zwar viele Vorzüge haben mag. in manchen Dingen sogar konsequenter als Java. aber für Anfängerinnen und Anfänger völlig ungeeignet ist. die sich bestens zum Einstieg in die Programmierung eignet. da es sich bei Python ja um eine einfache Programmiersprache handelt. Der unüberlegte Griff ins Bücherregal führt schnell zum Kauf eines Buches. Selbst Integer und Float-Zahlen sind in Python als Klassen realisiert. ein geeignetes Buch zu finden. Auch im Bereich objektorientierte Programmierung ist Python sehr konsequent. Python ist einfach. aber auch die optimale Lösung für Spezialisten aus zahlreichen Problemfelder ist. weil es mit erstaunlich wenigen Schlüsselwörtern auskommt und seine Syntax.

.

vor allem denjenigen. die mich während dieser Zeit tatkräftig unterstützt hatte. die mir geholfen haben. Zuletzt danke ich auch ganz herzlich dem Hanser Verlag.eu und www. Außerdem danke ich den zahlreichen Teilnehmern an meinen Python-Kursen.python-course. Ebenso möchte ich den Besuchern meiner Online-Tutorials unter www. Bernd Klein. Vor allem danke ich Frau Brigitte Bauer-Schiewek.pythonkurs. Lektorat und Online-Marketing. meine didaktischen und fachlichen Kenntnisse kontinuierlich zu verbessern. Singen . für die kontinuierliche ausgezeichnete Unterstützung. der mir viele kleine und große Ungenauigkeiten übermittelte und auch dieses Buch nochmals kritisch gelesen hat. Herrn Jürgen Dubau danke ich fürs Lektorat. Für die technische Unterstützung bei LaTex-Problemen danke ich Herrn Uwe Hartmann und Herrn Stephan Korell. Programmplanung Computerbuch.eu danken. die sich mit konstruktiven Anmerkungen bei mir gemeldet haben. die vor allem die Familie mitzutragen hat. Deshalb gilt mein besonderer Dank meiner Frau Karola. Zeit außerhalb des üblichen Rahmens. der dieses Buch ermöglicht hat. Zeit.Danksagung Zum Schreiben eines Buches benötigt es neben der nötigen Erfahrung und Kompetenz im Fachgebiet vor allem viel Zeit. und Frau Sarah Merz. Allen voran Stefan Günther.

dass man bis zehn oder zwanzig zählen kann. und vor allen Dingen – was uns am wichtigsten ist – konnten wir immer die Begeisterung für die Sprache Python entfachen. dass man Leute begrüßen kann. Was hat man sich zum Ziel gesetzt? Will man am Ende komplexe Aufgaben wie Routenplaner. dass Sie „programmieren gelernt haben”? Können Sie nun selbständig und problemlos auch komplexeste Probleme lösen? Lassen Sie es mich mit natürlichen Sprachen vergleichen. Sie werden zum einen von totalen Programmieranfängern und zum anderen von Programmierern mit Erfahrungen in anderen Programmiersprachen wie beispielsweise C. C++. wenn man einfache Konversationen mit Muttersprachlern führen. Will man jedoch überhaupt Shakespeare oder Joyce im Original lesen oder genügt es einem schon. definitiv! Wir erfahren es mehrmals im Monat in unseren meist fünftägigen Python-Kursen. aber auch nach einem Jahr wird man selten in der Lage sein. Man kann in wenigen Stunden soviel Englisch oder eine andere Sprache lernen.1 Einleitung Programmieren lernen in einer Woche Kann man in einer Woche programmieren lernen. Webcrawler. entschuldigen oder nach dem Weg fragen kann usw. Shakespeare oder James Joyce im englischen Original zu lesen. dass man sich bedanken. Perl und nicht zu vergessen Shell-Programmierung besucht. so wie es der Titel des Buches verspricht? Genauer gesagt: Kann man in einer Woche mit Python programmieren lernen? Was meinen wir überhaupt mit einer Woche? „Acht Tage” – und gemeint sind sieben – oder denken wir an eine Arbeitswoche mit fünf Tagen? Wie viel Stunden sollte man dann pro Tag an dem Buch arbeiten? Jeweils ein voller Arbeitstag oder ein paar Minuten oder Stunden zwischendurch? Die Liste der Fragen könnten wir noch beliebig fortsetzen. Nachrichten verstehen und Zeitungsartikel lesen kann? So ähnlich verhält es sich auch mit Programmiersprachen und der Programmierung im Allgemeinen. dass unsere Teilnehmerinnen und Teilnehmer programmieren gelernt haben. Manche haben auch schon vorher mehr oder weniger viel Erfahrung in Python gesammelt. Suchalgorithmen oder Ähnliches programmieren können oder möchte man vielmehr kleine oder mittlere praktische Probleme lösen? . Nun mögen Sie fragen. Formulieren wir die Hauptfrage einfach um: Kann man in wenigen Tagen programmieren lernen? Das ist möglich. Java.1 1. Aber eines war in allen Gruppen gleich: Wir haben es immer geschafft.. was bedeutet es.

So ist beispielsweise das Kapitel zur Systemprogrammierung von besonderer Wichtigkeit für Systemprogrammierer. NumPy ist insbesondere für Mathematiker und Ingenieure von besonderem Interesse. aber sie sind von unterschiedlicher Wichtigkeit für verschiedene Anwender und Anwendungszwecke. so sieht es in diesem Teil anders aus. Man kann sich immer wieder (selbst als anerkannter Experte) an kleinen neu gefundenen Details erfreuen. Dabei verwenden wir viele kleine Beispiele und Übungsaufgaben. Dennoch kann man die gleichen Programme auch ohne diese Techniken schreiben.2 Teil I: Aufbau des Buches Dieses Buch besteht aus vier Teilen: In diesem Teil behandeln wir die Grundlagen der Sprache. die wir bereits im 1. bieten eine faszinierende Möglichkeit. „Matrizenmultiplikation” oder „Nullstellen von Polynomen”. Dies sind zum einen weitere Sprachkonstrukte. Während es im ersten Teil prinzipiell keine Gebiete gibt. also beispielsweise „numerisches Lösen von Gleichungssystemen”. die nahezu unerlässlich sind.und reduceFunktionen. Sie werden sehen. den man durcharbeiten sollte. die unmittelbar zum Sprachumfang von Python gehören und um wichtige Module und Programmierkonzepte. Teil III: In diesem Teil wenden wir das im 1.oder Parameterdateien bestimmte Informationen herausfiltern will. 1. Dieser Teil wird auch in unseren fünftägigen Kursen komplett behandelt.2 1 Einleitung Apropos „am Ende”: Wie auch beim Sprachen lernen gibt es kein Ende. die man weglassen kann. Im nächsten Teil behandeln wir weiterführende Themen. die ihre Systemprogramme zukünftig unter Python und nicht mehr mit Shell-Skripting schreiben wollen. wie Teil II: . Dadurch kann man komplexere Probleme mit geringerem Programmieraufwand lösen. die gerne numerische Probleme effizient mit Python bearbeiten wollen. wenn man Python lernen will. Programmieren lernen ist eine lebenslange Angelegenheit. Aber das einführende Kapitel über Testverfahren und Debugging ist von allgemeinem Interesse. Teil behandelt haben. Teil gelernte Wissen in umfassenden Beispielen an. Im Prinzip hätten wir dieses Kapitel ebenso gut in den ersten Teil nehmen können. Dies ist der eigentliche Stoff. wenn wir von „Programmieren lernen in einer Woche” sprechen. filter. map-. Außerdem behandeln wir in einem Kapitel „Reguläre Ausdrücke”. wenn man aus Log. die Programmierung auf ein abstrakteres Level zu bringen. Man braucht sie auch. Die Listen-Abstraktionen. An die Bearbeitung dieses Teiles denken wir auch. Die Kapitel sind sehr wichtig für Python und die Benutzung von Python. um Python zu beherrschen. ebenso wie die lambda-. wenn man Textverarbeitung betreibt.

. die erfahrene Programmierer anderer Sprachen vielleicht als „trivial” oder „selbstverständlich” bezeichnen würden. die schon Erfahrungen mit Python haben. Insbesondere im zweiten Teil befinden sich viele Themen. Natürlich hatten wir beim Schreiben aber nicht nur eine Person im Blickfeld. Aber hier ist ein Buch wohl dem Präsenzunterricht. sondern eine ganze Leserschar. die den Stoff vertiefen... wenn sie mal etwas vergessen haben sollten oder sich in einer Sache mal doch nicht so ganz sicher sind.. auch wenn es keinesfalls unter diesem Aspekt geschrieben worden ist. bevor man sich zu langweilen beginnt. deutlich überlegen: Ist einem der Stoff eines Abschnittes oder sogar Kapitels bereits vertraut. kann man es einfach überspringen. Ebenso hemmen Formulierungen der Art „Als Benutzerin oder Benutzer gilt . Das Gleiche können dann auch die totalen Anfänger tun. 1. Damit können wir also im ersten Teil des Buches sowohl totale Programmieranfänger als auch erfahrenere Programmierer anderer Sprachen zufrieden stellen.. Dies ist eine Gruppe mit einer breiten Streuung: Angefangen mit denjenigen. die auch Anwendern von Python noch unbekannt sein könnten. dieses Buch außerdem als Referenz zu verwenden. Wörter wie „BesucherInnen” sehen unserer Meinung nach hässlich aus. die sich als Experten bezeichnen.1. In diesem Teil des Buches finden Sie nun die ausführlichen Musterlösungen mit Erläuterungen zu diesen Aufgaben.. also wenn Lehrer und Lernende am gleichen Ort zusammen sind. wenn man sie gut konzipiert hat. In der obigen Aufzählung fehlt aber noch eine wichtige Gruppe. 1 als Übersetzung des englischen Fachbegriffs „user” . Teil IV: Programmieren lernen ist vor allen Dingen eine aktive Tätigkeit. also Python schnell und problemlos zu erlernen. er oder sie . gefolgt von solchen. und objektiv betrachtet erschweren sie die Lesbarkeit eines Textes. bis hin zu jenen. aber auch generelle Unterschiede in der Vorgehensweise von Python im Vergleich zu anderen Sprachen eingehen. Diese Person kann sowohl eine Frau als auch ein Mann sein. Deshalb finden Sie zu den meisten Kapitel interessante und lehrreiche Übungsaufgaben. eine Person. Der umfangreiche Index in diesem Buch macht das Auffinden besonders einfach und erlaubt es damit. nämlich diejenigen.3 Zielgruppe des Buches Beim Schreiben eines Buches hat man ein Gegenüber vor sich. Nur ein Buch zu lesen und Beispiele nachzuvollziehen genügt nicht. sollten sein oder ihr . die das Geschriebene liest. Experten. wenn wir auf Ähnlichkeiten.. mögen und verstehen soll. die bereits kleine oder auch größere Programme geschrieben haben.3 Zielgruppe des Buches 3 man Funktionen. Da sind zum einen die totalen Programmieranfänger. die Sachverhalte erklärt haben wollen.. können dieses Buch als Nachschlagewerk benutzen. dennoch werden wir im Text meistens zum Beispiel nur vom „Benutzer”1 sprechen. die alles wissen oder zu wissen glauben. in anderen Programmen wiederverwenden kann. die bereits ein wenig reingeschnuppert haben.” den Lesefluss und lenken vom eigentlichen Ziel ab.

und dem Lernenden. Wenn Sie das Glück haben. Aber dank des Internets können wir Ihnen diese Interaktivität dennoch bieten. Übungen oder Beispiele möglicherweise als Zeit. große Fragezeichen erscheinen oder wenn sich jemand aus Stress das Ohrläppchen zu reiben beginnt. floss in dieses Buch die jahrelange Erfahrung sowohl in der Theorie und Praxis des Programmierens allgemein. wird es dennoch hier und da mal ein Problem geben. aktualisierte Übungen und sonstige Hilfestellungen. Aber viele Leserinnen und Leser haben nicht diesen Vorteil. 1. Vielleicht mit Ausnahme des Kapitels über die Systemprogrammierung. Dann weiß man als erfahrener Dozent. Aber ein Buch zu schreiben. ein paar zusätzliche Beispiele und Analogien hinzuzunehmen oder dass man den Stoff nochmals in anderen – möglicherweise auch einfacheren – Worten erklären sollte.eu/buch/ Dort finden Sie ein Korrekturverzeichnis.oder Platzvergeudung. führt bei anderen vielleicht zu Langeweile und Ungeduld. voraussetzt. vor allem Linux und Unix. Vor Ort kann man sofort sehen. Dann könnte sich ein Besuch unserer Webseite besonders lohnen: http://www. Beim Schreiben eines Buches muss man diese möglichen Klippen vorhersehen und die nötigen zusätzlichen Übungen und Beispiele an den entsprechenden Stellen bereitstellen. sollten sie in der Lage sein. wo Sie Hilfe und zusätzliche Informationen zum Buch finden. in einer Umgebung zu arbeiten. auch den zweiten Teil zu verstehen. aber vor allem auch die Vermittlung des Stoffes in zahlreichen kleinen und großen Kursen mit unterschiedlichsten Besuchertypen ein. Außerdem finden Sie hier auch ein Forum. diese Klippen zu umgehen. der das Wissen vermittelt.python-kurs.python-kurs. dass Sie ohne zusätzliche Hilfe auskommen sollten. dass es sich bei einem Buch nicht um ein interaktives Medium handelt. Das Grundproblem ist halt. haben Sie es natürlich gut. sodass andere Ihnen hel- .5 Download der Beispiele und Hilfe Alle im Buch verwendeten Beispiele finden Sie auf zum Download unter http://www.4 Programmieren lernen „interaktiv” Wie bereits erwähnt.eu/buch/beispiele/ Auch wenn wir das Buch so geschrieben haben. in dem Sie Ihr Problem schildern können. Beim Buch fehlt leider die direkte Interaktion zwischen dem. weil dieses Kapitel Vorkenntnisse über Betriebssysteme. denn sie empfinden diese zusätzlichen Erklärungen.4 1 Einleitung Wenn Programmieranfänger oder auch Programmierumsteiger von anderen Programmiersprachen erfolgreich den ersten Teil des Buches bearbeitet haben. 1. stellt dennoch eine neue Herausforderung dar. dass es höchste Zeit ist. wo Sie sich vielleicht fest gebissen haben. wenn sich bei einem Teilnehmer die Stirn runzelt. Aber was bei vielen Lesern nun hilft. Im nächsten Abschnitt finden Sie die Adressen. zusätzliche bzw. in der es andere Python-Programmierer gibt.

senden Sie uns einfach eine E-Mail an bernd@python-kurs. Falls Sie glauben.eu/buch/ finden. können Sie auch gerne eine E-Mail direkt an den Autor schicken: klein@python-kurs. Wenn Sie also Kritik. dies alles in kommenden Auflagen zu berücksichtigen.6 Anregungen und Kritik 5 fen können. Ansonsten ist natürlich Google. Anmerkungen oder auch Wünsche haben.1. Leider können wir jedoch – so gerne wir es auch tun würden – keine individuellen Hilfen zu speziellen Problemen geben.python-kurs. wie in so vielen anderen Situationen auch. wenn Sie Anregungen zum Buch geben wollen. Wir werden versuchen. Die jeweils aktuellsten Ergänzungen und weitere Informationen können Sie unter http://www. Natürlich gilt dies auch. Dazu soll unser Forum dienen.6 Anregungen und Kritik Trotz großer Sorgfalt können wir sicherlich nicht verhindern. dass sich der eine oder andere Fehler eingeschlichen hat.eu. 1.eu. ein williger Helfer. Bernd Klein im Mai 2013 . eine Ungenauigkeit oder einen Fehler im Buch gefunden zu haben.

und Umsteiger . .TEIL I Einführung in Python 3 – Für Ein.

.

2 2.1. Der Interpreter wird üblicherweise im Verzeichnis /usr/bin/ (aber manchmal auch in /usr/local/bin) installiert. um mit Python unter Linux zu arbeiten.1 2. der nach dem Quittieren mit der Eingabetaste (Return-Taste) sofort ausgeführt wird.3 (default. besteht darin.1 Gnome-Terminal In diesem Terminal – im Bild sehen Sie ein Gnome-Terminal – tippen Sie „python3” ein und drücken die Eingabetaste. Man kann jetzt beliebigen PythonCode eingeben. $ python3 Python 3. dass man zuerst ein Terminal startet wie beispielsweise ein „xterm” oder ein „gnome-terminal”. Python meldet sich mit Informationen über die installierte Version.2. BILD 2. Der einfachste Weg. Oct 19 2012. 19:53:57) . und damit ist auch die interaktive Python-Shell direkt verfügbar.1 Linux Kommandos und Programme Erste Schritte Bei den meisten Linux-Distributionen ist Python bereits vorinstalliert. Der Interpreter steht nun mit dem sogenannten Eingabeprompt (»>) für Eingaben bereit. aber diese Information benötigen wir jetzt noch nicht. Damit starten Sie die interaktive Python-Shell.

$ python Python 2. 3.2 von ActiveState installiert.2] on linux2 Type "help".python. dass Sie keinesfalls die Ziffer 3 hinter „python” vergessen dürfen.org. "copyright".x.7.3 usw.1. "copyright". Wenn Sie nur „python” eingeben. "credits" or "license" for more information. d. >>> Um die Beispiele in unserem Buch nachvollziehen zu können benötigen Sie jedoch Python in einer 3er-Version.2. 3. Wir haben die Version 3. >>> Bitte beachten Sie.2.7. "credits" or "license" for more information.0.3 (default. .7.1. 3. 21:53:58) [GCC 4.h. Sep 26 2012. Python 3. Die neuesten Versionen findet man unter www.10 2 Kommandos und Programme [GCC 4. starten Sie Python in einer 2er-Version. Python starten unter Windows 1 Also eine Version 3.2] on linux2 Type "help".2 Windows Unter Windows muss Python erst installiert werden.1 2.

In Englisch steht das Wort „shell” für eine Schale.B. Das Verb „agere” bedeutet unter anderem „tun”. auf die wir hier jedoch nicht eingehen wollen.1 Erste Schritte in der interaktiven Shell Wir nehmen nun an.2” oder „Python 3. liefert sofort das Ergebnis und wartet dann auf den nächsten Befehl. das eine Muschel umschließt. die mit dem blinkendem Cursor hinter dem Prompt „»>” auf Ihre Eingabe wartet. d. „Python Interactive Shell”. „treiben”. dem zu interpretierenden Programm (z. Personen oder Ereignissen sein. Dies ist jedoch nicht so: Es gibt auch vor allem im Umfeld von Linux und Unix Shells. Der Begriff „interaktiv” kommt vom lateinischen „inter agere”. Sie erhalten ein schwarzes Terminal-Fenster.2. Dabei handelt es sich um eine Mini-Entwicklungsumgebung. Windows oder anderen) bzw. und andererseits erspart sie dem Benutzer die Benutzung der „primitiven” und schwer verständlichen Basisfunktionen. dass es sich bei dem Begriff „interaktive Shell” um eine Tautologie handelt. also „Python (command line)” bzw. starten Sie bitte die Python-Kommandozeile.2. Auch die Programmiersprache Python bietet dem Anwender eine komfortable Kommandozeilenschnittstelle. die sogenannte Python-Shell. „shell” bezeichnet auch ein Schneckenhaus und das Gehäuse. Also heißt „inter agere” dazwischen handeln. „betreiben”. Die interaktive Shell steht aber auch zeitlich zwischen den einzelnen Aktionen. 2. so wie oben beschrieben. Wie eine Muschelschale schützt sie einerseits das Betriebssystem vor dem Benutzer. Unix.3”. „handeln”. „Python Interactive Shell” befinden. . Shells immer interaktiv sind. unter dem sich die Untereinträge „IDLE (Python GUI)” und „Python (command line)” bzw. manchmal auch als interaktive Python-Shell bezeichnet. die Shell führt diesen unverzüglich aus. Alternativ kann man auch mit IDLE arbeiten. Um die nachfolgenden Beispiele und Übungen nachvollziehen zu können. 2. In diesem Sinne steht die interaktive Shell zwischen dem Anwender und dem Betriebssystem (Linux.h. sollten Sie sich nun sowohl unter Linux als auch unter Windows in der interaktiven Python-Shell befinden. einen Panzer oder ganz allgemein eine Hülle oder Schutzhülle.2 Herkunft und Bedeutung des Begriffes interaktive Shell 11 Nachdem Python installiert worden ist. findet man unter „Alle Programme” einen Eintrag „Python 3. indem es ihm komfortable Befehle zur Kommunikation mit dem Computer zur Verfügung stellt. und „inter” bezeichnet die zeitliche und örtliche Position zu Dingen und Ereignissen. also „zwischen” zwei oder „inmitten” (oder „unter”) vielen Objekten. Man könnte meinen. die als Subshell aufgerufen werden und nicht interaktiv ausgeführt werden. da ja. zwischen den einzelnen Befehlen und Kommandos. Ebenso liegt eine Shell auch zwischen einem Betriebssystem und dem Benutzer. Python).2 Interaktive Shell Wenn die Aktivitäten des vorigen Kapitels erfolgreich waren. dass Sie entweder unter Linux oder unter Windows vor einer lauffähigen Python-Shell sitzen. Der Benutzer gibt einen Befehl ein.

B. „4 * 5.3) 21. die innerhalb eines Python-Skripts nicht zulässig ist. Auch Strings lassen sich mit oder ohne print in der interaktiven Shell ausgeben: >>> print("Hello World") Hello World >>> "Hello World" 'Hello World' >>> .2 >>> 4 * 12 / 3 16.3 21. In einem Programm hätten wir das Ergebnis des obigen Ausdrucks nur mittels einer print-Anweisung ausgeben können: >>> print(4 * 5.0 >>> Die interaktive Shell erlaubt eine Bequemlichkeit. also „_”.2” oder „4 * 12 / 3”. Der Name der Variable ist einfach ein Unterstrich.12 2 Kommandos und Programme Unsere Experimente mit der Python-Shell starten wir mit der Eingabe eines beliebigen arithmetischen Ausdrucks wie z. Das Ergebnis der letzten Berechnung kann man sich also damit wieder ausgeben lassen: >>> _ 85 >>> Der Unterstrich kann im Prinzip wie eine normale Variable benutzt werden: >>> _ * 3 255 >>> Dies gilt allerdings nicht in einem Python-Skript oder Python-Programm! In einem PythonProgramm hat der Unterstrich nicht diese Bedeutung. Ein Ausdruck wird mit dem Drücken der Eingabetaste (return) sofort ausgeführt. und das Ergebnis wird in der nächsten Zeile ausgegeben: >>> 4 * 5. wie wir im folgenden Beispiel sehen können: >>> 1 + (42 * 2) 85 >>> 1 + 42 * 2 85 >>> >>> (1 + 42) * 2 86 Der jeweils letzte Ausgabewert wird vom Interpreter in einer speziellen Variablen automatisch gespeichert.2 Python kennt wie die meisten anderen Programmiersprachen die Regel „Punktrechnung geht vor Strichrechnung”.

Alternativ dazu kann man die Python-Shell mittels Eingabe der Funktion exit() verlassen. Ctrl-C. Wenn Sie genau wissen wollen. also wieder in Richtung neuester Befehl. dennoch wollen sicherlich einige das Programm bereits verlassen. BILD 2. also zu älteren Befehlen. Die Klammern hinter exit sind ab Python 3 zwingend notwendig.2 Emergency Exit Alle Einstellungen wie beispielsweise Variablen oder eingegebene Funktionsdefinitionen gehen beim Verlassen der Python-Shell verloren und sind beim nächsten Start nicht mehr vorhanden. den man von den Linux-Shells gewöhnt ist. die bereits ein wenig Erfahrung mit Programmierung haben. empfehlen wir.3 Verlassen der Python-Shell 13 Die Python-Shell bietet noch einen Komfort.4 Benutzung von Variablen In der Python-Shell kann man auch ganz einfach Variablen benutzen. Es gibt einen Befehlsstack. Das folgende Beispiel wendet sich an Benutzer. bewegen. 2. – was vielen Linux. in dem alle Befehle der aktuellen Sitzung gespeichert werden. was es mit Variablen und Datentypen auf sich hat. Mit den Tasten „↑” und „↓” kann man sich in diesem Stack nach unten („↑”). Man kann also ganz einfach Werte in Variablen speichern. in Kapitel 4 (Datentypen und Variablen) weiterzulesen.2. – funktioniert nicht! Den Python-Interpreter kann man per Kontrollsequenz nur mit Ctrl-D wieder verlassen. Variablennamen bedürfen keiner besonderen Kennzeichnung wie in anderen Sprachen wie zum Beispiel das Dollarzeichen in Perl: >>> maximal = 124 >>> breite = 94 >>> print(maximal .3 Verlassen der Python-Shell Wir haben zwar gerade erst damit begonnen. 2.breite) 30 >>> . und nach oben („↓”). in der Python-Shell „herumzuspielen”.und Unix-Benutzern häufig als Erstes einfällt.

. ”.. BILD 2.. nachdem es gestartet worden ist. möglichst in kleinen Schritten vorzugehen. da noch einige Grundlagen zum Verständnis fehlen. A 42 78 Just a String >>> Achtung: Nachdem man die Zeile „for character in l:” eingetippt hat. mindestens jedoch ein Leerzeichen! Wenn wir fertig sind.14 2 Kommandos und Programme 2. und sollten deshalb besser mit dem folgenden Kapitel weitermachen. 2.. Das Programm soll lediglich einen kurzen Text ausgeben. wie die interaktive Shell mit mehrzeiligen Anweisungen wie zum Beispiel For-Schleifen umgeht. die mit der Schleife ausgeführt werden sollen.78. wartet die interaktive Shell im Folgenden auf eingerückte Zeilen. . print(character) ."Just a String"] >>> for character in l: . >>> l = ["A". Wir müssen also alle Anweisungen. bevor die Schleife wirklich ausgeführt wird. Deshalb wird unser erstes Programm in Python auch nur sehr wenig tun. Wir wollen dieser Tradition folgen. aber noch kein richtiges Programm geschrieben. Anfänger werden hier vielleicht Probleme haben.42.. Dies teilt uns die Shell mit einem neuen Prompt mit: Statt dem gewohnten „>>> ” erhalten wir nun eine Folge von drei Punkten „. um die gleiche Anzahl von Leerzeichen einrücken. Bei der Programmierung ist es generell wichtig.6 Programme schreiben Wir haben bisher ein wenig mit der interaktiven Python-Shell herumprobiert. Für diesen Text wird in fast allen Einführungen zu Programmiersprachen die Zeichenkette2 „Hallo Welt” oder auf Englisch „Hello World” verwendet.5 Mehrzeilige Anweisungen Bis jetzt haben wir noch nicht über mehrzeilige Anweisungen gesprochen. Wir demonstrieren..3 Hallo Welt 2 Eine Folge von Zeichen wird als „Zeichenkette” oder meistens als „String” bezeichnet. müssen wir nach der letzten Code-Zeile zweimal die Eingabetaste drücken.

emacs. Folgender Programm-Code ist in C++ nötig. kate oder gedit. . Schreiben Sie in einem Editor4 Ihrer Wahl die folgende Zeile und speichern Sie sie unter dem Namen „hello. in dem wir die Datei hello.3 Dies geschieht mit folgendem Befehl. wie leicht es ist. Sie können diesen kurzen Exkurs in die Programmiersprache C++ bedenkenlos überspringen. um ein so kleines Programm zum Laufen zu bringen. Dort können wir dann das Programm mit Kommando „python3 hello.B.py Hallo Welt 3 4 Näheres zu Compiler.py” ausführen. Wir bringen dieses Beispiel nur. in Python im Vergleich zu C++ zu programmieren. wenn wir uns in einem Terminal in das Verzeichnis begeben. muss man das Programm kompilieren.6 Programme schreiben oder schnell mal der Welt “Hallo” sagen 15 Im Folgenden wollen wir zeigen.py abgespeichert haben. Unter Windows könnte das beispielsweise „Notepad” sein. um ein Programm zu schreiben. was nach dem Start nur den Text „Hello World” in einer Zeile ausgibt: #include <iostream> using namespace std. unter Linux oder einem anderem Unix-System empfiehlt sich der vi. um ein lauffähiges Programm zu erhalten. Maschinen und Skriptsprachen erfahren Sie in Kapitel 3 (Bytecode und Maschinencode). der ein lauffähiges Programm unter dem Namen „hello” erzeugt: bernd@saturn:~/bodenseo/python/beispiele$ g++ -o hello hello. Interpreter. return 0.py” ab: print("Hello World") Unter Linux oder Unix starten wir dieses Programm am einfachsten. damit man später erkennen kann. Im Folgenden sehen wir dieses Vorgehen inklusive Ergebnis. was in der Programmiersprache C++ nötig ist. „hello. dass Sie die Datei in einem Unterverzeichnis python_beispiele Ihres Homeverzeichnisses abgespeichert hatten: bernd@venus:~$ cd ~/python_beispiele/ bernd@venus:~/python_beispiele$ python3 hello. Dabei nehmen wir an./hello Hello World! bernd@saturn:~/bodenseo/python/beispiele$ Deutlich einfacher können wir ein solches Programm unter Python erstellen. int main() { cout << "Hello World!\n". also z.2.cpp Im Folgenden starten wir das Programm „hello” und erhalten die gewünschte Ausgabe: bernd@saturn:~/bodenseo/python/beispiele$ .cpp”. } Wenn man dieses Programm in einer Datei gespeichert hat.

dass die nötige Syntax5 unter Python deutlich geringer ist als unter C++. „syn” bedeutet „zusammen”. Wir starten erst das Programm „Eingabeaufforderung”. .16 2 Kommandos und Programme Unter Windows können wir ähnlich vorgehen. Fragen zum Verständnis: ■ Wie kann man ein Python-Programm schreiben? Wie startet man ein Python-Programm? Wie kann man das Produkt aus 3.8 am einfachsten mit Python bezeichnen? ■ ■ 5 6 Etymologisch leitet sich das Wort Syntax aus dem altgriechischen Wort „syntaksis” ab. Auf diese gehen wir im nächsten Kapitel näher ein. Beim Start des Programmes wird nämlich implizit gegebenenfalls eine Kompilierung vorgenommen. Anschließend ist auch kein explizites Kompilieren6 nötig.h.oder „gesamt”-Reihenfolge der einzelnen Satzteile. man muss lediglich den Text mit einer print-Funktion aufrufen. mit denen man gültige Programme der Sprache beschreiben kann. Man beachte das Wort „explizit”. d.py abgespeichert haben. in das wir unser hello. In der Informatik versteht man unter der Syntax einer Programmiersprache die Regeln oder das System von Regeln. also sozusagen die „zusammen”. Unter Syntax versteht man in der Linguistik die Lehre vom Satzbau. Dort bewegen wir uns in unser Verzeichnis mit den Python-Programmen.5 und 7. und „taksis” steht für „Reihenfolge” oder „Ordnung”. Hello World unter Python in Windows-Eingabeaufforderung Wir haben gesehen. Man kann das Programm einfach so starten.

als bezeichnete man ein Fahrrad als Moped.und Skriptsprachen liegt. in der ein Compiler geschrieben wird. Würde man von einem Bourne-Shell-Programm sprechen.oder eine Skriptsprache? Wird ein Python-Programm übersetzt oder interpretiert? Kann der gleiche Python-Code auf verschiedenen Rechnern oder Betriebssystemen laufen? Worin liegt der Zusammenhang zwischen Python. da das Verständnis für die folgenden Kapitel nicht dringend notwendig ist. in denen es eindeutig ist: Hat man beispielsweise ein Problem in C gelöst.3 Interpreter.1 1 Manchmal bezeichnet man auch eine Sprache.oder der Bash-Shell spricht man nahezu immer von Skripten und nicht von Programmen. als Compilersprache . Es gibt Fälle. Doch worin liegt der Unterschied zwischen einem Shell-Skript und einem C-Programm? 3. worin der Unterschied zwischen Programmier. Kaum jemand würde ein C-Programm als Skript bezeichnen. deren Programme vor ihrer Ausführung vollständig in Maschinencode. lässt sich nicht einfach beantworten.B. Sehr häufig werden die Begriffe Skript und Programm nahezu synonym verwendet. Jython oder Java? 3. übersetzt werden. so wird allgemein das Ergebnis als „Programm” bezeichnet. so klingt das mindestens so falsch. Bei Shells wie z.3 3. Hier geht es um allgemeine Fragen: Handelt es sich bei Python um eine Programmier.2 Unterschied zwischen Programmierund Skriptsprachen Die Frage. der Bourne.1 Bytecode und Maschinencode Einführung Dieses Kapitel können Sie gerne beim Einstieg in die Materie auch überspringen.oder Compilersprache Compilersprache ist eine Programmiersprache. also Binärcode.

dass der Bytecode plattformunabhängig ist BILD 3. Die Programmiersprachen C und C++ sind reine Compilersprachen. . Python-Programme werden sowohl übersetzt als auch interpretiert. Man liest leider allzu häufig. Dateien gibt. bevor sie ausgeführt werden können.B. sondern interpretiert. in dem Ihre Python-Skripte stehen.h.pyc” gespeichert. Dieser Bytecode wird dann für einen bestimmten Maschinencode interpretiert.2 Dieser Code ist unabhängig von realer Hardware. d. Programme Programme können klein sein. Code für die JVM (Java Virtual Machine). aber kommt dem Code von Maschinensprachen schon relativ nahe. aber sie können auch aus mehreren Tausend oder gar Millionen Codezeilen bestehen. Bei Bytecode handelt es sich um Befehle für eine virtuelle Maschine. z.py") 2 Dieses Konzept entspricht der Vorgehensweise bei Java. dass es sich bei Python um eine interpretierte Sprache handelt. Startet man ein Python-Programm. Bei einer Interpretersprache werden die Programme Befehl für Befehl interpretiert und ausgeführt. Das bedeutet. bevor es ausgeführt werden kann.py” mit einer Zeile als Inhalt: print("Hallo ich komme von beispiel. compiliert). Aber bei Python handelt es sich auch nicht um eine Compilersprache im „klassischen” Sinne. Wird eine Ihrer Dateien als Modul importiert. wird Ihnen vielleicht schon mal aufgefallen sein. Skripte werden unmittelbar ausgeführt. Auch dort wird der Code zuerst in Bytecode übersetzt. woher diese Dateien kommen. Sie werden nicht übersetzt (bzw. wird zuerst der Programmcode in Bytecode übersetzt. Bei Python spricht man von der PVM („Python Virtual Machine). ein Programm mit dem Namen „beispiel. Programme in Programmiersprachen wie C und C++ müssen immer in Maschinencode übersetzt werden. also beispielsweise weniger als Hundert Zeilen Code. Sprachen wie Basic und VB werden interpretiert.h. Wenn Sie dies selbst testen wollen.1 Unterschiede zwischen Skripten und Programmen Skripte Ein Skript besteht typischerweise nur aus „wenigen” Zeilen Code.py”. häufig weniger als 100 Zeilen. so wird diese Datei in Bytecode übersetzt und der Code in einer Datei „beispiel. dass es „plötzlich” in dem Verzeichnis.1 Python: Compiler und Interpreter Wenn Sie schon eine Weile mit Python gearbeitet haben. Dies ist nicht richtig. erzeugen Sie doch einfach eine Datei „beispiel. d. Viele wundern sich und fragen sich. die die Endung „pyc” haben.18 3 Bytecode und Maschinencode TABELLE 3. jedes Programm muss zuerst in Maschinencode übersetzt werden.

3.2. 19:53:57) Type "help". >>> import beispiel Hallo ich komme von beispiel. "copyright".oder Compilersprache 19 Geben Sie dann im Python-Interpreter folgende Zeile ein: $ python3 Python 3.pyc” .3 Interpreter. Oct 19 2012.py >>> In Ihrem Verzeichnis finden Sie anschließend ein Unterverzeichnis „__pycache__ „beispiel. "credits" or "license" for more information. cpython-32.3 (default.

BILD 4. wie Python und C Variablen behandeln. Im Folgenden kreieren wir eine Variable i. also z. sie können ihren Wert ändern. . aber auch hier gibt es wesentliche Unterschiede zu C und C++. Man kann im Verlauf des Programms auf diese Variablen oder genauer: auf den Wert ihres Inhalts zugreifen.4 4. aber wahrscheinlich nicht genug.1 Datentypen und Variablen Einführung Haben Sie bereits in Sprachen wie C und C++ programmiert? Deswegen glauben Sie. Fließkommazahlen (floating point numbers) und Strings sind zwar in Python vorhanden. Eine Variable im allgemeinsten Sinne ist einfach ein Behälter (Container) zur Aufbewahrung von bestimmten Werten. Strings oder Zahlen. Deshalb lohnt es sich auf jeden Fall.1 Variablen als Container Möchte man Listen oder assoziative Arrays in C oder C++ verwenden. Es gibt gravierende Unterschiede in der Art. Vertraute Datentypen wie Ganzzahlen (Integer). sind Variablen „variabel”. dass Sie bereits genug über Datentypen und Variablen wissen? Vorsicht ist geboten! Sie wissen sicherlich viel.B. oder ihnen einen neuen Wert zuweisen. wenn es um Python geht.und Suchfunktionen programmieren oder schwer verständliche Libraries verwenden. hier weiterzulesen. Dieses Kapitel ist also sowohl für Anfänger als auch für fortgeschrittene Programmierer zu empfehlen. das stimmt. Wie der Name sagt. d. indem wir ihr einfach den Wert 42 unter Verwendung eines Gleichheitszeichens zuweisen: >>> i = 42 Man bezeichnet dies als Zuweisung oder auch als Definition einer Variablen. dann muss man sie sich selbst mühsam von Grund auf inklusive Zugriffs.h.

Zahlen wie 0. Dies sind dann beispielsweise in einem C-Programm so aus: int i. Java oder ähnlichen Sprachen hat. C++.0 +5. .8 >>> Man kann eine Variable auch gleichzeitig auf der rechten und der linken Seite einer Zuweisung benutzen.2 Statische und dynamische Typdeklaration In Programmiersprachen unterscheidet man zwischen verschiedenen Datentypen. 1 Man beachte. indem wir ihren Wert mit print ausgeben lassen: >>> print("Wert von i: ". j. dass in Programmiersprachen als Dezimaltrennzeichen immer ein Punkt anstelle eines Kommas verwendet wird.1 Wer Erfahrungen mit C.22 4 Datentypen und Variablen Anmerkung: Obige Anweisung darf man nicht als mathematisches Gleichheitszeichen sehen. So bezeichnet man Zahlen wie -2.h. Wir können nun diese Variable zum Beispiel benutzen. dessen Ergebnis dann einer Variablen zugewiesen wird: >>> x = i / 3. 0. d. ihr einen Typ zuordnen muss. x = i / 3. Man kann die Anweisung also wie folgt „lesen”: „i soll sein 42”. 1. -1.8 >>> print(x) 19. 2 als ganze Zahlen.8.897 werden als Fließkommazahlen oder Float-Zahlen bezeichnet. Im Folgenden erhöhen wir den Wert der Variablen i um 1: >>> i = i + 1 >>> print(i) 43 >>> 4.0 + 5.0676 oder 13. dass man. hat dort gelernt. der Inhalt von i ist nach der Zuweisung 42. sondern als „der Variablen i wird der Wert 42 zugewiesen”. Der Datentyp einer Variablen muss im Programm festgelegt werden und zwar bevor die Variable benutzt oder definiert wird. Ganzzahlen oder meistens mit dem englischen Wort Integer. bevor man eine Variable verwenden darf. float x. i) Wert von i: 42 >>> Wir können Sie aber auch auf der rechten Seite einer Zuweisung in einem Rechenausdruck verwenden.

9. so erreicht man dies einfach mit der folgenden Anweisung: >>> i = 42 Damit hat man automatisch eine Variable vom Typ Integer deklariert und definiert. wenn Datentypen beispielsweise aufgrund fehlender Zuweisungskompatibilität nicht regelgemäß verwendet werden. bezeichnet man als „dynamische Typdeklaration”. In Python kann es nur bei Ausdrücken zu Problemen kommen. und deshalb benötigt man in Python keine Typdeklaration. Man spricht von einer Typverletzung2 . Mit der Funktion type können wir uns den jeweiligen Typ ausgeben lassen: >>> i = 42 >>> type(i) <class 'int'> >>> i = "Hallo" >>> type(i) <class 'str'> >>> i = [3. da man 2 engl. j und x ändern. die auch während der Laufzeit erfolgen kann.17] >>> type(i) <class 'list'> >>> Während sich bei statischen Typdeklarationen. Benötigt man im Programm beispielsweise eine Variable i mit dem Wert 42 und dem Typ Integer.2 Statische und dynamische Typdeklaration 23 Während des Programmlaufes können sich dann die Werte für i. Zunächst einmal bezeichnen Variablen in Python keinen bestimmten Typ. also bei Sprachen wie C und C++. Man kann dann im weiteren Verlauf des Programmes der Variablen i auch beliebige Werte von anderen Datentypen zuweisen: >>> i = 42 >>> i = "Hallo" >>> i = [3. Dies bezeichnet man als „statische Typdeklaration”. type conflict . kann sich bei dynamischer Typdeklaration. Dieser Datentyp wird aber automatisch von Python erkannt. aber nicht Typ einer Variablen während eines Laufes ändert. aber ihre Typen sind für die Dauer des Programmlaufes fest auf int im Falle von i und j und float für die Variable x festgelegt.9. also in Python. In Python sieht dies anders aus.17] >>> Dennoch ordnet Python in jedem Fall einen speziellen Typ oder genauer gesagt eine spezielle Klasse der Variablen zu. da bereits der Compiler den Typ festlegt und während des Programmablaufes keine Änderungen des Typs mehr vorgenommen werden können. Aber Python achtet auf Typverletzungen. nur der Wert. Diese automatische Typzuordnung. sowohl der Wert als auch der Typ einer Variablen ändern.4.

Eine Typverletzung liegt beispielsweise vor. in <module> TypeError: Can't convert 'int' object to str implicitly >>> Allerdings kann man Integer und Floats – auch wenn es sich um unterschiedliche Datentypen handelt – in einem Ausdruck mischen. line 1.5 >>> z = x * y >>> z 42. Man benötigt Typumwandlungen beispielsweise. wenn man Strings und numerische Werte zu einem Ausgabestring zusammenpacken will: >>> first_name = "Henry" >>> last_name = "Miller" >>> age = 20 >>> print(first_name + " " + last_name + ": " + str(age)) Henry Miller: 20 >>> In dem Beispiel haben wir den Wert von „age” explizit mit der Funktion str in einen String gewandelt. Es wird in diesem Fall ein TypeError generiert: >>> x = "Ich bin ein String" >>> y = 42 >>> z = x + y Traceback (most recent call last): File "<stdin>". >>> x = 12 >>> y = 3. Der Wert des Ausdrucks wird dann ein Float.24 4 Datentypen und Variablen ja einer Variablen einen beliebigen Typ zuordnen kann.3 Typumwandlung In der Programmierung bezeichnet man die Umwandlung eines Datentyps in einen anderen als Typumwandlung3 . type conversion oder cast .0 >>> type(x) <class 'int'> >>> type(y) <class 'float'> >>> type(z) <class 'float'> >>> 4. wenn man eine Variable vom Typ int zu einer Variablen vom Typ str addieren will. Hätten wir in obigem Bei- 3 engl. Man bezeichnet dies als explizite Typumwandlung.

hätte Python einen TypeError generiert: >>> print(first_name + " " + last_name + ": " + age) Traceback (most recent call last): File "<stdin>".5 >>> type(x) <class 'float'> >>> x = "Ein String" >>> type(x) <class 'str'> >>> Als Alternative zu der Funktion „type” gibt es noch die eingebaute Funktion „isinstance”.und Floatwerte in einem Ausdruck gemischt hatten. Dennoch gibt es Ausnahmen so wie unser Beispiel. Dort wurde der Integer-Wert implizit in einen Float-Wert gewandelt.4.4] >>> type(l) <class 'list'> >>> x = 4 >>> type(x) <class 'int'> >>> x = 4. tuple) True . auf den geprüft werden soll. Man übergibt ihr als Argument einen Variablennamen und erhält den Typ des Objekts zurück. wie sie in Perl oder PHP möglich sind. ob es sich bei dem Objekt x um ein Tupel handelt: >>> x = (3.4 Datentyp ermitteln In vielen Anwendungen muss man für ein Objekt bestimmen. isinstance(object. Dafür bietet sich meistens die eingebaute Funktion „type” an. dass Python keine implizite Typumwandlung von „int” nach „str” vornehmen kann. um welchen Typ bzw. 4. line 1. ct) „object” ist das Objekt. in <module> TypeError: Can't convert 'int' object to str implicitly >>> Der Text besagt. Prinzipiell unterstützt Python keine impliziten Typumwandlungen. um welche Klasse es sich handelt.5. auf das die Variable zeigt: >>> l = [3.89.4 Datentyp ermitteln 25 spiel nicht den Integer-Wert age in einen String gewandelt. in dem wir Integer. und „ct” entspricht der Klasse oder dem Typ. Im folgenden Beispiel prüfen wir. die einen Wahrheitswert „True” oder „False” zurückgibt. das geprüft werden soll.67) >>> isinstance(x.

tuple)) True >>> isinstance(x.(int. ob es sich um einen von vielen Typen handelt. float)) False >>> . dass wir für ein Objekt wissen wollen.8 >>> isinstance(x. ob eine Variable ein Integer oder ein Float ist.26 4 Datentypen und Variablen In Programmen kommt es häufig vor. Dies könnte man mit der Verknüpfung „or” lösen: >>> x = 4 >>> isinstance(x. Statt eines Typs gibt man als zweites Argument eine Liste von Typen an: >>> x = 4.(list.8 >>> isinstance(x.float) True >>> Allerdings bietet isinstance hierfür eine bequemere Methode. Also zum Beispiel die Frage.898) >>> isinstance(x.123.float) True >>> x = 4. float)) True >>> x = (89.(int.int) or isinstance(x.int) or isinstance(x.

Listen und Tupeln gemeinsam: Es handelt sich jeweils um Datentypen. werden diese Zeichen in einfache oder doppelte Hochkommata gestellt. und bei Listen oder Tupeln handelt es sich um beliebige Element. wenn eine solche Operation für einen Typ erlaubt ist. aber die Leistung von Python besteht darin.5 5.B. d. . ’Ich bin ein String’ und “Ich bin auch ein String”. dass man solche Datentypen zu einer logischen Basisklasse „Sequentielle Datentypen” zusammenfasst. Bei Strings handelt es sich dabei um gleichartige Objekte. deren Elemente sequentiell angeordnet sind. egal ob es sich um einen String.1 Fotos aus dem Film „The Kiss” von 1896 Python stellt die folgenden sequentiellen Datentypen zur Verfügung: 5.h. falls „obj” ein String ist.1. Um einen String in Python zu generieren. also z. In Python gibt es deshalb gleichnamige Methoden oder Zugriffsmethoden für sequentielle Datentypen. Aber man kann obj[0] nicht verändern. Beispielsweise kann man mit obj[0] auf das erste Element eines sequentiellen Datentyps zugreifen. Eines haben nämlich Strings.1 Zeichenketten oder Strings Strings bestehen aus einer Folge – also Sequenz – von beliebigen Zeichen. Zeichen. eine Liste oder einen Tupel handelt.1 Sequentielle Datentypen Übersicht Auch Perl kennt die Datentypen String und List. BILD 5.

wie man im folgenden Beispiel sehen kann: BILD 5. Von hinten (rechts) beginnt man mit -1 zu zählen. Die vorigen Listenbeispiele sehen in Tupelschreibweise wie folgt aus: x = (3.1. 65 . 65 . 88 ) Der wesentliche Unterschied zwischen Listen und Tupel besteht jedoch darin. 5.99.h. dass Tupel nicht mehr verändert werden können. Float-Zahlen. 88 ] Wie wir in dem Beispiel gesehen haben. Listen können verschachtelt sein. Strings oder wieder Listen. [45. d.B. Beispiele: x = [3. 5. bestehen Listen aus einer Sequenz von beliebigen Objekten. Integer-Zahlen. Auf diesen Datentyp werden wir in einem späteren Kapitel eingehen."Ein Text") y = ( 42. Die Elemente einer Liste werden durch Kommata getrennt. dass die Zeichen eines Strings von links nach rechts mit 0 beginnend nummeriert sind. 5. Während Strings jedoch aus einer Sequenz von beliebigen Zeichen aufgebaut sind.28 5 Sequentielle Datentypen 5. 89].4 Sequenz von Binärdaten Man unterscheidet unveränderliche (bytes) und veränderliche (bytearray) Binärdaten.2 Listen Listen stellen wie Strings eine sequentielle Anordnung dar.2 Indizierung Betrachten wir den String "Hello World": Man sieht. 89]. das heißt.1.2 Indizierung eines Strings . dass sie andere Listen als Unterlisten enthalten können."Ein Text"] y = [ 42. dass nach und vor der eckigen Klammer auch Leerzeichen stehen können. Listen werden von eckigen Klammern und Tupel von runden Klammern eingefasst. Im Beispiel können wir auch erkennen. Jedes Zeichen eines Strings kann so eindeutig angesprochen werden.3 Tupel Rein äußerlich unterscheiden sich Listen und Tupel durch die Art der Klammerung.99. Dazu werden eckige Klammern benutzt. also z. [45.1. werden Listen mit eckigen Klammern generiert. ebenso wie vor und nach einem Komma.

89] >>> l[2][1] 89 >>> l[0] = "Ein neuer Wert" >>> l ['Ein neuer Wert'. 88 ) >>> t[0] 42 >>> t[2][0] 45 >>> t[0] = "Tupel lassen sich nicht ändern!" Traceback (most recent call last): File "<stdin>". >>> text = "Es geht auch von hinten!" >>> text[-1] '!' >>> text[-2] 'n' >>> Dies funktioniert bei allen Objekten von sequentiellen Datentypen.2 Indizierung von sequentiellen Datentypen 29 >>> text = "Hallo Kaa" >>> print(text[0]) H >>> print(text[6]) K >>> Mithilfe von negativen Indizes kann man die Zeichen auch von hinten aus ansprechen. also -1 für das letzte Zeichen. 89].5. 65 . also auch bei Listen und Tupeln: >>> l = [ 42. aber keine Tupel ändern können. (45. 89]. 88 ] >>> l[0] 42 >>> l[2] [45. 89). 65 . [45. line 1. 65. [45. -2 für das vorletzte und so weiter. 88] >>> >>> >>> t = ( 42. in <module> TypeError: 'tuple' object does not support item assignment >>> Im obigen Beispiel konnten wir sehen. . dass wir nur Listen.

Der Begriff „Slicing” wird in der deutschen Python-Literatur allzu häufig benutzt.30 5 Sequentielle Datentypen 5. Wie bei der Indizierung benutzt der Slicing-Operator eckige Klammer.und Endwert weg. [6:] ) Lässt man Anfangs.B. Im Englischen wird dieses Ausschneiden als „slicing"bezeichnet. aber nun werden statt einem Wert mindestens zwei Werte erwartet: Anfangswert und Endwert.3 Slicing oder Ausschneiden Man kann auch Teile eines sequentiellen Datentyps ausschneiden. um alles bis zum Ende zu übernehmen ( z. In der Überschrift zu diesem Kapitel benutzen wir sowohl den Begriff „Slicing” als auch „Ausschneiden”. 'green'] >>> >>> colours[-1] 'blue' . Analog kann man auch den Endwert weglassen. [:5] ). Im Falle eines Strings erhält man dann einen Teilstring oder bei Listen wieder eine Liste. wie sich dies bei Listen auswirkt: >>> colours = ['red'. da wir uns nicht für die deutsche Übersetzung eindeutig entscheiden wollten.B. Man versteht dies am besten an einem Beispiel: >>> txt = "Hello World" >>> txt[1:5] 'ello' >>> txt[0:5] 'Hello' >>> txt = "Hello World" >>> txt[0:5] 'Hello' Lässt man den Anfangswert weg (z. 'blue'] >>> colours[2:] ['blue'] >>> colours[:2] ['red'. 'green'. beginnt das Ausschneiden am Anfang des Strings (oder der Liste). 'blue'] >>> colours[1:3] ['green'. Deshalb werden wir die beiden Begriffe im Folgenden synonym benutzen. erhält man den ganzen String (oder entsprechend die ganze Liste oder Tupel) zurück: 'Hello' >>> txt[0:-6] 'Hello' >>> txt[:5] 'Hello' >>> txt[6:] 'World' >>> txt[:] 'Hello World' Das folgende Beispiel zeigt.

.5. solange (begin + i * step) < end ist.h.7.4 Aufgaben 31 Der Slicing-Operator funktioniert auch mit drei Argumenten.[3. das wievielte Argument jedes Mal genommen werden soll. txt[::3] gibt jeden dritten Buchstaben eines Strings aus. s[begin.[45.8."787". Wir haben die Ergebnisse. Aufgabe: Überlegen Sie sich. Aufgabe: Wie kann man am einfachsten das letzte Zeichen in einem String ausgeben? Lösung: Lösungen zu Kapitel 5 (Sequentielle Datentypen). Seite 379 4.. s[begin + i * step]. d. Das dritte Argument gibt dann an. Aufgabe: Welche sequentiellen Datentypen haben Sie kennengelernt? Lösung: Lösungen zu Kapitel 5 (Sequentielle Datentypen).4]] t2 = (4. Seite 379 3. step]. Seite 379 2. die von der interaktiven Python-Shell ausgeben wurden. Beispiel: >>> txt = "Python ist ganz toll" >>> txt[2:15:3] 'tnsgz' >>> txt[::3] 'Ph ta l' 5.4 Aufgaben 1. welche der folgenden Anweisungen korrekt sind.9) s = "Ich bin ein String" l = [45.98]) t[0] t[3] t(3) s[4] s[4] = "x" . Aufgabe: Wie erhält man das erste Element einer Liste? Lösung: Lösungen zu Kapitel 5 (Sequentielle Datentypen). . Ausgegeben werden dann die folgenden Elemente von s: s[begin]. s[begin + 1 * step]. gelöscht: >>> >>> >>> >>> >>> >>> >>> >>> >>> t = (4. end.98.

Aufgabe: Welche zwei Sätze verbergen sich hinter dem folgenden scheinbaren Buchstabensalat: ’DIenr diesmt Sdienrn eb eisstte HLielhfree rz..u rd eSre lsbiscthh inlafceh iumnmde rn aucnhs eürbee rofbleürssstieg Mmaaxcihmte. Seite 381 .32 5 Sequentielle Datentypen >>> >>> >>> >>> l[2][0] = "g" l[3][0] = "g" l t2[2][0] = 42 Lösung: Lösungen zu Kapitel 5 (Sequentielle Datentypen). Seite 380 5.’ Hinweis: Benutzen Sie Slicing! Lösung: Lösungen zu Kapitel 5 (Sequentielle Datentypen).

Objective-C und C# assoziative Arrays als Dictionaries.1 Dictionary den in verschiedenen Programmiersprachen mit verschiedenen Namen versehen. So spricht man in Java und C++ von einer Map. wir zeigen. Zu einem bestimmten Schlüssel gehört immer ein Objekt. In dieser Kategorie gibt es allerdings zur Zeit nur einen implementierten Typ. Strings und Tupel eingeführt. außerdem können sie während der Laufzeit beliebig wachsen und schrumpfen. Beim Dictionary handelt es sich um ein assoziatives Feld. daher der Kategorienname Mapping. in Perl und Ruby von einem Hash und wie in Python bezeichnen auch Smalltalk.h. Wie Listen können Dictionaries leicht verändert werden. d. Nun wollen wir eine weitere Kategorie von Datentypen genauer untersuchen. Man kann also die Schlüssel auf die Objekte „abbilden”. . sondern am Ende beschäftigen wir uns auch noch mit dem Zusammenhang zwischen Listen und Dictionaries. den Datentyp „Mapping”. wie man aus Dictionaries Listen erzeugt und umgekehrt aus bestimmten Listen Dictionaries. In diesem Kapitel geht es aber nicht nur um Dictionaries. Dictionaries gehören zu den wichtigsten Datentypen von Python. Ein Dictionary besteht aus Schlüssel-Objekt-Paaren.1 Dictionaries Dictionaries und assoziative Felder In den vorigen Kapiteln BIS HIER haben wir die sequentiellen Datentypen wie Listen.6 6. Assoziative Felder werden werBILD 6. Kaum ein Programm oder Skript kommt ohne Dictionaries aus. das Dictionary.

Was wäre Python und auch das Internet ohne „ham”. Ein Dictionary wird mit geschweiften Klammern eingegeben. definieren wir nun ein spezielles kulinarisches Dictionary. "spam" : "no"} >>> print(food) {'egg': 'yes'. "egg" : "yes". „egg” und „spam”? >>> food = {"ham" : "yes". Dabei ist es zunächst einmal irritierend. So weisen wir mit der Anweisung food["spam"] = "yes" dem Schlüssel "spam" den neuen Wert ’yes’ zu. ’yes’. dass die Reihenfolge – so wie auch in unserem Beispiel – meist nicht mit der Reihenfolge in der Definition des Directories entspricht. Im nächsten Beispiel kreieren wir ein einfaches deutsch-englisches Wörterbuch als Dictionary: >>> en_de = {"red" : "rot". Die verschiedenen Paare werden mit Komma getrennt eingegeben. So liefert food["ham"] den Wert für den Schlüssel "ham" zurück. Die Zuweisung eines neuen Wertes zu einem bestehenden Schlüssel erfolgt ähnlich wie bei den Listen. 'spam': 'no'} >>> food["ham"] 'yes' >>> food["spam"] 'no' >>> food["spam"] = "yes" >>> print(food) {'egg': 'yes'. sondern einen Schlüssel benutzen. nur dass wir keinen Index. Ein Schlüssel-Wert-Paar wird mit Doppelpunkt zwischen Schlüssel und Wert eingegeben.2 Definition und Benutzung Wir beginnen mit dem wohl einfachsten Fall eines Dictionarys.34 6 Dictionaries 6. 'red': 'rot'} . Python kann also die Schlüssel-Werte-Paare in einer beliebigen Reihenfolge ausgeben. 'spam': 'yes'} >>> Im vorigen Beispiel können wir ein paar interessante Dinge über Dictionaries lernen. 'green': 'grün'. Dies ist in Ordnung. während unsere Ausgabe mit „egg” beginnt. dass wir zum Zugriff auf einen bestimmten Schlüsselwert eckige Klammern benutzen. "Monty Python". 'yellow': 'gelb'. "yellow":" gelb"} >>> print(en_de) {'blue': 'blau'. Man kann ein ganzes Directory mit print ausgeben lassen. In unserer Definition stand als erstes „ham”. da auf dem Directory keine Ordnung definiert ist.h. d. "blue" : "blau". dem leeren: >>> empty = {} >>> empty {} Zu Ehren des Schutzheiligen von Python. Als Nächstes erkennen wir. 'ham': 'yes'. "green" : "grün". 'ham': 'yes'.

"grün" : "green". die noch nie programmiert haben. „vert”. Anfänger. müssen wir ein neues Dictionary definieren. "gelb":" jaune"} >>> print("The French word for 'red' is " + de_fr[en_de['red']]) The French word for 'red' is rouge >>> Was passiert. zum Beispiel in Deutsch-Französisch? Versuchen Sie es doch einmal zur Übung. wenn wir auf eine Farbe zugreifen wollen. "blau" : "bleu". Dennoch möchten wir Ihnen das typische Vorgehen hier nicht vorenthalten.6. einen KeyError. So gibt uns de_fr[en_de["red"]] das französische Wort für „red”. "yellow":" gelb"} >>> en_de["brown"] Traceback (most recent call last): File "<stdin>". "yellow":" gelb"} >>> de_fr = {"rot" : "rouge". können die folgenden paar Abschnitte getrost übergehen. "gelb": " yellow"} Wie wäre es mit einem weiteren Dictionary.1 Um nun auch über deutsche Schlüssel zuzugreifen. also „rouge”: >>> en_de = {"red" : "rot". "gelb":" jaune"} Nun sind wir in der Lage. werden häufig bedingte Anweisungen verwendet. „bleu” und „jaune”. "green" : "grün". in dem die deutschen Wörter als Schlüssel gespeichert sind und die englischen als Werte: >>> de_en = {"rot" : "red". Auf diese werden wir erst in Kapitel 8 (NumPy) eingehen. Möchten wir beispielsweise wissen. 1 Nicht ohne Programmierung jedenfalls . die gar nicht existiert? Wir probieren dies im Folgenden: >>> en_de = {"red" : "rot". obwohl wir gar kein Englisch-Französisch-Wörterbuch haben. "grün" : "vert". in <module> KeyError: 'brown' >>> Wir erzeugen also einen Fehler. von Englisch nach Französisch zu übersetzen. so geht dies nicht. "blue" : "blau".2 Definition und Benutzung 35 In obigem Dictionary können wir nur über die englischen Schlüssel zugreifen. "green" : "grün". "grün" : "vert". "blau" : "bleu". "blue" : "blau". Ein deutsch-französisches Dictionary sieht nun wie folgt aus: >>> de_fr = {"rot" : "rouge". line 1. wenn wir auf einen nicht existierenden Schlüssel zuzugreifen versuchen. damit sie keine Verständnisprobleme haben. Falls Sie kein Französisch können: Die Farben lauten: „rouge”. wie „grün” auf Englisch heißt. "blau" : "blue". Um solche Fehler zu vermeiden.

auf die wir auch erst später wieder eingehen: die inputAnweisung. In dem folgenden kleinen Programm benutzen wir noch eine weitere Anweisung. Das Programm bleibt bei einer input-Anweisung stehen und druckt den Text aus. In unserem Beispiel speichern wir den String in der Variablen „colour”: en_de = {"red" : "rot". ob ein Index in einem Dictionary vorkommt: >>> en_de = {"red" : "rot". die noch nicht enthalten ist: $ python3 guarded_dictionary_access. 'green': 'grün'. 'red': 'rot'} . Dann kann der Benutzer des Programms eine Eingabe vornehmen. 'brown': 'braun'.36 6 Dictionaries 6.3 Fehlerfreie Zugriffe auf Dictionaries Mit dem Schlüsselwort „in” kann geprüft werden. "green" : "grün". der als Argument angegeben wird. ob eine Farbe bereits als Schlüssel enthalten ist oder nicht. und einmal mit einer. "blue" : "blau"} >>> "red" in en_de True >>> "brown" in en_de False >>> Damit kann man mittels einer bedingten Anweisung prüfen. "blue" : "blau"} colour = input("Farbe? ") if colour in en_de: print("Die Farbe " + colour + " ist ein Schlüssel") print("Der deutsche Wert für " + colour + " ist " + en_de[colour]) else: print("Die Farbe " + colour + " ist noch kein Schlüssel") colour_de = input("Deutsch für " + colour + "? ") en_de[colour] = "braun" print("Nun kennen wir auch " + colour + ":") print(en_de) Wir starten dieses Programm zweimal: einmal mit einer Farbe. "green" : "grün". also in unserem ersten Aufruf „Farbe?”. die bereits im Dictionary enthalten ist. die von input als String zurückgeliefert wird.py Farbe? red Die Farbe red ist ein Schlüssel Der deutsche Wert für red ist rot $ python3 guarded_dictionary_access.py Farbe? brown Die Farbe brown ist noch kein Schlüssel Deutsch für brown? braun Nun kennen wir auch brown: {'blue': 'blau'.

Um dieses Verfahren zu demonstrieren. Dazu definieren wir ein Dictionary von Dictionaries: >>> en_de = {"red" : "rot".3]:"abc"} Traceback (most recent call last): File "<stdin>".3):"abc".2.2. line 1. keine Listen und keine Dictionaries.6. also z. "yellow":" gelb"} >>> de_fr = {"rot" : "rouge". 3): 'abc'} 6. "de_fr" : de_fr } >>> >>> print(dictionaries["de_fr"]["blau"]) bleu >>> . wie wir im folgenden Beispiel sehen: >>> dic = { (1. Ansonsten erhält man eine Fehlermeldung: < >>> dic = { [1. Verschachtelte Dictionaries werden häufig auch mit ihrem englischen Begriff als „Nested Dictionaries” bezeichnet. "grün" : "vert". in <module> TypeError: unhashable type: 'list' Tupel als Schlüssel sind in Ordnung. "gelb":" jaune"} >>> >>> dictionaries = {"en_de" : en_de. 3. 2. "blau" : "bleu". Bei den Schlüsseln gilt jedoch die Einschränkung. "green" : "grün". wie man Dictionaries verschachtelt. peppen wir unsere Wörterbücher für natürliche Sprachen noch ein wenig auf.B.4 Zulässige Typen für Schlüssel und Werte In einem Dictionary können beliebige Typen als Werte verwendet werden.1415:"abc"} >>> dic {(1. dass nur Instanzen unveränderlicher (immutable) Datentypen verwendet werden können. "blue" : "blau".5 Verschachtelte Dictionaries Wir zeigen nun.4 Zulässige Typen für Schlüssel und Werte 37 6.

Beispiel: >>> en_de = {"red" : "rot". 'green': 'grün'.fromkeys(S[.) D. "yellow ":"gelb"} >>> en_de. 'yellow': 'gelblich'. "blue" : "blau". 'red': 'rot'} >>> en_de {'blue': 'blau'. "green" : "grün". fromkeys(.38 6 Dictionaries 6. clear(. .. "green" : "grün". wie wir im folgenden Beispiel sehen: >>> en_de = {"red" : "rot". 'green': 'grün'. Eine flache Kopie erhalten wir mit der Methode copy. wenn wir es nicht anders vermerkt haben.. "green" : "grün". 'red': 'rot'} >>> Auf die besondere Problematik zwischen flacher und tiefer Kopie gehen wir in 13 (Flaches und tiefes Kopieren) ein.v]) liefert ein Dictionary zurück mit den Werten des unveränderlichen sequentiellen Datentyps S als Schlüssel und dem optionalen Wert „v”. 'red': 'rot'} >>> Wäre „d” in obigem Beispiel eine Kopie. "blue" : "blau". hätte sich der Wert von „en_de” nicht ändern dürfen. 'green': 'grün'. der 2 Auf die Unterschiede zwischen flacher und tiefer Kopie gehen wir in Kapitel 13 (Flaches und tiefes Kopieren) ein. 'red': 'rot'. 'yellow': 'gelblich'} >>> en_de {'blue': 'blau'.) Löscht alle Einträge eines Dictionaries. demonstrieren wir im folgenden Beispiel: >>> en_de = {"red" : "rot".copy() erzeugt eine flache Kopie von D. 'yellow': 'gelb'. "yellow ":"gelb"} >>> d = en_de >>> d["yellow"] = "gelblich" >>> d {'blue': 'blau'.6 Methoden auf Dictionaries Im Folgenden bezeichnet D ein Dictionary. Dass dies nicht so ist..copy() >>> d["yellow"] = "gelblich" >>> d {'blue': 'blau'. "yellow ":"gelb"} >>> d = en_de.. 'green': 'grün'.) dict.. 'yellow': 'gelblich'.2 Anfänger machen häufig den Fehler zu glauben. dass die Zuweisung eines Dictionarys an eine Variable bereits einer Kopie entspricht..clear() >>> en_de {} >>> copy(. "blue" : "blau".

..get("brown") >>> en_de.. Beispiel: >>> en_de = {"red" : "rot". 'green'. "green" : "grün". ('red'.) D.fromkeys(food. "yellow ":"gelb"} >>> en_de. was einer View der Schlüssel entspricht. Wird „v” nicht angegeben. "enjoy") >>> d {'eggs': 'enjoy'.. 'grün').get("brown". 'ham': 'enjoy'.6 Methoden auf Dictionaries 39 jedem Schlüssel automatisch zugeordnet wird. "blue" : "blau".) D. Beispiel: >>> en_de = {"red" : "rot".items() >>> type(x) <class 'dict_items'> >>> x dict_items([('blue'.get(k[. ansonsten d.) D. Der Default-Wert ist None. werden alle Werte auf None gesetzt: Beispiel: >>> food = ("ham".items() liefert ein Mengen-ähnliches Objekt vom Type „dict_item” zurück. Beispiel: >>> en_de = {"red" : "rot". 'yellow'. "spam") >>> d = dict.fromkeys(food) >>> d {'eggs': None. "blue" : "blau". falls k in D ist.keys() >>> type(x) <class 'dict_keys'> >>> x dict_keys(['blue'. was einer View der Schlüssel-Werte-Paare entspricht. "green" : "grün". 'ham': None. "blue" : "blau".d]) liefert D[k] zurück. "green" : "grün". 'spam': 'enjoy'} >>> get(. 'gelb'). 'red']) >>> . 'spam': None} >>> d = dict. "eggs"."spam") 'spam' >>> items(. 'blau'). ('yellow'. "yellow ":"gelb"} >>> x = en_de.6.. "yellow ":"gelb"} >>> x = en_de. 'rot')]) >>> keys(.get("red") 'rot' >>> en_de..keys() liefert ein Mengen-ähnliches Objekt vom Type „dict_item” zurück. ('green'.

'grün') >>> en_de.) D.popitem() ('yellow'. Beispiel: >>> en_de = {"red" : "rot".. "braun") . "blue" : "blau"} >>> en_de. falls der Schlüssel k noch nicht in D enthalten ist.d]) entfernt den Schlüssel „k” zusammen mit seinem Wert aus dem Dictionary.popitem() ('green'. Beispiel: >>> en_de = {"red" : "rot". 'rot') >>> en_de. wird ein KeyError generiert.pop("brown". verändert diese Methode das Dictionary D nicht. Falls k bereits in D enthalten ist.setdefault("brown".40 6 Dictionaries pop(.d]) setzt D[k] auf den Wert d.pop(k[. außer pop wurde mit dem optionalen Parameter „d” aufgerufen. In diesem Fall liefert D.. "green" : "grün". 'gelb') >>> en_de. 'blau') >>> en_de..popitem() Traceback (most recent call last): File "<stdin>". Falls das Dictionary leer ist.. >>> en_de = {"red" : "rot"..pop("brown") Traceback (most recent call last): File "<stdin>".) D. line 1. line 1. Die Methode liefert den Wert von D[k] zurück. falls der Schlüssel k noch nicht in D enthalten ist.pop("red") >>> x 'rot' >>> en_de {'blue': 'blau'.setdefault(k[. "green" : "grün". in <module> KeyError: 'popitem(): dictionary is empty' >>> setdefault(.pop(k.d) den Wert „d” zurück. Falls der optionale Parameter „d” nicht angeben wird. "yellow ":"gelb"} >>> x = en_de."spam") >>> x 'spam' >>> popitem(. dann wird ein KeyError generiert.popitem() wird ohne Parameter aufgerufen und liefert ein beliebiges Schlüssel-Wert-Paar (k. "blue" : "blau".) D. "yellow ":"gelb"} >>> en_de. v) zurück. 'green': 'grün'. Die Methode liefert den Wert D[k] zurück. in <module> KeyError: 'brown' >>> x = en_de. "green" : "grün".. Entspricht „k” keinem Schlüssel.popitem() ('red'.popitem() ('blue'. "blue" : "blau". was dann aus dem Dictionary entfernt wird. 'yellow': 'gelb'} >>> x = en_de. wird D[k] auf den Wert None gesetzt.

"green" : "grün". 'green': 'grün'. "blue" : "blau". 'brown': 'braun'.update(en_de2) >>> en_de {'blue': 'blau'. 'yellow': 'gelb'} >>> 6.7 Operatoren auf Dictionaries Auch auf Dictionaries ist eine „Länge” definiert. "yellow":" gelb"} >>> len(en_de) 4 >>> . 'brown': 'braun'. 'yellow': 'gelb'. "blue" : "blau"} >>> >>> en_de2 = {"yellow":"gelb".. "verde") 'grün' >>> en_de {'blue': 'blau'.7 Operatoren 41 'braun' >>> en_de {'blue': 'blau'. 'red': 'rot'.setdefault("green".6. was der Anzahl der verschiedenen Schlüssel entspricht.) Fügt ein Dictionary d2 zu d hinzu und überschreibt gegebenenfalls die Werte von bereits vorhandenen Schlüsseln.setdefault("yellow") >>> en_de {'blue': 'blau'. 'red': 'rot'} >>> en_de. >>> en_de = {"red" : "rot". Die Methode len() liefert die Anzahl der Schlüssel-Werte-Paare zurück. 'green': 'grün'.. 'red': 'rötlich'} >>> en_de = {"red" : "rot". 'red': 'rot'} >>> en_de. "green" : "grün". Beispiel: >>> en_de = {"red" : "rot". 'green': 'grün'.update(en_de) >>> en_de2 {'blue': 'blau'. 'brown': 'braun'. "red":"rötlich"} >>> en_de2. "green" : "grün". "red":"rötlich"} >>> en_de. 'yellow': None. 'green': 'grün'. 'green': 'grün'. "blue" : "blau"} >>> en_de2 = {"yellow":"gelb". ' red': 'rot'} >>> update(.

mit [(11. 22). (31. 33)] >>> Im obigen Beispiel hatten wir zip mit dem Argument *T aufgerufen.l2)) 3 Auf diesen Mechanismus gehen wir in Kapitel Funktionen. wäre zip mit einer Liste bestehend aus den vorigen Tupeln aufgerufen worden. 23] >>> z3 = [31. (13. d. . 22. weil wir sie im folgenden Abschnitt benötigen werden. 12. Dennoch behandeln wir sie an dieser Stelle. 23). Der SternchenOperator kann auf ein Tupel.42 6 Dictionaries 6. die Sequenzen als Ein. 13. 22. 33] >>> >>> T = zip(z1. 33)] >>> >>> M = zip(*T) >>> list(M) [] >>> T = zip(z1. 14] >>> l2 = [21. (12. 21. 12. 23. 22. Alle darüber hinaus existierenden Elemente werden ignoriert. z3) >>> M = zip(*T) >>> list(M) [(11. Hätte man T statt *T geschrieben. 22. 32). 32). eine Liste oder ganz allgemein auf einen sequentiellen Datentyp bzw. 24] >>> list(zip(l1. 21. 22. z2. z3) >>> T <zip object at 0x911ffac> >>> list(T) [(11. Mit Zip kann man eine Matrix transponieren. >>> l1 = [11. 23. 22. (13. 23. (14. (12. 13). 13] >>> l2 = [21. (13. 21). Seite 115 näher ein. Es ist eine Funktion. 21.und Ausgaben hat. 23. 24)] >>> Sind die Argumente von zip verschieden lang. 12. 32) und (13. Iterator angewendet werden. 23. 31). (21. dann arbeitet zip nur auf den Argumenten bis zur kleinsten Länge. 31). >>> z1 = [11. 22. um diesen zu „entpacken”. >>> l1 = [11.h. 32. 12.8 Zip Diese sehr nützliche Funktion gehört eigentlich nicht in die Dictionary-Klasse. (12. 32. in dem wir zwei flache Listen oder Tupel miteinander verknüpfen. 33)].3 Im obigen Beispiel wird zip mit den drei Argumenten (11. 23).l2)) [(11. 24] >>> list(zip(l1. 13] >>> z2 = [21. Besonders interessant im Zusammenhang mit Dictionaries ist der Fall. z2. (12. 33) aufgerufen. 31).

'Hamburger')] >>> Wenn Sie im vorigen Kapitel unter der Dictionary-Methode item nachschauen. 'Sauerkraut').6. (13. dass die von item zurückgelieferte Liste von 2er-Tupel obiges Aussehen hat. dass ein dict-Casting auf das obige Ergebnis das gewünschte Dictionary zurückliefert: >>> landesueblich = dict(zip(laender.9 Dictionaries aus Listen erzeugen Betrachten wir die beiden folgenden Listen: >>> gerichte = ["Pizza". was passiert. was alte Stereotypen bedient: Bei der Eingabe eines Landes als Schlüssel soll als Wert das landesspezifische Gericht erscheinen. (12. "Hamburger"] >>> laender = ["Italien"."USA"] Auch wenn mittlerweile Hamburger weltweit verbreitet sind. 22). Deshalb ist es nicht verwunderlich. "Sauerkraut". Schauen wir uns zunächst einmal an. ' USA': 'Hamburger'} >>> landesueblich["Deutschland"] 'Sauerkraut' >>> landesueblich["USA"] 'Hamburger' >>> . 'Paella '). gerichte)) [('Italien'.9 Dictionaries aus Listen erzeugen 43 [(11. 21). ('Deutschland'. 23)] >>> 6. 'Italien': 'Pizza'. bilden wir dennoch ein Dictionary."Deutschland". ('USA'. wenn vielleicht mehr Pizzen in Deutschland gegessen werden und Sauerkraut nicht mehr zu den deutschen Lieblingsgerichten gehört. gerichte)) >>> landesueblich {'Spanien': 'Paella'."Spanien". werden Sie erkennen. 'Pizza'). 'Deutschland': 'Sauerkraut'. wenn wir obige Listen mit zip verknüpfen: >>> list(zip(laender. "Paella". ('Spanien'.

Englisch. Aufgabe: BILD 6. Seite 381 . wir wollen in einem Programm die Bezeichnungen für ein Dateimenü internationalisieren.2 Datei-Menü Stellen Sie sich vor. Französisch und Italienisch anbieten.B. Wir wollen ein verschachteltes Dictionary verwenden. Neue Datei öffnen. Zum Übersetzen der Begriffe: Englisch – Deutsch – Französisch – Italienisch File – Datei – Fichier – File New – Neu – Nouveau – Nuovo Open – Öffnen – Ouvrir – Apri Save – Speichern – Enregistrer – Salva Save as – Speichern unter – Enregistrer sous – Salva come Print Preview – Druckansicht – Apercu avant impressioner – Anteprima di stampa Print – Drucken – Imprimer – Stampa Close – Schließen – Fermer – Chiudi Exit – Verlassen – Quitter – Esci Lösung: Lösungen zu Kapitel 6 (Dictionaries). Öffnen und Drucken angeben.10 Aufgaben 1. in Deutsch. Speichern unter neuem Namen. also z.44 6 Dictionaries 6. in dem wir die Übersetzung für die Menüpunkte zum Speichern.

Lösung: Lösungen zu Kapitel 6 (Dictionaries).6. Seite 382 . „schwarz”) sein.3 Schachbrett Überlegen Sie sich eine Darstellung des Schachbretts als Dictionary. welche Figur sich auf einem Feld befindet. Die erste Komponente dieses Tupels entspricht den Spalten des Spielfeldes. Die Schlüssel dieses Dictionaries sollen die Felder des Schachbrettes sein und die Werte die Information. Die zweite Komponente stellt eine Zahl zwischen 1 und 8 dar. Ein Schachbrett besteht bekanntlich aus 64 Feldern. Das Ergebnis könnte also beispielsweise von der Form („König”. Aufgabe: BILD 6. Diese werden mit Buchstaben zwischen „a” und „h” von links nach rechts gekennzeichnet. die in 8 Zeilen und 8 Spalten angeordnet sind. Ein Feld des Schachbretts kann mit einem Tupel bezeichnet werden.10 Aufgaben 45 2.

1918) begründete die Mengenlehre mit seinem 1874 erschienenen Artikel „Über eine Eigenschaft des Inbegriffes aller reellen algebraischen Zahlen”. Anfangs. Die Mengenlehre ist noch ein recht junges Gebiet der Mathematik.2 Mengen in Python Der Datentyp „set”. der ein sogenannter „collection”-Typ ist.7 7. Der deutsche Mathematiker Georg Cantor (1845 .1 Mengen Diagramme 1895 gab er folgende Definition einer Menge: „Unter einer . 7. ist in Python seit Version 2. also bis ins Jahr 1977. ist sie ein wesentliches Gebiet der Mathematik. Buchstaben.Menge’ verstehen wir jede Zusammenfassung M von bestimmten wohlunterschiedenen Objekten m unserer Anschauung oder unseres Denkens (welche die . enthalten. Namen oder sogar andere Mengen. Wörter.Elemente’ von M genannt werden) zu einem Ganzen. bezeichnete er übrigens die Mengenlehre noch als „Mannigfaltigkeitslehre”. Zeichen. Ein set enthält eine ungeordnete Sammlung von einmaligen und unveränderli- .4. Die heutige Mathematik ist in der Terminologie der Mengenlehre formuliert und baut auf deren Axiomen auf. BILD 7. Eine Menge wird in der Mathematik üblicherweise mit einem Großbuchstaben bezeichnet.” Eine Menge kann beliebige Elemente enthalten: zum Beispiel Zahlen.1 Mengen Übersicht Auch wenn die Mengenlehre über lange Zeit heftig kritisiert wurde und immer noch kritisiert wird.

dass wir beispielsweise keine Listen als Elemente haben können: . 't'. 'h'."Berlin". da wir diese ja bisher für Dictionaries verwendet hatten. 'r'. 'Berlin'} >>> print(staedte) {'München'."Paris". Im folgenden Beispiel wird mit dem Casting-Operator set ein String in seine Zeichen vereinzelt. In anderen Worten: Ein Element kann in einem set-Objekt nicht mehrmals vorkommen. 'a'. was bei Listen und Tupel jedoch möglich ist. 'München'. "Lyon". 'Birmingham'. Man bedient sich der gewohnten mathematischen Schreibweise. wie sie aus der Mathematik bekannt sind. 'Frankfurt'. 'London'. 'i'. so ist dies in Python3 sehr einfach. 'P'. 7. ' '. dass sie keine veränderlichen (mutable) Objekte erlauben. >>> staedte = {'Hamburg'. 'o'. Beim Datentyp set handelt es sich um die Python-Implementierung von Mengen. 'Berlin'. gibt es keine doppelten Einträge in unserer resultierenden Menge. Das folgende Beispiel demonstriert.2.2 Mengen von unveränderlichen Elementen Sets sind so implementiert. 'Lyon'. 'l'. 'Berlin'} >>> Wie erwartet. wenn wir ein Tupel mit wiederholt auftretenden Elementen an die set-Funktion übergeben – in unserem Beispiel tritt die Stadt Paris mehrmals auf: >>> cities = set(("Paris". 'n'.1 Sets erzeugen Will man eine Menge erzeugen. 'T'} >>> type(x) <class 'set'> >>> 7. 'y'.48 7 Mengen chen Elementen. dass wir die geschweiften Klammern für Mengen verwenden. 'u'. um die Menge der im String enthaltenen Buchstaben zu erhalten: >>> x = set("A Python Tutorial") >>> x {'A'. 'Hamburg'} >>> 'Berlin' in staedte True >>> 'Köln' in staedte False Im obigen Beispiel mag vielleicht verwundern.2. was passiert."Birmingham ")) >>> cities {'Paris'. "London". 'Frankfurt'. Nun wollen wir zeigen.

Es gilt zu beachten.1 Operationen auf „set”-Objekten add(element) Mit der Methode add fügt man ein Objekt in eine Menge als neues Element ein. Im folgenden Beispiel fügen wir einen String ein: >>> colours = {"red". ("Paris". Sie sind also unveränderlich (immutable): >>> cities = frozenset(["Frankfurt". ["Paris"."green"} >>> colours. 'yellow'.add("Strasbourg") >>> cities {'Freiburg'.3 Frozensets Auch wenn sets keine veränderlichen Elemente enthalten können. aber sie können nicht verändert werden.4. dass es sich dabei um ein unveränderliches Element handelt. line 1. "Basel". Wir können zum Beispiel neue Elemente einfügen: >>> cities = {"Frankfurt". 'Basel'.add("yellow") >>> colours {'green'.add("Strasbourg") Traceback (most recent call last): File "<stdin&module>". in <module> TypeError: unhashable type: 'list' >>> . "Basel"."Perl"). in <module> AttributeError: 'frozenset' object has no attribute 'add' >>> 7.add(["black". "London"])) Traceback (most recent call last): File "<stdin>". line 1. line 1.3 Frozensets 49 >>> cities = set((("Python". sind sie selbst veränderlich."Freiburg"} >>> cities. "Berlin". "London"))) >>> cities = set((["Python". falls es noch nicht vorhanden ist. 'Frankfurt'.7."white"]) Traceback (most recent call last): File "<stdin&module>". "Berlin".4 7."Perl"]. in <module> TypeError: unhashable type: 'list' 7. 'Strasbourg'} Frozensets sind wie sets."Freiburg"]) >>> cities. 'red'} >>> colours.

Wir demonstrieren die Benutzung anhand eines Beispiels: >>> more_cities = {"Winterthur"."d". 'Schaffhausen'} >>> Nur für diejenigen. "Freiburg"} >>> cities. die zurückgeliefert wird. dass eine einfache Zuweisung auch genügen könnte: >>> more_cities = {"Winterthur". 'Winterthur'.3 copy copy erzeugt eine flache Kopie einer Menge. Ist es bereits enthalten."St. Die Menge ist also anschließend leer.4."Schaffhausen".clear() >>> cities set() >>> 7. Wir illustrieren dies wie immer an einem Beispiel: >>> x = {"a". 7. "Konstanz".clear() >>> cities_backup {'St."St. die glauben.h."Schaffhausen". d.4 difference() Diese Methode liefert die Differenz von zwei oder mehr Mengen zurück."d"} . wenn es noch nicht enthalten ist. einen weiteren Namen für das gleiche Objekt."c"} >>> z = {"c".4. Gallen"} >>> cities_backup = more_cities.4. Gallen"} >>> cities_backup = more_cities >>> more_cities.copy() >>> more_cities.clear() >>> cities_backup set() >>> Die Zuweisung „cities_backup = more_cities” erzeugt nur einen Pointer. Gallen'."e"} >>> y = {"b"."c"."b".50 7 Mengen Selbstverständlich wird ein Objekt nur dann als neues Element eingefügt. hat der Aufruf der Methode keine Auswirkungen. wie wir im folgenden Beispiel sehen: >>> cities = {"Stuttgart".2 clear() Alle Elemente einer Menge werden entfernt. 7.

'e'. 'e'.y 'e'.difference_update()” ist gleichbedeutend mit „x = x .difference_update(y) >>> x {'a'."d". 'b'."c"} >>> x. hätten wir auch den Operator „-” benutzen können: >>> x {'a'. 'd']) >>> x. 'd'} >>> >>> x = {"a".discard("z") >>> x {'c'.y >>> x {'a'.z 'e'} 7."c".4 Operationen auf „set”-Objekten 51 >>> x.5 difference_update() Die Methode difference_update entfernt alle Elemente einer anderen Menge aus einer Menge. 'e'. >>> .difference(z) {'a'.difference(y).discard("a") >>> x {'c'."b"."d". 'e'.difference(y) set(['a'."c". „x."c".4. 'e'} >>> Statt die Methode difference zu benutzen.y” >>> x = {"a". falls es enthalten ist."c"} >>> x = x . 'b'. 'd'} >>> ."e"} >>> y = {"b"."e"} >>> x.6 discard(el) Das Element el wird aus einer Menge entfernt. 'd'} >>> x. Falls el nicht in der Menge enthalten ist."b"."e"} >>> y = {"b"."d". passiert nichts. >>> x {'a'.7. >>> x = {"a". 'd'} >>> 7.4. 'd'} . 'e'.y ."b".

remove("a") >>> x {'c'.isdisjoint(z) False . wird ein Fehler generiert."d"."d"."d"."b". 'd'} >>> >>> x = {"a"."e"} >>> y = {"c"."e"."c". aber falls el nicht in der Menge enthalten ist. >>> x = {"a"."d". 'd'} >>> x."c". line 1."e"."g"} >>> x."d"."e"} >>> y = {"c".intersection(y) {'c'.4.h."d"} >>> z = {"b". 'b'.4.intersection(y) {'c'. 'e'."d"."f". 'e'."b"."e"."g"} >>> x.9 isdisjoint() Diese Methode liefert True zurück."g"} >>> x & y {'c'. 'e'."f". 'd'} >>> 7.7 remove(el) Funktioniert wie discard(). 'd'} >>> Dies kann auch mit dem „&”-Zeichen formuliert werden: >>> x = {"a"."e"} >>> y = {"c". d.isdisjoint(y) True >>> x."c".4."c"."d". ein KeyError: >>> x = {"a". wenn zwei Mengen eine leere Schnittmenge haben."b"} >>> y = {"c".remove("z") Traceback (most recent call last): File "<stdin&module>"."b"."c"} >>> x."f". >>> x = {"a"."e"} >>> x."b". in <module> KeyError: 'z' >>> 7. 'e'.8 intersection(s) Liefert die Schnittmenge von s und der Instanzmenge zurück.52 7 Mengen 7.

12 pop() pop() liefert ein beliebiges Element der Menge zurück."d"} >>> x. >>> x = {"a".pop() 'c' ."b"."e"} >>> y = {"c".11 issuperset() x.10 issubset() x. falls die Menge leer ist."c". Die Methode erzeugt einen KeyError."d"."b"."c".4. „>” kann statt des Aufrufs der Methode verwendet werden.pop() 'a' >>> x."e"} >>> y = {"c". „<” kann statt des Aufrufs der Methode verwendet werden.4.issuperset(y) True >>> >>> x > y True >>> 7. >>> x = {"a". falls x eine Obermenge von y ist."d"."d".7. >>> x = {"a". Dieses Element wird dabei aus der Menge entfernt.4."c".issuperset(y) liefert True zurück.issubset(x) True >>> >>> x > y True >>> y < x True >>> 7."d"} >>> x."b"."e"} >>> x.issubset(y) liefert True zurück.4 Operationen auf „set”-Objekten 53 7. falls x eine Untermenge von y ist.issubset(y) False >>> y.

die unter einer bedingten Bedingung ausgeführt werden.1 Verzweigungen In diesem Kapitel beschäftigen wir uns mit bedingten Anweisungen. wie Verzweigungen auch genannt werden.2 Bedingte Anweisungen in Python Die einfachste Form einer if-Anweisung sieht in Python wie folgt aus: if bedingung: anweisungen . in denen eine Anweisung auf die andere folgt und diese auch in dieser Reihenfolge ausgeführt werden. Man möchte beispielsweise einen bestimmten Teil des Programms nur dann ausführen. Bedingte Anweisungen und Verzweigungen werden in Programmiersprachen (ebenso wie die Schleifen) den Kontrollstrukturen zugerechnet. oder ein anderer Teil soll gegebenenfalls mehrmals ausgeführt werden.8 8. BILD 8. Programme zu schreiben. Dazu bietet jede Programmiersprache Kontrollstrukturen.1 Verzweigungen Übersicht Bisher sind wir in der Lage. Dies sind Codeteile. wird dieser Code nicht ausgeführt. reagieren kann. 8. weil mit ihrer Hilfe ein Programm auf verschiedene Zustände. Ist die Bedingung nicht erfüllt. die sich aus Eingaben und Berechnungen ergeben. Anders ausgedrückt: Eine Verzweigung legt fest. die sich in zwei Kategorien unterscheiden lassen: Verzweigungen und Schleifen. Aber nur wenige Probleme lassen sich durch einen linearen Programmablauf kontrollieren. welcher von zwei (oder auch mehr) Programmteilen (Alternativen) in Abhängigkeit von einer (oder mehreren) Bedingungen ausgeführt wird. wenn bestimmte Bedingungen zutreffen.

Dieses Problem kann man mit einem „elif” lösen. wie alt ihr Hund wohl wäre. elif bedingung: anweisungen else: anweisungen Wir wollen uns im folgenden Beispiel-Skript mit der einfachen if-Anweisung beschäftigen.") 8. Wir haben keine Anweisungen für diesen Fall. Zum anderen gibt es aber auch noch andere Nationalitäten. Ganz allgemein sieht es so aus: if bedingung: anweisungen elif bedingung: anweisungen . person = input("Nationalität? ") if person == "französisch": print("Préférez-vous parler français?") if person == "italienisch": print("Preferisci parlare italiano?") Obiges kleines Python-Skript hat zwei Nachteile. also ohne „elif” und „else”. Der Block unter dem „else” wird immer ausgeführt. Dazu benötigen wir noch den else-Zweig der if-Anweisung.3 Beispiel: Hundejahre Kinder und Hundeliebhaber stellen sich häufig die Frage.") print("so we have to speak English. person = input("Nationalität? ") if person == "französisch": print("Préférez-vous parler français?") elif person == "italienisch": print("Preferisci parlare italiano?") else: print("You are neither Italian nor French.. Wir können als Default Englisch einstellen. wenn die Bedingung „bedingung” wahr. wenn er kein Hund sondern ein Mensch wäre. was in diesem Fall unmöglich ist. Anschließend wird aber in der nächsten if-Anweisung geprüft. Landläufig rechnet man Hundejahre in Menschen- . also True ist. wenn der Ausdruck beim letzten „elif” oder „if” „False” war. Wenn jemand als Nationalität „französisch” angegeben hat.56 8 Verzweigungen Der eingerückte Codeblock wird nur ausgeführt. ob „person” möglicherweise „italienisch” ist.. Der Ausdruck hinter dem „elif” wird nur geprüft. wenn die Ausdrücke hinter dem „if” und den „elif”s nicht zutrafen (True). wird wie zu erwarten die print-Anweisung des ersten if ausgeführt.

also True.0. der boolsche Wert False. leere Zeichenketten. dass es Lücken im Gesetz gibt.0j).4 Wahr oder falsch „Was nicht verboten ist. 22 Jahre" elif age > 2: human = 22 + (age -2)*5 print "Menschenjahre". was nicht False ist. 14 Jahre" elif age == 2: print "entspricht ca. also False ist: ■ numerische Null-Werte(0. .8. 0. Ab dann entspricht ein Hundejahr jeweils 5 Menschenjahren.4 Wahr oder falsch: Bedingungen in Verzweigungen 57 jahre um. Wir brauchen also nur zu definieren. was „falsch”. ■ ■ ■ ■ ■ Alle anderen Werte betrachtet Python als „wahr”. hat den Wert True. Dadurch wird vermieden. Ähnlich verhält es sich auch mit den Bedingungen in Python.0+0.B. leere Listen. Alles. indem man das Alter des Hundes mit 7 multipliziert. z.: ■ Ein einjähriger Hund entspricht in etwa einem 14-jährigen Menschen 2 Jahre eines Hundes entsprechen 22 Jahre eines Menschens. ist erlaubt”: So funktioniert unser Gesetz. leere Tupel. leere Dictionaries sowie der spezielle Wert None. Je nach Hundegröße und Rasse sieht die Umrechnung jedoch etwas komplizierter aus. 0. ■ ■ Das folgende kleine Beispielprogramm verlangt die Eingabe für das Alter des Hundes und berechnet nach obiger Regel das Alter in Menschenjahren: age = input("Alter des Hundes: ") print if age < 0: print "Das stimmt wohl kaum!" elif age == 1: print "entspricht ca. 0L. human ### raw_input('press Return>') 8.

Lösung: Lösungen zu Kapitel 8 (Verzweigungen). Allerdings machen wir damit einen neuen kleinen „Fehler”.2425 Tage. obwohl die Jahreszahl durch Hundert teilbar ist.952 Sekunden. obwohl es durch vier teilbar war. Man sieht. Lösung: Lösungen zu Kapitel 8 (Verzweigungen). 12 Sekunden oder anders ausgedrückt 31. ob eine gegebene Jahreszahl ein Schaltjahr ist oder nicht. Lesen Sie Stunden-. Aufgabe: Auch bei der zweiten Aufgabe bleiben wir bei der Zeitrechnung. Um diesen Unterschied zu beheben. Das Programm soll die neue Uhrzeit in der obigen Form ausgeben. Minuten. Aus diesem Grunde wird alle Hundert Jahre – und zwar wenn die Jahreszahl durch Hundert teilbar ist – auf einen Schalttag verzichtet.5 Aufgaben 1.58 8 Verzweigungen 8. Seite 384 . dann wird ein Schalttag eingefügt. also hh:mm:ss. das berechnet. So war beispielsweise das Jahr 1900 kein Schaltjahr. Man benötigt jedoch noch alle 400 Jahre ein weiteres Korrektiv. dass ein Jahr also grob gesprochen einen Viertel Tag länger ist als 365 Tage. also 365 Tage. Nach dem Gregorianischen Kalenderjahr dauert ein Jahr exakt 365. hat man Schalttage eingefügt. Minuten und Sekunden sollen Sie eine Sekunde hinzuzählen. Zu einer gegebenen Zeit in Stunden. Aufgabe: Ein Kalenderjahr hat bekanntlich 365 oder 366 Tage. 49 Minuten. denn nun haben wir einen Hundertertstel Tag zuviel. Aus der Uhrzeit 12:59:59 wird beispielsweise nach der Addition von einer Sekunde die Zeit 13:00:00 Uhr. 5 Stunden.556. Seite 383 2. Alle vier Jahre wird mit dem 29. Nach dieser Regel war das Jahr 2000 ein Schaltjahr.und Sekundenwerte der Uhrzeit in drei Integerwerte ein. Februar ein Schalttag eingefügt. Schreiben Sie nun ein Python-Programm.

wahr ist.1 Karussell der Rumpf der Schleife ausgeführt. und es wird mit dem Rest des Skripts fortgefahren. Dieser Ausdruck bestimmt das Endekriterium der Schleife. ob diese nochmals erfüllt ist. Einen solchen Codeblock bezeichnet man auch als Schleifenkörper oder Body. Das unten stehende Diagramm zeigt dies schematisch. Vor jedem Schleifendurchlauf wird geprüft. Wenn ja. In Python gibt es zwei Schleifentypen: die while-Schleife und die for-Schleife. „True” liefert. ansonsten wird der Schleifenkörper nicht mehr ausgeführt. in dem diese Variable oder Variablen vorkommen. werden diese Variablen initialisiert. wird BILD 9. also eine oder mehrere PythonAnweisungen. geht es wie oben beschrieben weiter. Solange die Berechnung dieses Ausdrucks wahr ist.1 Schleifen Übersicht Schleifen werden benötigt. um einen Codeblock.9 9. die im Verlauf der Berechnungen innerhalb des Schleifenkörpers ihre Werte ändern. d. . springt die Programmsteuerung automatisch zum Anfang der Schleife. also zur Prüfung des Endekriteriums zurück und prüft wieder. ob ein Ausdruck. wiederholt auszuführen.h. das heißt noch vor dem Beginn der Schleife. Die meisten Schleifenarten. Nachdem alle Anweisungen des Schleifenkörpers durchgeführt worden sind. enthalten einen Zähler oder ganz allgemein Variablen. Außerhalb. die in Programmiersprachen Verwendung finden.

. 1 2 3 4 5 6 7 8 9 10 >>> Auch die Summe der Zahlen von 1 bis 100 lässt sich mittels einer while-Schleife leicht berechnen...2 while-Schleife Das folgende Skript... print(i) . i += 1 . das wir in der interaktiven Shell direkt eintippen können. wie wir im folgenden Programm sehen können: #!/usr/bin/env python3 n = 100 sum = 0 i = 1 while i <= n: sum = sum + i i = i + 1 print("Summe von 1 bis %d: %d" % (n.. gibt die Zahlen von 1 bis 10 unter Benutzung einer while-Schleife aus: >>> i = 1 >>> while i <= 10: .sum)) .60 9 Schleifen 9.

Hätte man die Anweisungen nicht in den else-Teil gesteckt.h. aber müssen nicht von einem else-Teil gefolgt werden. . der Spieler die Zahl erraten hat. wenn die Bedingung im Schleifenkopf erfüllt ist. einem einfachen Zahlenratespiel. wären sie ja auch genauso ausgeführt worden. dass in Kombination mit einem break der else-Zweig durchaus sinnvoll sein kann. d. Mit break kann man aber eine Schleife vorzeitig verlassen. sondern einfach hinter die while-Schleife gestellt. sobald die Bedingung nicht mehr erfüllt ist. Der else-Teil einer while-Schleife wird erst zusammen mit dem break-Kommando sinnvoll.3 die Alternative im Erfolgsfall: else 61 9. that you're giving up!") break 1 Es gibt auch eine else-Schleife in C und C++.3 else-Teil C-Programmierern1 wie auch Programmierern anderer Programmiersprachen kommt es meist sehr merkwürdig vor. Diese wird aber nur selten verwendet. break. dann wird der else-Zweig der while-Schleife nicht ausgeführt. d.random()) + 1 guess = 0 while guess != to_be_guessed: guess = int(input("New number: ")) if guess > 0: if guess > to_be_guessed: print("Number too large") else: print("Number too small") else: print("Sorry. worin dann der Unterschied zu einer normalen while-Schleife liegt. Gibt der Spieler auf. Normalerweise wird eine Schleife nur beendet. Im folgenden Beispiel. import random n = 20 to_be_guessed = int(n * random. Nur wenn die while-Schleife regulär beendet wird. Sicherlich fragen sich einige nun.h. kann man erkennen. Die Anweisungen im else-Teil werden ausgeführt. gibt es einen Glückwunsch. Schleifen können.9. wenn sie ein else ohne zugehöriges if finden.

auszuführen ist.py New number: 12 Number too small New number: 15 Number too small New number: 18 Number too large New number: 17 Number too small Congratulation. i++) printf("i: %d\n". i < 100. mit der eine Gruppe von Anweisungen (ein Block) wiederholt ausführt werden kann. Bei dieser Schleifenart handelt es sich um ein Sprachkonstrukt. bis der definierte Zielwert erreicht ist. die die Zahlen von 1 bis 100 ausdruckt: for( i = 0. von Programmiersprache zu Programmiersprache unterschiedlich. aber sehr wohl eine for-Schleife. meistens um einen bestimmten Wert (z. Man nennt diese Schleifenform auch Zählschleife. Wohlgemerkt „keine solche”. Die „klassische” numerische Schleife. besitzt eine Schleifenvariable. weil die Schleifenvariable und damit auch der Startwert. . der Endwert und die Schrittweite numerisch sein müssen. Dazu werden sie einer Variable zugewiesen. müssen wir Sie leider enttäuschen: Python kennt keine solche for-Schleife. d. You made it!") Die Ausgabe einer Spielsitzung könnte beispielsweise so aussehen: $ python3 number_game. Im folgenden Beispiel sehen wir eine for-Schleife in C. mit dessen Hilfe nacheinander die Elemente einer Menge oder Liste bearbeitet werden können.4 For-Schleife Wie auch die while-Schleife ist die for-Schleife eine Kontrollstruktur. i). 1) erhöht oder vermindert wird.62 9 Schleifen else: print("Congratulation. wie sie C und C++ kennt.h. Auch wenn Sie diese Schleifenform bereits in C oder einer anderen Sprache liebgewonnen haben.B. Sequenz steht für ein iterierbares Objekt. also wie sie vom Compiler oder Interpreter zu verstehen bzw. Im Folgenden sehen wir die allgemeine Syntax der for-Schleife in Python. Ebenso ist die Semantik einer for-Schleife. Die Syntax der forSchleifen unterscheidet sich in den verschiedenen Programmiersprachen. You made it! $ 9. Die in Python benutzte Art von for-Schleife entspricht der in der Bash-Shell oder in Perl verwendeten foreach-Schleife. die mit einem Startwert initialisiert wird und sich nach jedem Durchlauf des Schleifenkörpers verändert.

.. delicious " + food) else: print("I am so glad: No spam!") print("Finally. Dieser Block wird nur ausgeführt. erhalten wir folgende Ausgaben: . wenn die Schleife nicht durch eine break-Anweisung abgebrochen wurde. Else-Anweisung_m Wie bereits gesagt. falls es überhaupt noch Anweisungen nach der for-Schleife gibt. "Perl". I finished stuffing myself") Wenn wir obiges Beispiel unter for."eggs"... Das bedeutet. "C++". Üblicherweise befindet sich die break-Anweisung wie im folgenden Beispiel innerhalb einer Konditionalanweisung: edibles = ["ham". dass der else-Block nur dann ausgeführt wird. print(language) .. Beispiel einer for-Schleife in Python: >>> languages = ["C". Trifft der Programmablauf auf eine break-Anweisung..4 For-Schleife 63 for Variable in Sequenz: Anweisung_1 Anweisung_2 . während sie in vielen anderen Sprachen meist nur „eine etwas andere whileSchleife” ist. "spam". die der for-Schleife folgt. Anweisung_n else: Else-Anweisung_1 Else-Anweisung_2 .. dient in Python die for-Schleife zur Iteration über eine Sequenz von Objekten."nuts"] for food in edibles: if food == "spam": print("No more spam please!") break print("Great.py speichern und aufrufen.9. so wird die Schleife sofort verlassen und das Programm nach der Anweisung fortgesetzt.. wenn alle Elemente der Sequenz abgearbeitet worden sind. "Python"] >>> for language in languages: . C C++ Perl Python >>> Wie die while-Schleife besitzt auch die for-Schleife einen optionalen else-Block.

In diesem Fall kommt die continue-Anweisung ins Spiel. „spam” essen zu müssen: edibles = ["ham". delicious nuts I am so glad: No spam! Finally. delicious " + food) # here can be the code for enjoying our food :-) else: print("I am so glad: No spam!") print("Finally. erhalten wir folgende Ausgabe: $ python for. delicious ham No more spam please! Great. I finished stuffing myself $ Wenn wir „spam” aus der Liste der essbaren Dinge entfernen. delicious eggs Great. delicious nuts I am so glad: No spam! Finally. I finished stuffing myself $ Vielleicht ist unsere Abscheu vor dem Dosenfutter „spam” nicht so groß.64 9 Schleifen $ python for. dass wir sofort aufhören zu essen. „continue” schützt uns davor. "spam". "eggs".py Great. delicious ham Great. um mit dem nächsten Artikel der essbaren Artikel weiterzumachen. delicious ham No more spam please! Finally.py Great. I finished stuffing myself $ . Im folgenden kleinen Skript benutzen wir continue. delicious eggs Great.py Great."nuts"] for food in edibles: if food == "spam": print("No more spam please!") continue print("Great. I finished stuffing myself") Die Ausgabe sieht dann wie folgt aus: $ python for.

Für diejenigen.... XIX XX XXI . XXIX XXX XL L LX XC C CC CD D CM M MM Wert (Dezimalzahl) 1 2 3 4 5 6 7 8 9 10 11 . 14 15 16 . TABELLE 9..9..... geben wir hier die Zuordnungen in der folgenden Tabelle.1 Römische Zahlen Römische Zahl I II III IV V VI VII VIII IX X XI . die sich nicht so ganz sicher sind mit römischen Zahlen. 19 20 21 . XIV XV XVI .5 Aufgaben Für die erste Aufgabe benötigen wir die römischen Zahlen.5 Aufgaben 65 9. 29 30 40 50 60 90 100 200 400 500 900 1000 2000 .....

Um die Aufmerksamkeit des Königs auf seine Fehler zu lenken. Dieser wünschte sich Weizenkörner: Auf das erste Feld eines Schachbretts wollte er ein Korn. Aufgabe: BILD 9. Der Unterricht im Schachspiel machte auf Shihram einen starken Eindruck. Die Entfernung. Aufgabe). Er wurde milder und ließ das Schachspiel verbreiten. Besonders seine Art. ob der Frosch es auf die andere Straßenseite schafft. ein Spiel. damit alle davon Kenntnis nähmen. dann springt er wegen zunehmender Erschöpfung mit jedem weiteren Schritt immer nur noch halb so weit wie vorher. der weise Brahmane Sissa. auf das dritte wiederum . Lösung: 33. ohne seinen Zorn zu entfachen. mittels eines Python-Programmes herauszubekommen. in dem der König als wichtigste Figur ohne Hilfe anderer Figuren und Bauern nichts ausrichten kann.125 und so weiter.. gewährte er dem Brahmanen einen freien Wunsch. eine Straße zu überqueren. so wie ihn sich nur Mathematiker ausdenken können. Aufgabe: Schreiben Sie ein Python-Programm. auf das zweite Feld die doppelte Menge. Aufgabe: Der indische Herrscher Shihram tyrannisierte seine Untertanen und stürzte sein Land in Not und Elend.4 (2. Aufgabe). macht es zweifelhaft. die er dabei zurücklegt. Seite 385 2.66 9 Schleifen 1. berechnet sich also als Summe der Werte 1 + 0. Lösung: 33.4 (1.5 + 0. Seite 386 3. also zwei.2 Achtung Frösche In der nächsten Aufgabe lernen wir einen besonderen Frosch kennen. Er überquert eine 2. Um sich für die anschauliche Lehre von Lebensweisheit und zugleich Unterhaltung zu bedanken. das eine beliebige römische Zahl in eine „gewöhnliche” Dezimalzahl umrechnet.25 + 0. ob er in der realen Welt lange überleben könnte.50 Meter breite Straße wie folgt: Mit dem ersten Sprung legt er die erstaunliche Distanz von einem Meter zurück.. Dies entspricht natürlich in mathematischer Schreibweise der folgenden Notation: 1 1 1 1 1 = 1+ + + + . schuf Dahers Sohn. i 2 4 8 16 i =1 n Versuchen Sie.

Der Rechenmeister half dem Herrscher aus der Verlegenheit. Aufgabe). Auf allen Feldern eines Schachbretts zusammen wären es 18. Der Vorsteher der Kornkammer meldete nach mehreren Tagen ununterbrochener Arbeit. er solle Sissa ibn Dahir ganz einfach das Getreide Korn für Korn zählen lassen.073. dass die Rechenmeister die Menge der Weizenkörner noch nicht berechnet hätten. Lösung: 33. musste er hören. Als sich Shihram einige Tage später erkundigte. Nun stellte er sich die Frage.446. wie das Versprechen eingelöst werden könne.744. Seite 387 2 Die Weizenkornlegende wurde wörtlich von Wikipedia entnommen .4 (3.5 Aufgaben 67 doppelt so viele. wieviele Weizenkörner angehäuft werden müssen. dass er diese Menge Getreidekörner im ganzen Reich nicht aufbringen könne.9. Der König lachte und war gleichzeitig erbost über die vermeintliche Bescheidenheit des Brahmanen. indem er ihm empfahl.2 Berechnen Sie mit Hilfe eines Python-Programmes ohne eine Formel zu Hilfe zu nehmen.615 Weizenkörner. also vier und so weiter.551.709. ob Sissa seine Belohnung in Empfang genommen habe.

Mit . muss man zuerst die Datei zum Lesen öffnen. Die beiden Wörter Daten und Kartei wurden zu dem neuen Wort Datei verschmolzen. Namens wieder identifizierbar und damit ansprechbar sind. Die Bytes erhalten erst durch Anwendungsprogramme und das Betriebssystem eine Bedeutung.BILD 10. Auch wenn es so scheinen mag: Das Wort Datei ist kein altes deutsches Wort.10 10. Um dies tun zu können. Dazu benötigt man die open()-Funktion. Deswegen werden sie auch als nicht flüchtig oder persistent bezeichnet. Der Inhalt jeder Datei besteht grundsätzlich aus einer eindimensionalen Aneinanderreihung von Bits. ob es sich um eine Textdatei. was eine Datei ist. wie man Daten aus einer Datei ausliest.1 Dateien mung (DIN). Auch wenn nicht jeder eine exakte Definition geben könnte. der nicht wüsste. Sie entscheiden also.1 Dateien lesen und schreiben Dateien Man findet wohl kaum jemanden im 21. Es ist eine künstliche Schöpfung des Deutschen Instituts für Nor. Ein solches Kunstwort wird übrigens als Portmanteau oder Kofferwort bezeichnet. die normalerweise in Byte-Blöcken zusammengefasst interpretiert werden. Jahrhundert. also beispielsweise: Eine Datei ist eine Menge von logisch zusammenhängenden und meist sequentiell geordneten Daten.2 Text aus einer Datei lesen Unser erstes Beispiel zeigt. Die Daten einer Datei existieren also über die Laufzeit eines Programms hinaus. ein ausführbares Programm oder beispielsweise ein Musikstück oder ein Bild handelt. 10. die auf einem Speichermedium dauerhaft gespeichert werden und mittels eines Bezeichners bzw.

Deutsche Übersetzung: „Lass uns leben. darauf ein anderes Tausend und ein zweites Hundert. dein mille altera. wird automatisch Lesen zum Defaultwert: fobj = open("ad_lesbiam. Jede Zeile wird dann mit print ausgegeben.” .txt” zum Lesen. damit wir es nicht wissen. deinde centum.close() Führt man obiges Programm aus. noch irgendein Schlechter auf uns neidisch sein kann.txt". dein. dein secunda centum. aut ne quis malus invidere possit. müssen wir eine ewige Nacht schlafen. cum milia multa fecerimus. deinde centum.txt") for line in fobj: print(line. erhält man folgende Ausgabe1 : VIVAMUS mea Lesbia. werden wir jene verwirren.70 10 Dateien lesen und schreiben der open-Funktion erzeugt man ein Dateiobjekt und liefert eine Referenz auf dieses Objekt als Ergebniswert zurück. Die open-Funktion erwartet zwei Parameter: einen Dateinamen. Gib mir tausend Küsse. wie man eine Datei zeilenweise einliest. wie viele Küsse es gewesen sind. darauf hundert.rstrip()) fobj. deinde usque altera mille. ne sciamus. d. meine liebe Lesbia. Die String-Methode rstrip() entfernt vor der Ausgabe etwaige Leerzeichen und Newlines vom rechten Rand: fobj = open("ad_lesbiam. Das folgende Programmstück demonstriert. 1 Es handelt sich um ein Gedicht des Dichters Catullus. als nächstes ein weiteres Tausend und dann hundert. wenn wir viele Tausende gemacht haben.mode) Im folgenden Beispiel öffnen wir die Datei „ad_lesbiam. man liest eine Datei Zeile für Zeil. und optional kann man den Modus angeben: open(filename. Dann.h. Fehlt der Modus. gegebenenfalls mit einem Pfad. und lieben und lass uns alle Gerüchte der allzu strengen Alten nicht höher als einen Cent achten! Sonnen können untergehen und wieder aufgehen: wenn uns einmal das kurze Licht ausgeht. da mi basia mille. atque amemus. wenn er weiß. nox est perpetua una dormienda.txt") Sehr häufig bearbeitet man eine Datei zeilenweise. conturbabimus illa. da der Modus auf „r” (read) gesetzt ist: fobj = open("ad_lesbiam. rumoresque senum severiorum omnes unius aestimemus assis! soles occidere et redire possunt: nobis cum semel occidit brevis lux. cum tantum sciat esse basiorum. "r") Alternativ kann man die obige Anweisung auch ohne die Angabe des „r” schreiben.

fobj_in = open("ad_lesbiam. conturbabimus illa. rumoresque senum severiorum omnes unius aestimemus assis! soles occidere et redire possunt: nobis cum semel occidit brevis lux. cum milia multa fecerimus. "w") counter = 0 for line in fobj_in: counter += 1 out_line = "{0:>3s} {1:s}\n".rstrip()) fobj_out.format(str(counter). da mi basia mille.10. einen String oder eine Liste. deinde usque altera mille. nox est perpetua una dormienda. aut ne quis malus invidere possit.txt” enthält nach Ausführung des obigen Programms folgenden Text: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 VIVAMUS mea Lesbia. Auf diese Art kann die Datei schnell wieder geschlossen werden. dein secunda centum.h.write(out_line) fobj_in.4 Die Methoden read() und readlines() Bis jetzt haben wir Dateien Zeile für Zeile mit Schleifen verarbeitet.3 Schreiben in eine Datei Auch das Schreiben in eine Datei lässt sich in Python einfach bewerkstelligen. und man arbeitet anschließend nur noch auf der Datenstruktur weiter: . Zum Öffnen der Datei benutzt man „w” statt „r” als Modus. cum tantum sciat esse basiorum. dein mille altera. wir schreiben eine neue Datei. 10.txt") fobj_out = open("ad_lesbiam2.3 Schreiben in eine Datei 71 10. z.line. d. atque amemus. Aber es kommt öfters vor.close() fobj_out.txt". ne sciamus.B. dein. Im folgenden Programm versehen wir die vorige Datei mit Zeilennummern. deinde centum. die alle Zeilen der alten Datei plus eine Zeilennummer vor jeder Zeile enthält. deinde centum. Daten schreibt man in eine Datei mit der Methode write des Dateiobjekts. dass man eine Datei gerne in eine komplette Datenstruktur einlesen will.close() Die Datei „ad_lesbiam2.

\n'. \n'. bietet die Methode read() von open.txt"). Lösung: 33. wie wir im folgenden Beispiel zeigen: >>> poem = open("ad_lesbiam. 'da mi basia mille. deinde centum.txt"). 'omnes unius aestimemus assis!\n'. in der pro Zeile jeweils ein Vorname und ein Nachname steht. Seite 388 2.5 Aufgaben 1. . Aufgabe).\n'.readlines() >>> print(poem) ['VIVAMUS mea Lesbia. 'soles occidere et redire possunt :\n'. in der jeweils abwechselnd ein Vorname und ein Nachname in einer Zeile steht. dein secunda centum. 'conturbabimus illa . 10.read() >>> print(poem[20:34]) atque amemus. '\n'] >>> print(poem[2]) omnes unius aestimemus assis! Im obigen Beispiel wurde das ganze Gedicht in eine Liste namens poem geladen.\n'. 'aut ne quis malus invidere possit. 'dein.\n'. Aufgabe: Schreiben Sie ein Programm.5 (1. Aufgabe: Gegeben sei eine Datei.72 10 Dateien lesen und schreiben >>> poem = open("ad_lesbiam. atque amemus. deinde centum. 'cum tantum sciat esse basiorum. das jeweils drei Zeilen aus der folgenden Datei zu jeweils einer zusammenfasst und diese als Standardausgabe mittels print() ausgibt.\n'. eine Datei einzulesen.\n'. 'nox est perpetua una dormienda. Wir können nun beispielsweise die dritte Zeile mit poem[2] ansprechen. Mit dieser Methode kann man eine ganze Datei in einen String einlesen.\n'.\n'. 'nobis cum semel occidit brevis lux. 'dein mille altera. also beispielsweise so: Fred Miller Eve Turner Steve Baker Diese Datei soll in eine andere Datei überführt werden.\n'. 'rumoresque senum severiorum\n'. ne sciamus. Eine andere angenehme Methode. cum milia multa fecerimus. 'deinde usque altera mille.

Seite 389 . Künstlername soll in Klammern ausgegeben werden. Aufgabe). Aufgabe: Ändern Sie das vorige Programm so. Lösung: 33. „Marshall Bruce Mathers III (Eminem)”: Brian Molko Placebo Jim Morrison The Doors Ray Davies The Kinks Marshall Bruce Mathers III Eminem Andre Romelle Young Dr. eine Ausgabezeile soll jeweils den Vornamen. Der Band. Aufgabe).5 Aufgaben 73 D.10.bzw.5 (3.h. den Nachnamen und den Künstlernamen bzw. die Band des Künstlers enthalten. Also z.5 (2. dass es nun die Ausgabe in eine Ausgabedatei schreibt.B. Seite 389 3. Dre Beth Gibbons Portishead Lösung: 33.

um das oberste Element vom Stapel wegzunehmen.1 Listen und Tupel im Detail Stapelspeicher In den bisherigen Kapiteln haben wir bereits einiges über Listen erfahren.1 Alles Strings In den Programmiersprachen werden hierfür meistens die folgenden Operationen zur Verfügung gestellt: ■ push Mit dieser Methode legt man ein neues Objekt oben2 auf den Stapel. aber „append” erfüllt diese gleiche Funktionalität. was gelesen werden „muss”. je nach Sichtweise . die im Wesentlichen zwei Operationen besitzt: eine. Aber es fehlen noch einige wichtige Aspekte. mit der man Daten auf den Stapel legen kann. Bei Python gibt es im Gegensatz zu vielen anderen Sprachen keine Methode mit dem Namen „push”. BILD 11. Stellen Sie sich das wie einen Stapel noch zu lesender Bücher vor. ■ 1 2 englisch: stack oder „rechts”. und eine. kommt es oben drauf und ist damit das nächste Buch. pop Diese Methode liefert das oberste Objekt eines Stapels zurück.11 11. Man bezeichnet dies im Deutschen als „auskellern”. Sie wollen die Bücher des Stapels von oben nach unten durchlesen. In der Informatik bezeichnet ein Stapelspeicher (oder Stapel) – manchmal auch Kellerspeicher (Keller) genannt – eine Datenstruktur. Diese Operation bezeichnet man im Deutschen als „einkellern”. Kaufen Sie zwischendurch ein neues Buch. Dabei wird das Objekt vom Stapel entfernt. So kann man eine Liste auch wie einen Stapelspeicher1 behandeln.

kann man dem folgenden Beispiel entnehmen.append(x) Hängt x ans Ende der Liste s an. was dem „normalen” pop entspricht. Bei Listen oder Tupel kann man sie jedoch mit einem Indexzugriff simulieren. 'green'] BILD 11.pop() Ist i nicht angegeben.76 11 Listen und Tupel im Detail ■ peek Diese Methode dient zum Nachschauen. also in anderen Sprachen. wenn es peek bei Python gäbe. Dies entspricht der Methode „push”.pop() >>> c 'blue' >>> colors ['red'.2 ■ Stapelverarbeitung in Python s. 'green'. wie es in anderen Programmiersprachen verwendet wird. was zuoberst auf dem Stapel liegt. ■ ■ Wie man „pop” und „append” anwendet. >>> colors=["red".pop(i) Gibt das i-te Element von s zurück und entfernt es dabei aus der Liste. In Python gibt es keine solche Methode. das am weitesten rechts stehende Element zurück. Dabei wird das Objekt aber nicht wie bei pop entfernt. s. 'green'] >>> colors.peek().append(colors.2 pop und append . s. Falls „liste” eine Liste ist.pop()) >>> colors ['red'. 'blue'] >>> c = colors."green"] >>> colors. 11. liefert pop nur das „oberste” bzw. wird das letzte Element genommen. so wie sie sich in anderen Programmiersprachen findet. Normalerweise. dann entspricht liste[-1] einem liste.append("blue") >>> colors ['red'.

3. fib = [0. 1. 3.extend([8. 5. ' '.1.5] fib.1.21) l = [8.3 extend 77 11. 't'.21]) fib 1. 'S'.13. 13.extend("Ich bin ein String") >>> liste ['I'.13. 'n'.1. 'i'.extend(t) extend Die Methode „extend” dient dazu.4 Entfernen eines Wertes Mit der Methode „remove” kann man einen bestimmten Wert ohne Kenntnis des Indexes aus einer Liste entfernen. 3.remove(x) .extend(t) print fib 1.3 s. 5. 'g'] >>> 11. 8. Dabei muss das Argument „t” ein iterierbares Objekt sein. so wird der String in seine einzelnen Buchstaben zerlegt.1. 2. an eine Liste mehrere Elemente anzuhängen. 'r '.11.3. Das Ergebnis bleibt gleich: >>> >>> >>> >>> >>> [0. 'n'. 2. 'e'.3.5] fib.append([8. >>> t = (8.5] fib. 3.21] fib = [0. [8.3.13. 13. 'h'. 1. 2.1.13. 'b'. 1. 'n'.5] fib. 2. 'c'. 21] fib = [0. 13. ' '. 5.21]) fib 1.2. 5.1. 1. s.1.extend(l) print fib 1. 21]] Das Argument von extend() kann auch ein Tupel sein. 21] Übergibt man einen String als Argument für extend. 'i'.3. 8.2. die dann einzeln in die Liste eingefügt werden: >>> liste = [] >>> liste.1.2. fib = [0.2. >>> >>> >>> [0. 'i'. 13. 21] Man beachte den Unterschied zu append: >>> >>> >>> [0. >>> >>> >>> [0. 8. ' '.

Falls der optionale Parameter i gegeben ist. 'yellow'] >>> colours.index(x[.remove("green") Traceback (most recent call last): File "<stdin>". kann man mit „el in liste” testen. Im folgenden Beispiel rufen wir dreimal die remove-Methode auf. j]]) Es wird der Index für das x ermittelt. .remove(x): x not in list >>> 11. Da die Farbe nur zweimal in der Liste „colours” ist. >>> colours = ["red". „count” liefert die Anzahl der Vorkommen eines Elements in einer Liste zurück. i[.6 Positionsbestimmung Mit der Methode index kann man die Position eines Elements innerhalb einer Liste ermitteln. Es erfolgt eine Fehlermeldung. line 1. erhalten wir beim dritten Mal einen ValueError: >>> colours = ["red". "blue". 'blue'. beginnt die Suche erst ab dieser Position und endet bei der Position j. Man erhält als Ergebnis True. "yellow"] >>> colours. falls j gegeben ist. 'green'. gibt es einen ValueError. in <module> ValueError: list. "yellow"] >>> colours. "green". "green".5 Enthalten in Liste Wie wir bereits gesehen haben. 'yellow'] >>> colours. wenn „el” einmal oder mehrmals in der Liste vorkommt. Ist man an der genauen Anzahl interessiert. um die Farbe „green” zu entfernen. bietet sich die Methode „count” an.count("green") 2 >>> colours. s. "green". "blue".78 11 Listen und Tupel im Detail Dieser Aufruf entfernt das erste Vorkommen des Wertes x aus der Liste s. ob ein Wert „el” in der Liste „liste” vorkommt.remove("green") >>> colours ['red'.count("black") 0 >>> 11. falls x nicht in s vorkommt. Falls x beim Aufruf nicht in der Liste vorhanden ist. 'blue'. "green".remove("green") >>> colours ['red'.

object) Ein Objekt „object” wird in die Liste „s” eingefügt. 'yellow'] >>> Die Methode „append” lässt sich sehr einfach mit „insert” realisieren: >>> abc = ["a"."c"] >>> abc.8 Besonderheiten bei Tupel Wir haben bereits erfahren.4) 3 >>> colours. d. "green". man kann Elemente nicht entfernen.h. "blue". verändern oder neue Elemente anfügen. mittels append ein Element an eine beliebige Stelle einer Liste einzufügen.7 Einfügen von Elementen 79 >>> colours = ["red". "blue". "yellow"] >>> colours. Dazu gibt es die Methode „insert”: s. dass Tupel unveränderlich sind.insert(len(abc). wie wir im Folgenden sehen: .index("black") Traceback (most recent call last): File "<stdin>". 'green'. "green". line 1. >>> colours = ["red". 2) 3 >>> colours.index("green") 1 >>> colours.7 Einfügen von Elementen Wir haben gesehen. dass es die Methoden „pop”.index("green". 'black'. Aber es gibt keine Möglichkeit. "yellow"] >>> colours."b". "green". 'c'. 'b'. Auch über den Index kann man ein Tupel nicht verändern.11. 3.insert(index. 'd'] >>> 11. „append” und „insert” für Tupel nicht gibt. in <module> ValueError: 'black' is not in list >>> 11."d") >>> abc ['a'. 'blue'."black") >>> colours ['red'. Die früheren Elemente ab der Position index werden um eins nach rechts verschoben. dass wir mit append ein Element an das Ende einer Liste anhängen können.insert(1.index("green". Das bedeutet.

1. in <module> TypeError: 'tuple' object does not support item assignment >>> 11.13) >>> t[0] = 42 Traceback (most recent call last): File "<stdin>". Dies sieht nicht schön aus.2 1-Tupel Wie sieht es aber aus. also zum Beispiel: ((a + b ) ∗ c ) Aber auch dies ist ein gültiger Ausdruck: (c ) Damit versteht man auch. Hinter dem Wert muss ein Komma folgen.8.3. line 1.1 Leere Tupel Leere Tupel definiert man mit leeren runden Klammern: >>> t = () >>> type(t) <class 'tuple'> >>> 11.8. aber erfüllt seinen Zweck: >>> t = (5.) >>> type(t) <class 'tuple'> >>> .2.80 11 Listen und Tupel im Detail >>> t = (1. wenn man ein Tupel mit nur einem Element definieren will? Runde Klammern werden auch in arithmetischen Ausdrücken zur Klammerung von Teilausdrücken verwendet.5. dass „t = (5)” eine Integerzahl und nicht einen Einer-Tupel mit der Zahl 5 definiert: >>> t = (5) >>> type(t) <class 'int'> >>> Tupel mit nur einem Element kann man nur mit einem „Trick” generieren.8.

dass es doch geht: >>> galileo = ([]. y = y.) >>> Nein.y) 11 47 >>> Wir wollen nun zeigen. last) = t >>> print(first. dass es in Python eine Mehrfachzuweisung gibt. worin der Zusammenhang zwischen obigen Anweisungen und Tupeln besteht.8.) >>> galileo[0]. dass sich Tupel nicht verändern können! Oder können sie es vielleicht doch? Folgender Code zeigt scheinbar. Packing und Unpacking Wir haben schon gesehen.9 Die veränderliche Unveränderliche Wir haben festgestellt. Die folgende Anweisung bezeichnet man als Tupel-Packing. y = 47. da man die Zahlen 47 und 11 in ein Tupel packt: >>> t = "Philip". wenn man die einzelnen Werte eines Tupels Variablen zuordnet: >>> (first. . "Glass" >>> type(t) <class 'tuple'> >>> Dies ist gewissermaßen eine Kurzschreibweise für >>> t = ("Philip". Tupel sind unveränderlich. last) Philip Glass >>> 11. x >>> print(x.append("Sie dreht sich doch!") >>> galileo (['Sie dreht sich doch!'].11.3 Mehrfachzuweisungen. "Glass") Man spricht von Tupel-Unpacking oder Tupel-Entpacken. 11 >>> x. mit der man beispielsweise ideal Variablenwerte vertauschen kann: >>> x. so wie sich die Sonne auch nicht wirklich um die Erde dreht. keine Angst.9 Die veränderliche Unveränderliche 81 11.

12.8] >>> liste = liste. Wir haben also die Liste innerhalb des Tupels und nicht das Tupel selbst verändert. Versucht man.3 Alles Strings oder besser gesagt den speziellen Wert „None”.20. und die Liste ist verloren: >>> liste = [32. 11.12.20. dass man glaubt. und zum anderen die eingebaute Funktion „sorted”. >>> liste = [32.82 11 Listen und Tupel im Detail Im obigen Beispiel ist das erste und einzige Objekt ein Zeiger auf eine Liste. Schauen wir uns zunächst einmal „sort” an: >>> >>> >>> [7.7. Die Liste wird dann mit der in-Place-Methode append verändert. die die Liste inplace sortiert. in <module> TypeError: 'tuple' object does not support item assignment >>> Nach der Lektüre unseres Kapitels 13 (Flaches und tiefes Kopieren) sollte das oben Gesagte völlig klar sein. die aus einem Iterator-Objekt eine neue sortierte Liste baut.sort() >>> print(liste) None >>> . Ein beliebter Fehler besteht darin. dem ersten Element direkt einen neuen Wert zuzuweisen. dass liste.8] liste.sort() liste 8.sort() die sortierte Liste zurückgibt. 32] Die Methode „sort” sortiert also direkt das Objekt und liefert kein Ergebnis zurück BILD 11. 20.10 11. line 1. Im folgenden Beispiel hat dann „liste” nur noch den Wert „None”.12. erhält man wie erwartet einen Fehler: >>> galileo = ([].7.) >>> galileo[0] = "Sie dreht sich doch!" Traceback (most recent call last): File "<stdin>".10.1 Sortieren von Listen „sort” und „sorted” Zum Sortieren von Python-Listen gibt es zwei Möglichkeiten: zum einen die sortMethode der list-Klasse.

reverse=True) >>> x [32. .sort(reverse=True) >>> liste [32. dass man eine Liste oder ein iterierbares Objekt nicht nach der Standard-Ordnungsrelation sortieren will. x 2 . f (x n )] BILD 11. Die Arbeitsweise kann man sich mathematisch wie folgt vorstellen: Die zu sortierende Liste sieht wie folgt aus: l = [x 1 .3 Eigene Sortierfunktionen Manchmal kommt es vor. dann wird die ganze Liste mittels f in eine neue Liste abgebildet: [ f (x 1 ). Standardmäßig steht er auf False.2 Umkehrung der Sortierreihenfolge Um die Sortierreihenfolge umzukehren.4 sort mit eigener Sortierabbildung . 12.12. 12. 7. genügt es. 7] >>> liste.7. 7] >>> 11.11.10. x n ] Sei nun f die an „key” übergebene Funktion.12. . 20. f (x 2 ). . . 32] >>> liste [32.20.8] >>> x = sorted(liste. Für diesen Fall übergeben wir dem Schlüsselwortparameter „key” eine Funktionsreferenz auf eine Funktionsreferenz. 20. f (x 3 ).8] >>> x = sorted(liste) >>> x [7. 8. . x 3 . 12. sowohl bei „sort” als auch bei „sorted” den Schlüsselwortparameter „reverse” auf True zu setzen.10 Sortieren von Listen 83 Die Funktion „sorted” hingegen liefert als Ergebnis die sortierte Liste zurück. die als Argument den gleichen Typ wie die Listenelemente erwartet. 20. 12. 8. >>> liste = [32. .7.10. 20. 8.20. und die Originalliste bleibt unverändert: >>> liste = [32. 8] >>> 11.

Dazu müssen wir eine Funktion übergeben. "Baker". key=lambda x:x[0]) . (-4-7j)] >>> Im Folgenden wollen wir Listen mit Tupel oder anderen Listen als Elementen anhand einer bestimmten Komponente dieser Listen. 2 . "Green". -4 -7j. "red"] >>> sorted(l. filter und reduce. "Miller". "4289"). ("Tina". sondern eine. "blue". 3 +2j] >>> x.oder Tupelelemente sortieren. 'Green'. So beispielsweise auch nicht für die komplexen Zahlen. Sehr elegant kann man diese Aufgabe mit der lambda-Notation lösen. wenn zwei Werte. was einer Float-Zahl entspricht: >>> x = [ 3 + 4j. 'yellow'] >>> Wären alle Farben in obigem Beispiel klein geschrieben. map.1j. "blue". "Green". aber jedes Mal. "Black". (3+2j). (3+4j). "4103")] >>> sorted(phone. line 1.sort() Traceback (most recent call last): File "<stdin>". "Black". also x i und x j . "4567"). da „abs” die Länge eines Vektors berechnet. Seite 289 behandeln: >>> phone = [("John". key=str. die ein Tupel oder eine Liste als Argument hat und eine Komponente zurückliefert. 'Green'. 'red'. 2 . 'yellow'] >>> Bei Python ist nicht für jeden Datentyp oder Klasse eine Ordnung definiert. in <module> TypeError: unorderable types: complex() < complex() Übergibt man jedoch die Funktion „abs” an „key”. Wenn wir eine Liste von Strings sortieren.lower) ['Black'. Das heißt. funktioniert das Sortieren. sagen wir beispielsweise f (x i ) und f (x j ). Wir demonstrieren nun die Arbeitsweise von „key” im folgenden Beispiel. 3 +2j] >>> x. "red"] >>> sorted(l) ['Black'. erhält man einen „TypeError”: >>> x = [ 3 + 4j. die sich nach der Codierung der Zeichen richtet. Versucht man. (" Randy". werden auch die entsprechenden Elemente in l vertauscht. 'red'. eine Liste mit komplexen Zahlen zu sortieren. 'blue'. die wir aber erst in Kapitel lambda. 'blue'. erhalten wir keine alphabetische Sortierung.1j.sort(key=abs) >>> x [(2-1j). dass jeder Großbuchstabe bzgl. der Sortierreihenfolge kleiner ist als alle Kleinbuchstaben: >>> l = ["yellow". Dies führt uns zur Lösung: Wir bilden alle Strings mittels des Parameters „key” in Kleinbuchstaben ab: >>> l = ["yellow". -4 -7j.84 11 Listen und Tupel im Detail Die neue Liste wird von Python standardmäßig sortiert. vertauscht werden müssen. "Steiner". gäbe es das Problem nicht mit „Black” und „Green”.

"brown"] >>> numbers = [10. '4103'). auch mit der itemgetter-Funktion lösen: >>> from operator import itemgetter >>> phone = [("John". "pink".21...33.10 Sortieren von Listen 85 [('John'.15. ('Tina'. mit der man dann von einem beliebigen iterierbaren Objekt den Wert des Elementes an der Position „index” zurückliefert. "green". ('Tina'. "Steiner".33. "blue". '4103')] >>> sorted(phone. ('John'.11. "Miller". empfiehlt sich der Einsatz der Funktion „itemgetter” aus dem Modul „operator”.5. 'Steiner'. '4289').21. "yellow". dass man sich einen extra Funktionsnamen für den i-ten Itemzugriff anlegt. >>> from operator import itemgetter >>> colours = ["red". 'Baker'. key=lambda x:x[1]) [('Tina'. 'Miller'. ('Randy'. ' Baker'. "yellow". ' Steiner'. '4289')] >>> sorted(phone. "4567").8] >>> itemgetter(1)(colours) 'green' >>> itemgetter(1)(numbers) 15 >>> itemgetter(4)(numbers) 5 >>> itemgetter(4)(colours) 'pink' >>> Nun können wir unser ursprüngliches Sortierproblem. ("Tina". key=itemgetter(0)) . "4103")] >>> # nach dem 0-ten Index sortieren: . was wir bereits in lambda-Notation gelöst hatten. key=lambda x:x[2]) [('Randy'. "pink". Man kann dies auch direkt tun: >>> from operator import itemgetter >>> colours = ["red". "green". "4289"). '4103'). Die Funktion „itemgetter” wird mit einem Index „index” aufgerufen und liefert dann eine Funktion zurück.5. "blue". '4567'). ('Randy'. 'Steiner'.8] >>> get_index1 = itemgetter(1) >>> get_index1(colours) 'green' >>> get_index1(numbers) 15 >>> Natürlich bedarf es nicht des Umwegs. >>> sorted(phone. (" Randy". "brown"] >>> numbers = [10. '4567')] >>> Will man die Aufgabe ohne Hilfe der lambda-Notation lösen. "Baker". '4567'). '4289').15. ' Miller'. 'Miller'. 'Baker'. ('John'.

'Miller'. ('Randy'. '4289'). 'a'."c". ' Steiner'. '4289')] >>> # nach dem 1-ten Index sortieren: . Verzichten Sie aber auf die Benutzung der Listen-Methode „reverse” und versuchen Sie stattdessen.. >>> sorted(phone.[1. 'Steiner'. 'Steiner'. ('Randy'. Aufgabe: Aufgaben Schreiben Sie eine Funktion."c". ('John'. 1."a"] Lösung: Lösungen zu Kapitel 11 (Listen und Tupel im Detail).7]]. Aufgabe: Schreiben Sie mit Hilfe der Methoden extend() und append() eine Funktion flatten(). 1. ' Miller'. 1.. '4103'). >>> liste = ["a".7. ('Tina'. die eine verschachtelte Liste (oder ein Tupel) in eine flache Liste überführt.. 1. ('John'."d"] >>> rev(liste) ["d".h. '4289'). d. key=itemgetter(1)) [('Tina'. '4103')] >>> # nach dem 2-ten Index sortieren: . ' Baker'. type() wird auch benötigt. 'Python'. nur die Methoden „pop” und „append” zu benutzen. 'Baker'. '4567'). key=itemgetter(2)) [('Randy'. Seite 390 3..86 11 Listen und Tupel im Detail [('John'. "Python". 'Baker'."b". '4567')] >>> 11. 2.2). Seite 390 2. ["a"."b". 'Miller'.3] Lösung: Lösungen zu Kapitel 11 (Listen und Tupel im Detail). die die Reihenfolge einer Liste umkehrt.3]) [1.11 1. '4567'). ('Tina'. Aufgabe: Sortieren Sie eine Liste von Zahlen in alphabetischer Reihenfolge. '4103').1. Seite 391 . >>> flatten([(1. das gilt: 1 < 10 < 111 < 19 < 2 Lösung: Lösungen zu Kapitel 11 (Listen und Tupel im Detail). >>> sorted(phone.

('Tina'. Bei Gleichheit des Nachnamens sortieren Sie anhand des Vornamens weiter. ('Randy'. Die Häufigkeiten sollen sortiert ausgegeben werden. ('y'. 40. Aufgabe: Gegeben ist eine Liste von Verkäufern mit ihren getätigten Verkäufen für ein bestimmtes Produkt. 31. Beispiel: s = "Monty Python" x = letter_frequency(s) print x Ausgegeben wird: [('o'.99).11 Aufgaben 87 4. 'Baker'. 18.11. 23. ('Henry'. ('h'. Anzahl. ('t'. 27. 48.23). ('Eve'. 27. Nachname.56)] Sortieren Sie die Liste zuerst nach den Verkaufserlösen. 46. Lösung: Lösungen zu Kapitel 11 (Listen und Tupel im Detail). Seite 391 . 'James'. 2). ('m'. also dem Produkt aus der Anzahl und dem Einzelpreis. Einzelpreis): [ ('John'. Seite 391 5. 2). 'Steiner'. Dabei sollen keine Sonderzeichen und Ziffern berücksichtigt werden. 'Baker'. 2). 53. Aufgabe: Schreiben Sie eine Funktion. 1).67). 44. 1)] Lösung: Lösungen zu Kapitel 11 (Listen und Tupel im Detail). 'Miller'. ('p '.99). Die Liste besteht aus 4 Tupeln der Art (Vorname. 1). die die Buchstabenhäufigkeit eines Strings bestimmt. ('n'. 18. 'Turner'. 50. Dann geben Sie die Liste nochmals nach den Nachnamen sortiert aus. ('Andrea'.75). 2).

insbesondere bei größeren Software-Projekten. Der Ansatz der modularen Programmierung besteht darin. Es gibt verschiedene Konzepte. Modulares Design ist ein Ansatz. Computer gehören zu den Produkten. Das was für die Hardware ein Muss ist. Diese Komponenten bezeichnet man üblicherweise als Module. eine unvermeidliche Notwendigkeit dar. die lesbar. stellt auch für die Software. geht es nicht ohne modulares Software-Design. Unter modularem Design versteht man.12 12. Ein Modul kann unabhängig vom Gesamtsystem erzeugt und separat getestet werden. Wenn man Programme schreiben will. Mobiltelefone und so weiter. dass man ein komplexes System in kleinere selbständige Einheiten oder Komponenten zerlegt. die auf dem allgemeinen Prinzip des modularen Designs beruht. Es gibt: – die umfangreiche Standardbibliothek – eigene Module – Module von Drittanbietern . In den meisten Fällen kann man ein Modul auch in anderen Systemen verwenden. d.1 Modularisierung Module Modulare Programmierung ist eine Software-Designtechnik. aufzuspalten. BILD 12. das nicht auf Modularisierung beruht. um Programme modular zu gestalten. zuverlässig und und ohne hohen Aufwand wartbar sind. Programme systematisch in logische Teilblöcke. die bis zum Äußersten modularisiert sind. die auf ihr läuft. Module.1 Dateien Heutzutage gibt es kaum ein Produkt. so wie Autos.h. Die Aufteilung eines Quelltextes in einzelne Teile (Module) bezeichnet man als Modularisierung. der sich im Ingenieurwesen schon lange vor den ersten Computern als unausweichlich und unentbehrlich herausgestellt hat. In Python unterscheiden wir zwei Arten von Modulen: ■ Bibliotheken (Libraries) Stellen Datentypen oder Funktionen für alle Python-Programme bereit.

cos(math. wie der Name vermuten lässt.sin(math. in <module> NameError: name 'sin' is not defined . wird mit der import-Anweisung eingebunden.B.1. Mit der folgenden Anweisung wird beispielsweise das math-Modul aus der Standardbibliothek importiert.1415) 9.cos(math.pi/2) 6. Auf die sin()-Funktion des math-Moduls kann man zunächst nur über den vollen Namen („fully qualified”) zugreifen.sin()) und die Cosinus-Funktion (math.265358966049024e-05 sin() ohne Präfix math ist nicht bekannt und führt zu einer entsprechenden Fehlermeldung: >>> sin(3.123031769111886e-17 >>> math. line 1.141592653589793 >>> math. 12. dann stehen die Namen der Bibliothek in einem eigenen Namensraum zur Verfügung.90 12 Modularisierung ■ lokale Module nur für ein Programm verfügbar Ein Modul. egal ob aus der Standardbibliothek oder ein eigenes. mathematische Funktionen und Konstanten zur Verfügung. >>> math. d. import math Es stellt.1415) Traceback (most recent call last): File "<stdin>". so zum Beispiel die Konstante π (math.pi/2) 1. die Sinus-Funktion (math. manchmal auch als Bibliothek bezeichnet.pi) -1.0 >>> math.pi 3.sin(3. aber man sollte sie der Übersichtlichkeit willen an den Anfang stellen.cos()): >>> math.pi). random import-Anweisungen können an jeder Stelle des Quellcodes stehen.h.0 Nach dem Schlüsselwort import können auch mehrere durch Komma getrennte Modulnamen folgen: import math.1 Namensräume von Modulen Wird eine Bibliothek wie z. import math importiert.

ohne dass die Vorteile eines Namensraums aufgegeben werden: >>> import math as m >>> m. usw.1 Module 91 Möchte man gerne „bequem” auf Funktionen wie z.898 >>> from math import * >>> print(pi) 3.141592653589793 12. also ohne das Präfix math. Im Folgenden importieren wir math als m.dll.pi 3. Dabei werden dann gegebenenfalls bereits vorhandene gleichlautende Namen überschrieben.141592653589793 >>> sin(pi/2) 1.12.so.pyc Dynamisch geladene C-Module Endung: . Man im obigen Fall nur auf sin und pi zugreifen.3 Modularten Es gibt verschiedene Modularten: ■ in Python geschriebene Modulendung: .pi) 12.1. wie dies im folgenden Beispiel dargestellt wird: >>> pi = 57.B.1. . Man kann auch eine Bibliothek komplett in den globalen Namensraum einbinden.py oder .sl.. die Sinus-Funktion zugreifen können.2 Namensräume umbenennen Beim Import einer Bibliothek kann man auch einen neuen Namen für den Namensraum wählen.pyd. so kann man die entsprechenden Funktionen direkt importieren: >>> from math import sin. die mit dem Interpreter gelinkt sind ■ ■ .sin(m. Dies führt bei der Benutzung des mathModuls zu einer deutlichen Schreiberleichterung. pi >>> print(pi) 3. .141592653589793 >>> m.0 >>> Die anderen Methoden der Bibliothek stehen dann nicht zur Verfügung weder mit vollem Namen noch direkt. . C-Module.898 >>> print(pi) 57.

■ ■ sys. print(dir) . 'marshal'. '_weakref'. '_string'. '_random'.path: .2/plat-linux2 /usr/lib/python3. '_ast'.4 Suchpfad für Module Wenn man ein Modul importiert. ' itertools'. '_struct '. 'syslog'. 'imp'. 'fcntl'. '_pickle'. .B..py in der folgenden Reihenfolge ■ im aktuellen Verzeichnis PYTHONPATH Falls PYTHONPATH nicht gesetzt ist. '_io'. sucht der Interpreter nach abc. '_heapq'. 'zipimport'.2/dist-packages /usr/lib/python3/dist-packages In der folgenden interaktiven Sitzung sehen wir. 'posix'. 'select'.. 'pyexpat'. line 1. 'time'. 'spwd'. '_locale'.2 /usr/lib/python3. wie man herausfinden kann. wo sich ein zuvor geladenes Modul befindet: >>> import numpy >>> numpy.builtin_module_names) ('__main__'.92 12 Modularisierung Um eine Liste dieser Module zu erhalten: >>> import sys >>> print(sys. 'sys'.1. also unter Linux/Unix z.path enthält die Verzeichnisse. 'array'. abc.py' >>> import math >>> math.. '_warnings'. 'errno'. '_functools'. ist das __file__-Attribut nicht vorhanden. 'builtins'. 'unicodedata'. '_datetime'. 'xxsubtype'. ' _posixsubprocess'. '_bisect'. 'binascii'. 'math'. 'zlib') 12. wenn es sich bei dem Modul um ein C-Modul handelt. 'gc'. 'atexit '.__file__ '/usr/lib/python3/dist-packages/numpy/__init__. in <module> AttributeError: 'module' object has no attribute '__file__' Wir wir oben sehen. wird installationsabhängig im Default-Pfad gesucht. in denen Module gesucht werden: >>> import sys >>> for dir in sys. 'grp'. '_symtable'.. '_codecs'. /usr/lib/python3. '_sre'.B. ' _elementtree'. '_thread'. z.2/lib-dynload /usr/local/lib/python3. 'signal'.__file__ Traceback (most recent call last): File "<stdin>". 'operator'. '_collections'. 'pwd'.3. '_socket'. in /usr/lib/python3. welches statisch an den Interpreter gelinkt ist.

'cos'. def fib(n): a. "credits" or "license" for more information. 1 for i in range(n): a. 'ldexp'. b = 0.1. 19:53:57) [GCC 4.6 Eigene Module Eigene Module zu schreiben. 'acos'. 'exp'.5 >>> l = [2344. ist in Python extrem einfach. 'trunc'] Ohne Argumente liefert dir() die definierten Namen des Namensraums. ' math'] >>> 12. 'radians'. 'erf'. 'modf'. 'acosh'. 'sin'. 'factorial'. >>> import math >>> a = 42 >>> b = 4. 'expm1'. 'isinf'. '__name__'. 'gamma'. ' pow'. 'isfinite'. 'e'. 'atan2'."Hallo"] >>> dir() ['__builtins__'. 'log10'. 'sqrt'. '__doc__'. 'tanh'.12. 'atanh'. ohne es zu wissen. b = b. Oct 19 2012.7. 'sinh'. 'atan'. 'log'. in dem man sich befindet: $ python3 Python 3. '__package__'. 'asinh'.1 Module 93 12. 'log1p'. 'b'.1. >>> dir(math) ['__doc__'.1] for i in range(1. die den n-ten Fibonacci-Wert zurückliefert. 'erfc'. ' isnan'. 'a'. "copyright".5 Inhalt eines Modules Mit der built-in-Funktion dir() kann man sich die in einem Modul definierten Namen ausgeben lassen.3 (default. 'fabs'. 'tan'. '__package__'.py gespeichert. 'copysign'.2] on linux2 Type "help". '__name__'. Jedes Python-Programm ist automatisch auch ein Modul. 'fmod'. 'pi'. 'fsum'. 'lgamma'. a + b return a def fiblist(n): fib = [0. 'degrees '. 'cosh'. 'asin'. 'l'. 'ceil'. 'hypot'. Die beiden folgenden Funktionen fib().2. 'floor'. und die Funktion fiblist() werden in einer Datei fibonacci.n): fib += [fib[-1]+fib[-2]] return fib . Viele tun es. 'frexp'.

1 for i in range(n): a.py Wünschenswert wären jedoch noch allgemeine Informationen zum fibonacci-Modul und zu den einzelnen Methoden. falls fibonacci.py innerhalb des Suchpfads zu finden ist. Eine allgemeine Beschreibung des Moduls kann man in einem Docstring zu Beginn einer Moduldatei verfassen. 1.7 Dokumentation für eigene Module Auch wenn es so ist. 13. 5. so sollte jedes Modul dennoch über ausreichend Kommentare verfügen. Das pydoc-Modul erzeugt automatisch eine Dokumentation für jedes Modul. wie wir im vorigen Abschnitt gesagt haben. erhalten wir folgende Ausgabe: Help on module fibonacci: NAME fibonacci FUNCTIONS fib(n) fiblist(n) FILE /home/data/bodenseo/python/fibonacci. 55] >>> fibonacci. die Datei mit den beiden FibonacciFunktionen als Modul aufrufen.fib(10) 55 >>> fibonacci. b = b. Rufen wir beispielsweise help auf unser fibonacci-Modul auf. 1. a + b return a . 3. 21.fiblist(10) [0. 2. 34. >>> import fibonacci >>> fibonacci. b = 0.94 12 Modularisierung Von einem anderen Programm oder von der interaktiven Shell kann man nun. Die Funktionen dokumentiert man wie üblich mit einem Docstring unterhalb der ersten Funktionszeile: """ Modul mit wichtigen Funktionen zur Fibonacci-Folge """ def fib(n): """ Iterative Fibonacci-Funktion """ a. dass jedes PythonProgramm automatisch auch ein Modul ist.1. 8.__name__ 'fibonacci' >>> 12.

Kapitel. sucht.h. In diesem neu erzeugten Ordner muss man nun eine Datei mit dem Namen __init__. wenn dieser Inhalt nicht gegliedert ist.2 Beispielpaket in der Übersicht hatten wir Module kennengelernt. Was aber. Abschnitte und so weiter. Der dazu erforderliche Mechanismus ist in Python wiederum denkbar einfach gelöst. aber man wird wohl kaum diesen Inhalt an seine Leserinnen und Leser bringen können. Im vorigen Kapitel BILD 12.12. Ähnliches gilt natürlich auch für PythonProgramme. wenn wir die Übersicht über unsere Module verlieren könnten? Für diesen Fall hat Python das Paketkonzept.n): fib += [fib[-1]+fib[-2]] return fib Die help-Ausgabe sieht nun zufriedenstellend aus: Help on module fibonacci: NAME fibonacci . zu modularisieren. Man gliedert in Bücher.2 Pakete 95 def fiblist(n): """ produziert Liste der Fibo-Zahlen """ fib = [0. Die Datei .py 12. in dem Python Module erwartet bzw.2 Pakete Beim Verfassen sprachlicher Dokumente steht natürlich der Inhalt selbst im Vordergrund. Programme zu strukturieren bzw.py anlegen. modularisiert. wenn die Zahl unserer Module wächst. Wir können mehrere oder beliebig viele Module zu einem Paket „schnüren”. sind nur zwei Dinge zu tun: Man erzeugt einen Unterordner in einem Verzeichnis. Um ein Paket in Python zu erstellen.1] for i in range(1.Modul mit wichtigen Funktionen zur Fibonacci-Folge FUNCTIONS fib(n) Iterative Fibonacci-Funktion fiblist(n) produziert Liste der Fibo-Zahlen FILE /home/data/bodenseo/python/fibonacci. Werden sie nicht ordentlich gegliedert. d. die sich hervorragend eignen. sie zu verstehen und zu warten. wird es schwer. Unterkapitel.

in <module> AttributeError: 'module' object has no attribute 'a' Jetzt kann man das Initialisierungsverhalten von __init__. Außerdem legen wir noch zwei einfache Module in diesem Verzeichnis an: ein Modul namens „a.py” und diesem Inhalt: def foo(): print("Hello.f1() Hello.a. dass die Module in einem Paket nicht automatisch importiert werden: >>> import SimplePackage >>> SimplePackage.f1() Hello. Unser Paket soll SimplePackage heißen.py ideal einsetzen. Pakete können wiederum Pakete enthalten.96 12 Modularisierung kann leer sein oder Initialisierungscode enthalten. f1 from module 'a' calling Wie wir gesehen haben. wie man ein Paket erzeugt. f1 from module 'a' calling >>> b. Dies liegt daran. 1 2 In Linux oder Unix können wir dies mit dem Befehl „mkdir SimplePackage” tun.foo() Hello. der beim Einbinden des Pakets einmalig ausgeführt wird. >>> import SimplePackage >>> SimplePackage. foo from module 'b' calling Versucht man.f1() Traceback (most recent call last): File "<stdin>". foo from module 'b' calling") Nun sind wir in der Lage. .py__”.b >>> a. Wir fügen in diese bisher leere Datei die Zeile „from SimplePackage import a. also mittels „import SimplePackage” zu importieren. erhalten wir keine Fehlermeldung und können auch auf die Module wie gewünscht zugreifen. das Paket SimplePackage direkt. unser Paket zu benutzen: >>> from SimplePackage import a.py” mit folgendem Inhalt def f1(): print("Hello.a. In diesem Ordner legen wir eine leere Datei mit dem Namen __init__. In Linux kann man dies mit einem touch-Kommando am einfachsten tum: „touch __init. Im Folgenden zeigen wir nun anhand eines einfachen Beispiels. erhält man eine Fehlermeldung. Dazu erzeugen wir einen Ordner1 mit dem Namen SimplePackage. b” ein und können nun obigen Versuch wiederholen. f1 from module 'a' calling") sowie ein weiteres Modul mit dem Name „b.py an2 . line 1.

für y angelegt. zu verblüffenden und verwirrenden Erfahrungen kommen.oder wird eine eigene Speicherzelle. Diese Identität. d.oder besser das gleiche Objekt . Betrachten wir folgenden Code: >>> x = 3 >>> y = x BILD 13. solange es im Programmablauf existiert. was bei der Zuweisung „y = x” passiert? Bezeichnen x und y die gleiche Speicherzelle . falls sie die genauen Zusammenhänge nicht kennen. id(obj) liefert die „Identität” des Objekts obj. x und y teilen sich das gleiche Objekt. d. Dabei kann es vor allem bei Anfängern. die meist mit Fehlern im Programm einhergehen.h. der eindeutig und konstant für dieses Objekt ist. die ein Objekt als Parameter hat. ein eigenes Objekt.h. Im Folgenden werden wir die Identitätsfunktion id() benutzt.1 Tiefsee Es stellt sich die Frage.13 13. der Rückgabewert der Funktion.1 Flaches und tiefes Kopieren Einführung In diesem Kapitel geht es nun um das Kopieren von Listen und vor allem um das Kopieren von verschachtelten Listen. in das die Zahl 3 kopiert wird? Ersteres ist der Fall. ist ein Integer. Bildlich kann man sich dies wie folgt veranschaulichen: .

Kritisch wird es jedoch.3 (default. sie „zeigen” bzw. "credits" or "license" for more information. wenn wir einer der beiden Variablen einen neuen Wert zuweisen. 19:53:57) [GCC 4. dass es der Anwender.B. . explizit verlangt. >>> x = 3 >>> y = x >>> id(x) == id(y) True >>> print(id(x). Wir zeigen. wenn wir veränderliche (mutable) Objekte wie Listen und Dictionaries kopieren wollen. so entsprechen die Resultate der Zuweisungen dennoch unseren Erwartungen. Oct 19 2012. d.h. d. Ansonsten verhält sich Python ebenso wie im obigen einfachen Beispiel: Es gibt nur Zeiger auf das gleiche Objekt.7. dass dies wirklich so ist.2] on linux2 Type "help". also z. wenn es unbedingt muss. können wir mittels der id-Funktion führen. Im Folgenden wollen wir dies im Detail darstellen und auf einige Probleme eingehen.98 13 Flaches und tiefes Kopieren Den Beweis.2.h. also der Programmierer. teilen sich das gleiche Objekt: $ python3 Python 3. Python legt nur dann echte Kopien an. Perl etc. also beispielsweise die Zahl 4 der Variablen y: >>> y = 4 >>> id(x) == id(y) False >>> print(x. die beim nicht „korrekten” Kopieren von veränderlichen Objekten entstehen können. ist. id(y)) 137220832 137220832 Was passiert nun. dass die Identität von x und y gleich sind. "copyright".y) 3 4 >>> Bildlich sieht die Situation nun also wie folgt aus: Aber auch wenn das obige Verhalten ungewöhnlich im Vergleich zu anderen Programmiersprachen wie C. beim Kopieren von Listen und Dictionaries. C++.

"vert"] >>> print(colours1) ['red'. sondern nur ein einzelnes Element der Liste ändern. was passiert. 'blue'] >>> print(colours2) ['red'. BILD 13.id(colours2)) 3072482700 3072482700 >>> colours2 = ["rouge".2 Kopieren von Listen zu. Mit „flach” (Englisch in diesem Zusammenhang: shallow) meinen wir. wenn wir einer Variablen nicht ein neues Elements zuordnen. 'vert'] >>> print(id(colours1). 'green'] >>> print(colours2) ['red'.2 Kopieren einer Liste 99 13. dass beide Variablen auf das gleiche Listenobjekt zeigen. also keine weiteren Unterlisten enthält. "green"] >>> colours2 = colours1 >>> print(colours1) ['red'. Mittels der print()-Funktion können wir uns überzeugen.3 Kopieren von Listen .2 Kopieren einer Liste >>> colours1 = ["red". wenn dieser Variablen eine komplett neue Liste (also ein neues Objekt) zugeordnet wird. >>> colours1 = ["red". Es erstaunt wenig. dass die Liste nicht verschachtelt ist. Nun weisen wir colours2 eine neue Liste zu. Anschließen weisen die Liste colours1 einer Variablen colours2 BILD 13.id(colours2)) 153810028 153810028 >>> colours2[1] = "blue" >>> print(id(colours1). Wie im obigen Beispiel mit den Integer-Variablen wird ein neuer Speicherbereich für colours2 angelegt.id(colours2)) 3072482700 3072470444 Im obigen kleinen Code-Beispiel legen wir als Erstes eine flache colours1 an. dass die Werte von colours1 dabei unverändert bleiben.id(colours2)) 153810028 153810028 >>> print(colours1) ['red'. dass beide Variablen den gleichen Inhalt haben. 'green'] >>> print(colours2) ['rouge'. "green"] >>> colours2 = colours1 >>> print(id(colours1).13. 'blue'] >>> Im obigen Beispiel sind wir der Frage nachgegangen. 'green'] >>> print(id(colours1). und mittels id() sehen wir.

['ab'. führt dies nicht zu einem Nebeneffekt. 'd']] Man erkennt. also dem Element mit dem Index 1. ändern wir nun zwei Einträge in lst2: >>> lst1 = ['a'. Viele wird es nun erstaunen. Probleme gibt es erst. sondern auch den Eintrag von lst1[2][0]. wie man im folgenden Beispiel sehen kann: >>> liste1 = ['a'. dass man aber nicht nur die Einträge in lst2 geändert hat. Diese Unterliste wurde nicht mit [:] mitkopiert. ['ab'.100 13 Flaches und tiefes Kopieren Um dies zu testen. BILD 13. werden nur Zeiger auf diese Unterlisten kopiert: Dieses Verhalten beim Kopieren veranschaulicht das nebenstehende Bild. 'd'] >>> Sobald jedoch auch Unterlisten in der zu kopierenden Liste vorkommen. 'd'] >>> print(liste1) ['a'. Dies liegt daran. BILD 13. also lst1 und lst2. dass beide Variablen weiterhin auf das selbe Listenobjekt zeigen.4 Kopieren von Listen Um dies zu demonstrieren. 13. sehen wir. 'x'.'c'. wenn man direkt eines der beiden Elemente der Unterliste verändert. einen neuen Wert zu. weisen wir dem zweiten Element von colours2.'ba']] >>> lst2 = lst1[:] >>> lst2[0] = 'c' >>> lst2[2][1] = 'd' >>> print(lst1) ['a'.3 Kopie mit Teilbereichsoperator Mit dem Teilbereichsoperator (slicing) kann man flache Listenstrukturen komplett kopieren. 'b'. das jeweils dritte Element nur ein Link auf eine physikalisch gleiche Unterliste ist.'b'. 'c'.5 Kopieren von Listen .'b'. 'b'. ohne dass es zu Nebeneffekten kommt. dass in beiden Listen. obwohl man doch eine Kopie von colours1 gemacht zu haben glaubte. Wenn wir uns die Speicherorte mittels der Funktion id() anschauen. Weist man nun zum Beispiel dem 0-ten Element einer der beiden Listen einen neuen Wert zu. dass auch colours1 damit verändert wurde. 'c'.'d'] >>> liste2 = liste1[:] >>> liste2[1] = 'x' >>> print(liste2) ['a'.

'b': '2.'ba']] >>> lst2 = deepcopy(lst1) >>> lst2[2][1] = "d" >>> lst2[0] = "c".13. Buchstabe'} >>> d {'a': '1. 'b': '2. Dieses Modul stellt die Methode „deepcopy” zur Verfügung. ['ab'.5 Deepcopy für Dictionaries deepcopy aus dem Modul copy funktioniert für beliebige Python-Objekte.h. Das Gleiche gilt natürlich auch umgekehrt. 'b'. Buchstabe". die das komplette Kopieren einer nicht flachen Listenstruktur erlaubt.4 Kopieren mit deepcopy aus dem Modul copy Abhilfe für das eben beschriebene Problem schafft das Modul „copy”. 'b': '2. Buchstabe'} Achtung: Die Methode copy der Klasse dict erzeugt nur flache Kopien eines Dictionarys. also beispielsweise auch für Dictionaries: >>> from copy import deepcopy >>> d = {"a":"1. >>> print(lst2) ['c'.4 Kopieren mit deepcopy aus dem Modul copy 101 13. Buchstabe'. 'ba']] BILD 13. Das folgende Skript kopiert unser obiges Beispiel nun mit Hilfe dieser Methode: >>> from copy import deepcopy >>> lst1 = ['a'. Buchstabe'} >>> d {'a': '1. Änderungen an „lst1” wirken sich nicht auf „lst2” aus. Buchstabe"} >>> d2 = deepcopy(d) >>> d2 {'a': '1. ['ab'. Buchstabe'. 13. Buchstabe'} >>> d2["a"] = "Erster Buchstabe" >>> d2 {'a': 'Erster Buchstabe'.['ab'. Buchstabe'. wirken sich Änderungen „lst2” nicht auf „lst1 aus.'b'. wie wir im Folgenden sehen können: . 'b': '2. 'b'.6 Kopieren mit Deepcopy Da es sich nun um eine vollständige Kopie ohne gemeinsame Referenzen handelt. "b":"2. 'd']] >>> print(lst1) ['a'. d.

"de_fr" : de_fr } >>> d2 = d. "green" : "grün". "grün" : "vert". 'red': 'rot '}. 'blau': 'bleu'. 'rot': 'rouge'}} >>> d2 {'en_de': {'blue': 'blau'. 'green': 'grün'. "blau" : "bleu"} >>> d = {"en_de" : en_de. 'blau': 'bleu'. "green" : "grün". 'green': 'grün'. 'red': 'rot'}. "blue" : "blau"} >>> de_fr = {"rot" : "rouge". 'blau': 'bleu'. und das Problem ist behoben: >>> from copy import deepcopy >>> en_de = {"red" : "rot". "grün" : "vert". "de_fr" : de_fr } >>> >>> d2 = deepcopy(d) >>> >>> d["en_de"]["brown"] = "braun" >>> >>> d {'en_de': {'blue': 'blau'. 'green': 'grün'. 'green': 'grün'. 'rot': 'rouge'}} >>> . 'brown': 'braun'.102 13 Flaches und tiefes Kopieren >>> en_de = {"red" : "rot". 'red': 'rot'}. 'de_fr': {'grü n': 'vert'. 'blau': 'bleu'. 'rot': 'rouge'}} >>> d2 {'en_de': {'blue': 'blau'. "blau" : "bleu"} >>> d = {"en_de" : en_de. "blue" : "blau"} >>> de_fr = {"rot" : "rouge". 'rot': 'rouge'}} >>> Nun erzeugen wir mit deepcopy eine Kopie.copy() >>> d {'en_de': {'blue': 'blau'. 'red': 'rot'}. 'de_fr': {'grü n': 'vert'. 'de_fr': {'grün': 'vert'. 'de_fr': {'grü n': 'vert'.

was natürlich sehr fehlerträchtig wäre. Außerdem senkt die Verwendung von Funktionen auch die Kosten für die Software-Entwicklung und die Wartung der Software.14 14. Prozeduren. Routinen. damit man sie mehrmals im Programm verwenden kann. Eine solche Funktion berechnet ein oder mehrere Werte und ist vollständig von den übergebenen Eingabewerten. Dann müsste man den Code entBILD 14. den sogenannten Parametern. um eine Menge von Anweisungen zu gruppieren. Spätere Änderungen müssten dann an allen kopierten Stellen nachgezogen werden.1 Funktionen sprechend anpassen. Ohne Funktionen könnte man Code nur kopieren. Funktionen kennt man unter unterschiedlichen Bezeichnungen in verschiedenen Programmiersprachen. Auch in Programmiersprachen werden Funktionen häufig eingesetzt. Ganz allgemein gesehen stellt eine Funktion ein Strukturierungselement in einer Programmiersprache dar. Die Benutzung von Funktionen erhöht die Verständlichkeit und Qualität eines Programms oder Skripts. . So kennt man sie auch als Subroutinen.1 Funktionen Allgemein Das Konzept einer Funktion gehört wohl zu den bedeutendsten der Mathematik. um mathematische Funktionen in Algorithmen umzusetzen. um ihn wiederzuverwenden. Methoden und Unterprogramme. abhängig.

Also ebenso wie alle anderen Blöcke in Python. wird in Python durch eine eine homogene Einrückung markiert. Die optionalen Parameter (0 oder mehr) folgen den obligatorischen. Die Parameter der Definition werden beim Aufruf der Funktion als Argumente bezeichnet. Der Funktionskörper kann ein oder mehrere return-Anweisungen enthalten. Schauen wir uns ein einfaches Beispiel an: def say_hello(name): return "Hello " + name n = "Michael" n = say_hello(n) print(n) name = "Kirstin" name = say_hello(name) print(name) BILD 14. Der Funktionskörper (function body). der hinter der returnAnweisung steht. wird an die aufrufende Stelle zurückgeliefert. Diese können sich an beliebiger Stelle innerhalb des Funktionskörpers befinden. wenn eine Anweisung erfolgt. Parameter können obligatorisch und optional sein. und das Ergebnis des Ausdrucks. endet der Funktionsaufruf. die bei Aufruf der Funktion ausgeführt werden. Meistens werden die beiden Begriffe jedoch fälschlicherweise wie Synonyme verwendet.2 Funktionen in Python Funktionen werden mit dem Schlüsselwort def eingeleitet def funktions-name(Parameterliste): Anweisung(en) Die Parameterliste besteht aus einem oder mehr Bezeichnern. ohne auf eine return-Anweisung gestoßen zu sein. wird der spezielle Wert None zurückgeliefert. Falls kein Ausdruck dem return folgt.2 Funktionsaufrufe . und es wird ebenfalls der Wert None zurückgegeben. Programmablauf: Falls der Funktionsaufruf das Ende des Funktionskörpers erreicht. also die Anweisungen. Die Funktionsdefinition ist beendet.104 14 Funktionen 14. Eine return-Anweisung beendet den Funktionsaufruf. die wieder auf derselben Einrückungsstufe steht wie der Kopf der Funktion. die durch Kommata getrennt sind.

Falls beim Aufruf allerdings kein Name übergeben wird. Sie wird beim Lauf des Programms „übersprungen”. Als erste Anweisung wird die Zuweisung an die Variable n ausgeführt.8 27. Wir zeigen dies an einem Beispiel. Danach wird die Variable „name” auf „Kirstin” gesetzt. 27.44 81. 25. Man nennt sie auch Default-Parameter.6 25. Das folgende kleine Skript.3 29. begrüßt eine Person mit Namen.3. die dann den String „Hello Kirstin” zurückliefert.6. die beim Aufruf nicht angegeben werden müssen.3 Optionale Parameter 105 Im nebenstehenden Diagramm zeigen wir.14. Zurückgeliefert wird der String „Hello Michael”.8): print(t. was passiert. Dies sind Parameter. druckt sie nur „Hello everybody!”: def Hello(name="everybody"): """ Greets a person """ print("Hello " + name + "!") Hello("Peter") Hello() Die Ausgabe sieht wie folgt aus: Hello Peter! Hello everybody! . wenn man obiges Programm ausführt. fahrenheit(t)) Die Ausgabe des obigen Skripts mit der Funktion fahrenheit: 22.64 14. das nicht sehr nützlich ist.3 Optionale Parameter Funktionen können auch optionale Parameter haben. Danach wird die Funktion say_hello mit dem Argument n aufgerufen.8 : : : : 72.14 85. Beim ersten Teil des Programms handelt es sich um die Definition der Funktion. Dann wird wieder die Funktion say_hello aufgerufen.8. Ein weiteres Beispiel: def fahrenheit(T_in_celsius): """ returns the temperature in degrees Fahrenheit """ return (T_in_celsius * 9 / 5) + 32 for t in (22.68 78. ": ". In diesem Fall werden dann Default-Werte für diese Parameter eingesetzt. 29.

Aber was wird zurückgeliefert.d print(sumsub(12. Diese Anweisung wird Docstring genannt. wenn wir keine explizite Rückgabeanweisung haben? Wir wollen es uns an einem Beispiel anschauen: .b + c . Wenn wir keine Schlüsselwortparameter hätten. eine Funktion aufzurufen.15. Man sieht also. die nicht bereits als Positionsargumente verwendet wurden. die als Funktionsname. c=0. Beispiel: def Hello(name="everybody"): """ Greets a person """ print("Hello " + name + "!") print("The docstring of the function Hello: " + Hello. obwohl c nur den Default-Wert haben muss: print(sumsub(42.5 Schlüsselwortparameter Dabei handelt es sich um eine alternative Möglichkeit.__doc__ abfragbar ist. Ein Beispiel: def sumsub(a.0.106 14 Funktionen 14. aber nicht in Hello verwendet.4)) print(sumsub(42.d=10)) Als Schlüsselwortparameter dürfen nur solche verwendet werden.4 Docstring Die erste Anweisung eines Funktionsrumpfs ist normalerweise eine Zeichenkette. eine return-Anweisung in einer Funktion zu haben. Wir können den Vorteil im Beispiel sehen. müssten wir im zweiten Funktionsaufruf alle Argumente angeben. b. Die Funktionsdefinition selbst ändert sich nicht. d=0): return a .15. dass es nicht zwingend notwendig ist.6 Rückgabewerte In unseren früheren Beispielen haben wir return-Anweisungen in der Funktion sumsub.10)) 14.__doc__) Die Ausgabe: The docstring of the function Hello: Greets a person 14.

sie liefert ein 2-Tupel zurück. Das bedeutet. Der Rückgabewert wird direkt mittels „unpacking” in die Variablen lub und sup gespeichert: def fib_intervall(x): """ returns the largest fibonacci number smaller than x and the lowest . wie wir im folgenden Beispiel sehen: def empty_return(x. wird None gedruckt. Im folgenden Beispiel berechnet die Funktion fib_intervall die Fibonacci-Begrenzung für eine beliebige positive Zahl. aber auch ein komplexes Objekt wie etwa eine Liste oder ein Dictionary. d. und die zweite Komponente ist die kleinste Fibonacci-Zahl größer oder gleich x. dass wir indirekt auf eine sehr einfache Art und Weise beliebig viele Werte zurückliefern können. Dieser Wert wird aber auch zurückgeliefert.5) print(res) 14. haben wir die Möglichkeit. Im nächsten Beispiel wird 9 zurückgeliefert: def return_sum(x. die ohne return-Anweisung endet. Wenn wir beispielsweise drei Integers zurückliefern wollen.5) print(res) Ansonsten wird der Wert des Ausdrucks hinter dem return zurückgeliefert.7 Mehrere Rückgabewerte Eine Funktion kann genau einen Wert zurückliefern oder wir sollten besser sagen: genau ein Objekt.h.h. None zurückliefert.5) print(res) Wenn wir das obige kleine Skript starten. der spezielle Wert None wird von der Funktion no_return zurückgeliefert. wenn eine return-Anweisung ohne nachfolgenden Ausdruck eine Funktion beendet.7 Mehrere Rückgabewerte 107 def no_return(x. Ein Objekt kann beispielsweise ein numerischer Wert wie eine ganze Zahl (Integer) oder eine Nachkommazahl (float) sein. die kleiner oder gleich x ist. diese in ein Tupel oder eine Liste zu packen und dieses Listenoder Tupel-Objekt als return-Wert zu übergeben. d. Das zeigt.y): c = x + y return c res = return_sum(4.14.y): c = x + y res = no_return(4. Das erste Element ist die größte Fibonacci-Zahl. dass eine Funktion.y): c = x + y return res = empty_return(4.

108 14 Funktionen fibonacci number higher than x""" if x < 0: return -1 (old.8 Lokale und globale Variablen in Funktionen Variablen sind standardmäßig (by default) lokal in einer Funktion.0) while True: if new < x: lub = new (old. sup) = fib_intervall(x) print("Largest Fibonacci Number smaller than x: " + str(lub)) print("Smallest Fibonacci Number larger than x: " + str(sup)) 14.1. new) while True: x = int(input("Your number: ")) if x <= 0: break (lub. Erweitern wir nun die Funktion f um die Zuweisung s = „Perl” vor der print-Anweisung: def f(): s = "Perl" print(s) s = "Python" f() print(s) Die Ausgabe lautet dann: Perl Python . lub) = (0.old+new) else: return (lub.new.new) = (new. Allerdings kann auch auf globale Variablen innerhalb einer Funktion lesend zugegriffen werden: def f(): print(s) s = "Python" f() Das obige Skript gibt „Python” aus. in der sie definiert werden.

9 Beliebige Anzahl von Parametern 109 Daran erkennt man. Man kann dies in Python durch eine sogenannte Tupel-Referenz realisieren.9 Beliebige Anzahl von Parametern Man hat sehr häufig Fälle. was man keineswegs mit der entsprechenden C-Syntax verwechseln sollte. d. wenn man eine print-Anweisung vor die Zuweisung an s in der Funktion f einfügt: def f(): print(s) s = "Perl" print(s) s = "Python" f() print(s) Man erhält nun die folgende Fehlermeldung: UnboundLocalError: local variable 's' referenced before assignment Die Variable s ist in f() mehrdeutig. Der letzte Parameter erhält einen * vorangestellt.14. in denen die Anzahl der beim Aufruf nötigen Parameter a priori nicht bekannt ist. . dass die Variable s innerhalb der Funktion f lokal ist. so muss man diese explizit als global deklarieren. Anschließend definieren wir eine lokale Variable mit dem Wert „Perl”. Dies geschieht mittels der global-Anweisung: def f(): global s print s s = "Perl" print s s = "Python" f() print s Die Ausgabe lautet: Python Perl Perl 14.h. im ersten print von f() könnte es sich um die globale Variable s mit dem Wert „Python” handeln. Will man innerhalb einer Funktion auf eine globale Variable schreibend zugreifen. denn die Variable s des Hauptprogramms wurde nicht durch die Zuweisung in der Funktion verändert. Interessant wird es nun.

Parameter stehen im Kopf der Funktion oder Prozedur. Prozedur. Indem man Parameter benutzt. und die Semantik. Bei einigen Lesern hat sich sicherlich der Eindruck eingestellt.78. wie man die Argumente des Aufrufs an die formalen Parameter der Funktion oder Prozedur weiterleitet. Sie liefern die Werte für die formalen Parameter während der Laufzeit des Programmes.31 77 45 0 14.32. den man als „Call by Object” (auch „Call by Object Reference” oder „Call by Sharing”) bezeichnet. d. während Argumente beim Aufruf verwendet werden. dass die beiden Begriffe synonym sind.89.78778. Python benutzt einen Mechanismus.bzw. Auch in der Literatur werden diese Begriffe häufig synonym verwendet. also in der Definition der Funktion oder Prozedur. sind abhängig von der jeweiligen Programmiersprache. besteht aus speziellen Variablen. Die Referenz auf das unveränderliche Objekt wird an den formalen Parameter der Funk- BILD 14.8.73)) print(arithmetic_mean(45.78)) print(arithmetic_mean(8989. Strings oder Tupel an eine Funktion übergibt. Die Schnittstelle zwischen dieser Umgebung und der Funktion bzw. dem Funktions. Prozedurrumpf (body). aus der heraus sie aufgerufen wurde.3 Funktionen . wie man Parameter deklariert. die man als Parameter bezeichnet. Dennoch gibt es einen klar definierten Unterschied.10 Parameterübergabe Eine Funktion oder eine Prozedur benötigt üblicherweise Informationen über die Umgebung.3453. Die Syntax.78787.110 14 Funktionen Beispiel: def arithmetic_mean(*args): sum = 0 for x in args: sum += x return sum print(arithmetic_mean(45. verhält sich die Übergabe nach außen hin wie eine Wertübergabe.32)) print(arithmetic_mean(45)) print(arithmetic_mean()) Ergebnisse: 244 170009. kann man verschiedenste Objekte von „außen” innerhalb der Funktion benutzen. Parameterübergabe: Wenn man unveränderliche Argumente wie Integer.h. Im vorigen Abschnitt haben wir mehrfach die Begriffe Parameter und Argumente verwendet.

d. Diese Identität. In der ersten print-Anweisung der ref_demo()-Funktion wird das x aus dem main-Gültigkeitsbereich benutzt. Parameterübergabe: Zwei Objekte.h. Auch sie werden per Referenz an die Funktionsparameter übertragen. da es sich ja um unveränderliche Objekte handelt. also auf die Liste." id=". z.id(x)) Im obigen Beispiel haben wir die Identitätsfunktion id() benutzt. dass sich Python zuerst wie Call-by-Reference verhält. die beim Aufruf übergeben worden ist. solange es im Programmablauf existiert. Wird allerdings ein komplett neues Element dem formalen Parameter zugewiesen. Zwei verschiedene Objekte. Es wird also eine lokale Speicherposition für den formalen Parameter x angelegt. Der Parameter innerhalb der Funktion ref_demo bleibt solange eine Referenz auf das Objekt. und das x in main behält seinen ursprünglichen Wert: >>> x = 9 >>> id(x) .14. denn wir sehen. Wenn man die Funktion ref_demo() des obigen Beispiels aufruft. Zuerst wollen wir einen Blick auf die Integer-Variablen werfen. eine andere Liste. und der formale Parameter zeigt nun auf diese Speicherstelle.x. die gleichzeitig existieren. erzeugt Python eine neue Speicherstelle für das Objekt. aber sobald es einen Wert zugewiesen bekommt. ist ein Integer. aus dem die Funktion aufgerufen wurde.4 Funktionen die Identität 41902552 hat. Dies bedeutet. Wenn wir jedoch den Wert 42 dem x zuweisen. diese Änderung wirkt sich auch auf den Gültigkeitsbereich aus. das übergeben wurde. d. dass x BILD 14. der Rückgabewert der Funktion. 41903752. Innerhalb der Funktion kann der Inhalt des Objekts nicht verändert werden. id(obj) liefert die „Identität” des Objekts obj.x.h. es hat weiterhin den Wert 9." id=". dann hat dies keine Auswirkungen auf die „alte” Liste. Anders verhält es sich jedoch. Wenn wir beispielsweise eine Liste an eine Funktion übergeben. die ein Objekt als Parameter hat. so wie wir es im grünen Block weiter unten tun. das heißt eine separate Speicherstelle. die nicht-überlappende Lebensbereiche haben. Die Variable des Funktionsaufrufs wird dadurch nicht verändert. erhält x eine neue Identität. verhält es sich wie bei Call-by-Value. können wir prüfen. und das x in main bleibt unberührt. was mit x passiert: Wir können im Hauptprogramm (Gültigkeitsbereich main) sehen.10 Parameterübergabe 111 tion übertragen. müssen wir zwei Fälle unterscheiden: Die Elemente einer Liste können verändert werden. der eindeutig und konstant für dieses Objekt ist.id(x)) x=42 print("x=". wie wir im folgenden Beispiel nachvollziehen können: def ref_demo(x): print("x=".B. müssen verschiedene Identitäten haben. Sobald also ein neuer Wert an den Parameter überwiesen wird. wenn man veränderliche Argumente überträgt. wie keine Änderung am Parameter erfolgt. dürfen allerdings den gleichen Identitätswert haben. dass wir den gleichen Identitätswert für x erhalten. Allerdings können einzelne Elemente eines solchen veränderlichen Objekts im Funktionsrumpf verändert werden.

>>> def s(liste): . print(liste) .1. z. sondern eine komplette Kopie übergeben. liste += [47.. Schlimmer ist es jedoch.11] .1.. mit denen man nicht gerechnet hat. z.. wenn Listen oder Dictionaries als Parameter übergeben werden.1. Dies kann auch in Python passieren.. Im folgenden Beispiel wird die Liste fib. Auch wenn manche Programmierer bewusst Nebeneffekte zur Lösung ihrer Probleme einsetzen. liste += [47. >>> fib = [0. print(id(liste)) . Der Aufruf verändert also nicht den Wert von fib. mit der Liste [47.8] ..5. 3.2.1. und dadurch Fehler verursacht werden. die als aktueller Parameter an die Funktion s() übergeben wird.3. wenn Nebeneffekte auftreten. wenn man statt einer Liste eine Kopie der Liste als Parameter übergibt. So wird in s(fib[:]) nicht die Liste fib... >>> fib = [0.11] verkettet.5. 8.11] . 11] Man kann dies verhindern..B .B.. 5.112 14 Funktionen 9251936 >>> ref_demo(x) x= 9 id= 9251936 x= 42 id= 9252992 >>> id(x) 9251936 >>> 14. wie man im folgenden interaktiven Programmstück sehen kann: >>> def s(liste): . 47. wird dies im Allgemeinen als schlechter Stil betrachtet...2.. dann. 2.. dass die Funktion den korrekten Wert für die Argumente zurückliefert und sonst keine Effekte verursacht. 1. print(id(liste)) . Mittels der Slicing-Funktion kann man ganz leicht eine Kopie erzeugen.. 1.3.11 Nebeneffekte Von einem Funktionsaufruf erwartet man. Ändern von Speicherzuständen.8] >>> id(fib) 24746248 >>> s(fib) 24746248 24746248 >>> id(fib) 24746248 >>> fib [0.

die mit einer beliebigen Anzahl von Argumenten aufgerufen werden können. 8] 14.py python kurs fuer anfaenger 14. also sys.py) listet sämtliche mitgegebenen Argumente in der Standardausgabe auf: # Modul sys wird importiert: import sys # Iteration über sämtliche Argumente: for eachArg in sys. Das Skript (argumente. 1. Man bezeichnet diese als Kommandozeilenparameter. sondern auch einem Python-Skript kann man Argumente übergeben. die für das Verständnis der weiteren Beispiele dieses Kapitels nicht wichtig sind: Der Begriff Stelligkeit oder Arität bezeichnet in der Informatik die Para- . 47. 1. 5.argv abrufbar.argv[0]. 3.py gespeichert wurde: python argumente. Dieser steht als erster Eintrag in der Liste. werden die Argumente jeweils durch ein Leerzeichen voneinander getrennt hinter dem Skriptnamen aufgeführt. also die Kommandozeilenparameter. Im Python-Skript selber sind die Argumente. 11] fib 1. s(fib[:]) 1. Ruft man ein Python-Skript aus einer Shell auf.13 Variable Anzahl von Parametern Wir führen nun Funktionen ein. >>> [0. falls das Skript unter argumente.12 Kommandozeilenparameter 113 >>> [0. Zusätzlich zu den Kommandozeilenparametern enthält diese Liste auch den Namen des aufrufenden Skripts (Dateiname).12 Kommandozeilenparameter Nicht nur Funktionen. Diejenigen mit Programmiererfahrungen in C und C++ kennen das Konzept als varargs.argv: print(eachArg) Beispiel eines Aufrufs. als Liste unter dem Namen sys. 2. 8.14. 3.py python kurs fuer anfaenger Dieser Aufruf erzeugt folgende Ausgabe argumente. 2. 5. Es folgen einige Definitionen.

other_cities) . die von einer beliebigen Anzahl von Parametern gefolgt werden können. 'Konstanz'.. 'Do you like Python?'. in einem Tupel gesammelt werden. Ruft man die Funktion ohne jegliche Argumente auf.. Als variadische Funktion bezeichnet man in der Informatik Funktionen. die das arithmetische Mittel aus einer variablen Anzahl von Werten berechnet."Do you like Python?". 'Of course') >>> Aus dem vorigen Beispiel lernen wir... Wir schreiben eine Funktion."Freiburg". aber die Positionsparameter müssen immer zuerst kommen. also solche. um eine variable Anzahl von Parametern zu kennzeichnen. deren Parameteranzahl nicht bereits in ihrer Deklaration festgelegt ist.114 14 Funktionen meteranzahl von Funktionen. print(city. Dies ist möglich. Prozeduren oder Methoden mit unbestimmter Arität. der immer angegeben werden muss. Manchmal ist es notwendig. Prozeduren oder Methoden.. *l): """ The function calculates the arithmetic mean of a non-empty arbitrary number of numbers """ sum = x for i in l: sum += i return sum / (1. gefolgt von einer beliebigen Anzahl von weiteren Städten „other_cities”: >>> def locations(city. Lösung: def arithmetic_mean(x. 'Stuttgart'. dass die Argumente. Im folgenden Beispiel benutzen wir einen Positionsparameter „city”. Dazu wird das Sternchen unmittelbar vor einen Variablennamen gestellt. dass man eine feste Anzahl von Positionsparametern benötigt. "Of course") (34. >>> varpafu() () >>> varpafu(34.. *other_cities): . Ein Sternchen „*” wird in Python benutzt. >>> def varpafu(*x): print(x) .. Auf dieses Tupel kann als „normale” Variable im Rumpf (body) der Funktion zugegriffen werden."Stuttgart". . so ist x ein leeres Tupel. 'Frankfurt') >>> Wir wollen dies an einem sinnvolleren Beispiel veranschaulichen. die bei einem Funktionsaufruf von varpafu übergeben werden."Frankfurt") Berlin ('Freiburg'.. >>> locations("Berlin") Berlin () >>> locations("Berlin". "Konstanz".0 + len(l)) .

99) 26..7.. In der folgenden interaktiven Python-Sitzung lernen wir.99] >>> arithmetic_mean(l) Traceback (most recent call last): File "<stdin>". Die Idee besteht darin.z): . wie wir diese Funktion benutzen können. line 1.7.z) .14 * in Funktionsaufrufen 115 Man mag sich fragen.12) >>> f(*p) (47.14 * in Funktionsaufrufen Ein Stern kann auch in einem Funktionsaufruf erscheinen. was einen Fehler verursachen würde. print(x.9.0 + len(l)) TypeError: unsupported operand type(s) for /: 'list' and 'float' Die Lösung besteht in der Benutzung eines weiteren Sternchens: >>> arithmetic_mean(*l) 26. 11. wenn jemand die Funktion mit einer Liste statt mit einer variablen Zahl von Zahlen aufrufen will? Im Folgenden sehen wir. 12) .11. in arithmetic_mean return sum / (1.666666666666667 >>> arithmetic_mean(4. dass wir erzwingen wollten.7. Was ist.14.45. line 8.71666666666667 Das funktioniert gut.-3. um eine Division durch 0 zu vermeiden.py gespeichert worden ist.y. Dazu nehmen wir an.7..71666666666667 >>> 14. Ein Argument wird entpackt und nicht gepackt. >>> p = (47. wie wir in der vorigen Übung gesehen haben: Die Semantik ist in diesem Fall „invers” zu der Verwendung eines Sterns in der Funktionsdefinition.-3. In anderen Worten: Die Elemente einer Liste oder eines Tupels werden vereinzelt: >>> def f(x. warum wir sowohl einen Positionsparameter „x” und einen Parameter für eine variable Anzahl von Werten „*l” in unserer Funktionsdefinition benutzt haben. in <module> File "statistics.9) 6. dass unsere Funktion immer mit einer nichtleeren Anzahl von Argumenten aufgerufen wird. Dies ist notwendig. dass die Funktion arithmetic_mean in einer Datei mit dem Namen statistics. dass dann ein Fehler verursacht wird: >>> l = [4.45.y.py".. >>> from statistics import arithmetic_mean >>> arithmetic_mean(4.9.7. aber die Sache hat einen Haken.

'en': 'English'} >>> 14.h. wenn Listen „unbekannter” Längen verwendet werden sollen..fr="French") {'fr': 'French'.. >>> f() {} >>> f(de="Germnan".p[1]. 'yes') und nun in Kombination mit *: >>> t = (47. **d) (47. 'block'.en="English".116 14 Funktionen Es besteht wohl kaum die Notwendigkeit zu erwähnen. 'de': 'Germnan'. 'yes') >>> ..'x':'extract'.b.16 Doppeltes Sternchen im Funktionsaufruf Das folgende Beispiel veranschaulicht die Verwendung von ** in einem Funktionsaufruf: >>> def f(a.'y':'yes'} >>> f(*t...x. 'extract'.y): ..x. >>> d = {'a':'append'. 'b':'block'. „Unbekannt” bedeutet. print(args) .. ist die vorige Aufrufsart im allgemeinen Fall nicht anwendbar. 14.. während man das Skript schreibt. 11. dass dieser Aufruf weniger komfortabel ist. 12) >>> Zusätzlich.b.y) .15 Beliebige Schlüsselwortparameter Es gibt auch einen Mechanismus für eine beliebige Anzahl von Schlüsselwortparametern. d. print(a. 'extract'. wurde als Notation ein doppeltes Sternchen „**” eingeführt: >>> def f(**args): . Um dies zu ermöglichen. 11.'y':'yes'} >>> f(**d) ('append'. dass diese Art unsere Funktion aufzurufen komfortabler ist als die folgende: >>> f(p[0]. dass die Länge erst während der Laufzeit bekannt ist und nicht.p[2]) (47.11) >>> d = {'x':'extract'.

Also folgen wir der Tradition und widmen uns auch in unserem Python-Tutorial dieser Funktion.15 15. dass die Rekursion etwas mit Unendlichkeit zu tun hat... dass ich weiß. Die Gründe liegen auf der Hand: Der mathematische Hintergrund ist leicht zu verstehen. Diese Definition definiert rekursiv eine Grammatik. Die Rekursi. Vor allem. Sie ist sicher. Mathematisch wird die Fakultät wie folgt definiert: n! = n * (n-1)!. um sprachliche Ausdrücke mit Hilfe einer Metasprache formal zu definieren. Wir glauben nicht. Dieses sprachliche Spiel könnten wir beliebig fortsetzen. Der Linguist Noam Chomsky hatte einen Formalismus eingeführt. indem sie sich selbst aufruft. dass ich weiß. Das Adjektiv „rekursiv” stammt vom lateinischen Verb „recurrere”. Dies ist ein Beispiel für RekurBILD 15. und sie lässt sich besonders leicht rekursiv programmieren. was „zurücklaufen” bedeutet. dass sie sicher ist.1 Rekursion in der natürlichen sion in der natürlichen Sprache. dass er denkt. Die Fakultätsfunktion ist das Standardbeispiel für die Einführung der Rekursion in nahezu jedem Tutorial. sondern der menschlichen kognitiven Fähigkeiten. if n > 1 and f(1) = 1 . .1 Rekursive Funktionen Definition und Herkunft des Begriffs Die Rekursion hat etwas mit Unendlichkeit zu tun. Er denkt. dass er denkt. Jedem. dass ich weiß. dass die Rekursion etwas mit Unendlichkeit zu tun hat. wenn man bereits eine Programmiersprache erlernt hat. Die Beweismethode der „Vollständigen Induktion” in der Mathematik ist auch eine Art von Rekursion. Diese formalen Sprachen von Chomsky werden auch zur Definition und Spezifikation von Programmiersprachen in der Informatik benutzt. dass die Rekursion etwas mit Unendlichkeit zu tun hat. was eine rekursive Definition oder eine rekursive Funktion macht: Sie läuft gewissermaßen zurück auf sich selbst. der sich bereits ein wenig mit Mathematik oder Informatik beschäftigt hat. Unser ganzes Denken basiert auf rekursiven Denkprozessen. Ich weiß. dürfte wohl die Fakultät begegnet sein.Sprache on ist nicht nur eine fundamentale Eigenschaft der natürlichen Sprache. Das ist genau das. dass die Rekursion etwas mit Unendlichkeit zu tun hat.

die die Bedingungen der Rekursion erfüllt. dass das Python-Skript ebenso elegant wie die mathematische Funktion ist: def faculty(n): if n == 1: return 1 else: return n * faculty(n-1) Wenn wir nachvollziehen wollen. Abbruchbedingung: Eine rekursive Funktion muss terminieren. Eine rekursive Funktion terminiert. nennen wir eine rekursive Funktion. Beispiel für die Fakultät: 4! = 4 * 3! 3! = 3 * 2! 2! = 2 * 1 Ersetzt man die ausgerechneten Werte in der jeweiligen Ursprungsgleichung. indem eine Funktion sich selbst ein oder mehrmals in ihrem Funktionskörper (body) aufruft.3 rekursive Funktionen in Python Als Beispiel für eine rekursive Funktion in Python wählen wir eine rekursive Implementierung der Fakultätsfunktion in Python. dem Fall. können wir zwei print()Funktionen ergänzen: def faculty(n): . ohne dass ein rekursiver Aufruf notwendig ist. d. So liefert beispielsweise die Fakultätsfunktion für das Argument 1 den Wert 1 zurück. erhält man für 4! folgenden Ausdruck: 4! = 4 * 3 * 2 * 1 Ganz allgemein könnten wir sagen: Rekursion ist eine Methode in der Informatik. wenn das Abbruchkriterium nicht erreicht wird. in der die Lösung für ein Problem auf die Lösung kleinerer Instanzen des Problems zurückgeführt wird.2 Definition der Rekursion Die Rekursion ist eine Programmiertechnik oder ein Programmierkonzept. Eine Funktionsdefinition.h. (Anmerkung für Mathematiker: Das Abbruchkriterium in einer rekursiven Funktion entspricht der Induktionsverankerung bei der vollständigen Induktion!) Eine rekursive Funktion kann in eine Endlosschleife führen. wie die Funktion funktioniert. in dem die Funktion sich nicht mehr selbst aufruft. Man sieht.118 15 Rekursive Funktionen 15. wenn mit jedem Rekursionsschritt das Problem reduziert wird und sich in Richtung der Abbruchbedingung bewegt. damit man sie in einem Programm benutzen kann. 15.

4 Die Tücken der Rekursion In diesem Abschnitt geht es um ein spezielles Problem bei der Rekursion. " * faculty(" .n-1. BILD 15. Ruft eine Funktion sich in einem Ausdruck wiederholt auf. wie dieses exponentielle Laufzeitverhalten zustande kommt. n.2 Fibonacci-Rechtecke und goldener Schnitt . res) return res print(faculty(5)) Obiges Python-Skript liefert folgende Ausgaben: faculty has been called faculty has been called faculty has been called faculty has been called faculty has been called intermediate result for intermediate result for intermediate result for intermediate result for 120 with n = 5 with n = 4 with n = 3 with n = 2 with n = 1 2 * faculty( 3 * faculty( 4 * faculty( 5 * faculty( 1 2 3 4 ): ): ): ): 2 6 24 120 Die Fakultätsfunktion lässt sich natürlich auch iterativ schreiben: def iterative_faculty(n): result = 1 for i in range(2.4 Die Tücken der Rekursion 119 print("faculty has been called with n = " + str(n)) if n == 1: return 1 else: res = n * faculty(n-1) print("intermediate result for ". "): ". Die Fibonacci-Zahlen sind eine unendliche Zahlenfolge. Deshalb werden die Fibonacci-Zahlen auch als Fibonacci-Folge bezeichnet. Am Beispiel der Fibonacci-Zahlen demonstrieren wir. erhalten wir ein exponentielles Laufzeitverhalten. also mehr als einmal.15.n+1): result *= i return result 15.

1. besser bekannt als Fibonacci. Es sollte hoffentlich nicht zu schwer gewesen sein. das Konstruktionsprinzip dieser Folge zu erkennen. Die Fibonacci-Zahlen resultieren also aus einem „künstlichen” Kaninchenproblem.89.. Seine Folge beginnt mit F1 = 1. denn ob man bei 0 oder 1 startet. Jede Zahl.5.5 Fibonacci-Folge in Python Nun kommen wir endlich wieder zu Python und den rekursiven Funktionen zurück. In seinem Buch „Liber Abaci”.3. das die folgenden Bedingungen erfüllt: ■ Die Anfangspopulation wird von einem Kaninchenpaar gebildet.120 15 Rekursive Funktionen Im Folgenden sehen Sie die ersten Glieder der Fibonacci-Folge: 0. Dies ist aber gewissermaßen nur Geschmackssache. außer den beiden ersten. Die rekursive Python-Implementierung spiegelt ziemlich exakt die rekursive mathematische Funktion wieder: def fib(n): if n == 0: return 0 elif n == 1: return 1 else: return fib(n-1) + fib(n-2) .. Versuchen Sie doch einmal.1.8. während in modernen Mathematikbüchern und Büchern über Programmiersprachen die Folge meistens mit dem Wert für das Argument 0 startet. Ansonsten wirft jedes Kaninchenpaar jeweils ein weiteres Kaninchenpaar pro Monat. Formale Definition der Fibonacci-Zahlen: Fn = Fn-1 + Fn-2 wobei gilt: F0 = 0 und F1 = 1 Die Fibonacci-Zahlen sind nach dem Mathematiker Leonardo von Pisa. Sie sind unsterblich. führte er diese Folge als Übungsaufgabe ein. In dieser Übung geht es um Kaninchen. also F0 = 0.21. benannt. ■ ■ Die Fibonacci-Zahlen geben also die Anzahl der Paare am Ende eines bestimmten Monats an.13. das im Jahre 1202 veröffentlicht wurde. Die Fibonacci-Zahlen lassen sich sehr leicht als rekursive Python-Funktion realisieren. hat keine Auswirkungen auf die weiteren Folgeglieder. Ein neugeborenes Kaninchenpaar kann sich erst am Ende des ersten Monats paaren und wirft am Ende des zweiten Monates ein weiteres Paar. . 15. ergibt sich aus der Summe der beiden Vorgänger.2.55.34.

00 1.50 16. n= 9. und time2 ist entsprechend die Zeit für drei Aufrufe der iterativen Funktion fibi(). 0. dass sie ein deutlich unterschiedliches Laufzeitverhalten an den Tag legen. 0. 0.011 Millisekunden benötigt. percent: %10. fib(40) braucht bereits 215 Sekunden. b = 0."from fibo import fibi") time2 = t2. 0.5 Fibonacci-Folge in Python 121 Eine iterative Funktion zur Berechnung der Fibonacci Zahlen lässt sich ebenso leicht in Python bewerkstelligen.000008. fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: 0.000047. 0. also ohne exakte Zeitmessung den Eindruck. sehen wir.000006. Aber bei Werten ab n = 30 sieht es deutlich anders aus.6f.016 Millisekunden begnügt. während fibi(20) für drei Aufrufe gerade 0. n= 5.000007.000006. stellt man sehr schnell fest. n= 7.000005. fib: %8.2f" % (i.000005.000013.50 27.00 1. 0. dass fibi() und fib() genauso schnell wären. 0."from fibo import fib") for i in range(1.000006.000198. time1/time2)) time1 ist die Zeit in Sekunden. hat man rein gefühlsmäßig. b = b. 0. fib(20) ist also etwa 1300 Mal schneller als fib(20).41): s = "fib(" + str(i) + ")" t1 = Timer(s.B.000030. 0. 1 for i in range(n): a. 0.000008. a + b return a Benutzt man die beiden Funktionen fib() und fibi().000005. Bei kleinen Werten. 0. die drei Aufrufe von fib(n) benötigen.000004.000006. 0. 0. z.70 41.15.000006.timeit(3) s = "fibi(" + str(i) + ")" t2 = Timer(s. Um dieses Gefühl mit soliden Messwerten zu untermauern.81 1.timeit(3) print("n=%2d.000005.79 10. 0. percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: 0. n=10.04 5.000075. n= 2. haben wir ein Skript geschrieben. 11 oder 15. n= 6. 0. 0. 0. time2. fibi: %7.20 3. n= 1. fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: 0. wie wir im folgenden Skript sehen können: def fibi(n): a. n=12. Wenn wir uns die Ergebnisse anschauen. dass fib(20) etwa 14 Millisekunden benötigt.52 . n= 8. fib() braucht nun sekundenlang.000287. n=11.62 2.000118. n= 3.36 5.000007. 0.6f. n= 4. 0. 0. also mehr als 3. 0.000007. während fibi(4) sich mit 0. 0.000007."from fibo import fib") time1 = t1. n = 10. time1.000020. während fibi() weiterhin „sofort” mit dem Ergebnis da ist. mit dem wir die Zeiten messen können: from timeit import Timer from fibo import fib t1 = Timer("fib(10)".5 Minuten.

dass f(4) zweimal aufgerufen wird.000012.000780.036963.253764.000013. fibi: 0.861763. fibi: 0.840097.000013.000018. fibi: 0. n=22.001279. percent: 13465060. n=23. fibi: 0.000013.000016.78 81. fibi: 0.13 50. fibi: 0. percent: 112. n=27.742688. percent: 313. percent: 1764. fibi: 0.000014. f(6) zu berechnen.980462. percent: 19352.000007.000015.000014.060626. fibi: 0. fibi: 0. percent: 47908.83 19.000014. percent: 851689.44 4.003439.519086.80 0. n=36. fibi: 0.80 0. percent: 309461.339578.33 7.000015. percent: 11989.78 Was ist faul an unserer rekursiven Implementierung? Schauen wir uns den Berechnungsbaum an. percent: 123887.426206. n=32.157224.000014. n=20.000011. percent: 233. percent: 1216110.000012.59 0.h.42 0. fibi: 0. n=19.030006. fibi: 0. n=38. fibi: 0.91 0. n=30. dass alle Berechnungen immer wieder durchgeführt werden.000014.17 0.51 2.59 0.023137. n=29.086484. in der die Funktionsaufrufe erfolgen.000016.000009. fibi: 0.76 1. n=14. fibi: 0. percent: 34506. fibi: 0. die Reihenfolge. Sie müssen also immer wieder aufs Neue berechnet werden.000011.03 1. n=18. fibi: 0. n=15. fibi: 0.45 0.411353.96 0.122 15 Rekursive Funktionen n=13.014366.000008. fibi: 0.09 215.04 0. percent: 7383653.05 0.000013. percent: 203442.08 132. n=31. percent: 72334. percent: 162. n=35. Wenn man sich vorstellt. fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: 0.097643. n=21.002059.000007. erkennt man. percent: 3116064. fibi: 0. d. percent: 2053218. n=24. percent: 486. fibi: 0. n=17. fibi: 0. n=25. percent: 4985. . n=16. percent: 840. percent: 1309.55 0. percent: 2818. fibi: 0. n=37.000016. fibi: 0. fibi: 0. n=34.009219.41 0.000011.648224. n=28. fibi: 0. da bereits berechnete Werte nicht gespeichert werden. n=39.86 11. fibi: 0.822418.000480.091484.000015. percent: 7584. percent: 69. n=40. Statt fib() schreiben wir allerdings vereinfachend f(): Wir können sehen.64 30. f(3) dreimal und so weiter. fibi: 0. percent: 521769. Das bedeutet.005794.000012. percent: 5447430.000015.000013. n=26. dass der Unterbaum zur Berechnung von f(2) (also fib(3)) dreimal auftaucht und der Unterbaum zur Berechnung von f(3) zweimal. n=33.673918.89 0.83 0.

0.000008.000011."from fibo import fibi") time2 = t2. 0. n= 4. 1:1} def fibm(n): if not n in memo: memo[n] = fibm(n-1) + fibm(n-2) return memo[n] Diese Technik.000010. 0. n= 7.000003. n=13.000004. 0. 0. 0.5 Fibonacci-Folge in Python 123 Wir können eine „Erinnerung” für unsere rekursive Version implementieren.72 0.000004.59 0. 0.000020. n=10. n=20. n=21. fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: 0. 0. fib: %8. n= 9. 0.000004.6f.000004.000008. fibi: %7.000003. n= 3.52 0. n= 2. percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: 0.000012.000011. n=16.45 0.55 0.50 0. dass unsere neue Funktionsversion sogar schneller ist als die iterative. 0. 0. 0.65 0.85 0.000009.000018. 0. 0."from fibo import fib") for i in range(1. 0. n=14.45 . 0.6f.57 0. 0. 0. 0.000004. 0.61 0.timeit(3) print("n=%2d.2f" % (i.39 0. time1. 0.000011. 0.000014. n=11.000012. n= 5. 0. n=12.86 0. 0.000009.000011. 0.45 0. 0.41): s = "fibm(" + str(i) + ")" t1 = Timer(s. 0. 0. Wir schauen uns wieder die benötigten Zeiten im Vergleich zu fibi() an: from timeit import Timer from fibo import fib t1 = Timer("fib(10)". n=19. 0.000015. 0.000009. 0.000013. 0.000007. bezeichnet man als Memoisation. 0.000010.000016.000008.75 0. n=18.73 0. 0. n=17.000011.000018. Dazu nutzen wir ein Dictionary.000020.29 0. 0.000015.45 0. 0. time1/time2)) Wir können sehen. fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: 0. also das Speichern von Ergebnisse zur späteren Wiederverwendung. Vor allem die großen Argumente haben einen besonderen Vorteil von der Memoisation: n= 1.000017. 0.61 0. n= 8.000012. n= 6."from fibo import fibm") time1 = t1. time2.000012.000004. in dem wir bereits berechnete Werte speichern: memo = {0:0.000004. 0. 0.000007.50 0.000004. percent: %10.000011. n=15.000017.79 0. 0.timeit(3) s = "fibi(" + str(i) + ")" t2 = Timer(s.15.000009.

Aufgabe: Schreibe eine rekursive Version der Funktion f(n) = 3 * n.29 15. n=33. (Hinweis: Diese Funktion sieht ähnlich wie die Fakultätsfunktion aus!) Lösung: Lösungen zu Kapitel 15 (Rekursive Funktionen). n=38. 0. 0. fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: fibi: 0.000011.000004.31 0. 0. n=30.40 0. 0.000004.000004. 0.33 0.000011. die die Vielfachen von 3 berechnet.000012. 0. Aufgabe: Schreiben Sie eine Funktion.31 0. 0. 0.000012.000004. n=37. n=34.000013. 0. n=36.6 Aufgaben 1.000012.000004. 0. 0. 0.000004.35 0.34 0.000011.40 0.33 0. Seite 393 2.000012. n=40. n=31.000004. n=24. 0.000014.32 0. die das Pascalsche Dreieck implementiert: 1 1 1 1 1 1 5 4 3 2 3 1 1 1 6 4 1 10 10 5 1 Lösung: Lösungen zu Kapitel 15 (Rekursive Funktionen). n=27. 0. n=26. 0. 0. 0.35 0.000004. percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: percent: 0.29 0.29 0.000004.30 0. welche die Summe der ersten n ganzen Zahlen zurückliefert. Aufgabe: Schreibe eine rekursive Python-Funktion.000004. n=23. Seite 393 . 0.124 15 Rekursive Funktionen n=22. 0.000004.000012. also eine Funktion.000004. 0.31 0. n=32. 0.000010.000012.000014. 0. 0. Lösung: Lösungen zu Kapitel 15 (Rekursive Funktionen). n=39.34 0. 0. 0. fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: fib: 0.000013. 0.000004.000013.000004. n=25. Seite 393 3.000004.000004. 0.000010.33 0.31 0. 0.000004.000013.000014. 0. n=28.34 0. 0. n=35.000004. 0.000004. 0. n=29. 0.000013. 0. 0. 0.

d. Alle Zahlen. Erzeuge eine Liste der natürlichen Zahlen von 2 bis n: 2.h. Dies ist die nächste Primzahl. 4*i. n. 4.. Algorithmus zum Finden aller Primzahlen kleiner einer gegebenen natürlichen Zahl n: 1. Lösung: Lösungen zu Kapitel 15 (Rekursive Funktionen). Diese Menge kann man rekursiv konstruieren. dass es genügt.15.. Das Sieb des Eratosthenes ist ein einfacher Algorithmus zur Berechnung aller Primzahlen bis zu einer bestimmten natürlichen Zahl. 3. Seite 394 . die erste Primzahl. 3*i. Wenn man die fett markierten Zahlen im folgenden Pascalschen Dreieck aufsummiert. 4. und so weiter. die Vielfachen von 4 zu entfernen. also die Zahlen 2*i. d. (Als Verbesserung: Es genügt. Wenn wir uns den obigen Algorithmus genauer anschauen. Fibonacci-Zahl: 1 1 1 2 1 3 1 1 3 *1 1 4 4 1 *6 1 10 10 5 1 *5 6 15 20 15 6 1 *1 Schreibe ein rekursives Programm. die Vielfachen der Primzahlen bis zu der Quadratwurzel von n zu entfernen. Aufgabe: Die Fibonacci-Zahlen verbergen sich auch innerhalb des Pascalschen Dreiecks. Aufgabe: Schreibe eine rekursive Funktion in Python für das Sieb des Eratosthenes. sind Primzahlen. Lösung: Lösungen zu Kapitel 15 (Rekursive Funktionen). Finde die erste auf i folgende Zahl in der Liste. . falls vorhanden. Beginnend mit i+i. obwohl die bereits durch die Vielfachen von 2 entfernt worden sind. 3. Starte mit einem Zähler i mit dem Wert 2. rekursive Funktion. 2. die noch in der Liste sind. bis zur Quadratwurzel von n zu gehen) 7. Seite 394 5. inkrementiere jeweils um i und lösche alle so erhaltenen Zahlen aus der Liste. bis i größer als n ist. 6. dass wir ineffizient sind. So versuchen wir zum Beispiel.h. sehen wir. Setze i auf den im letzten Schritt gefundenen Wert. 4 und 5. die die Fibonacci-Zahlen aus einem Pascalschen Dreieck heraus berechnet. Man erkennt. 5. Dieser Algorithmus geht auf den alten griechischen Mathematiker Eratosthenes zurück. Wiederhole die Schritte 3. erhält man die 7.6 Aufgaben 125 4..

um die Position der Summe der Quadrate aus zwei aufeinander folgenden Fibonacci-Zahlen in der Folge zu finden. sieht wie folgt aus: 0 1 2 3 4 5 6 a b a + b a + 2b 2a + 3b 3a + 5b 5a + 8b Wir erkennen. dass für eine natürliche Zahl n mit n > 1 Folgendes gilt: Fib(2*n + 1) = Fib(n)**2 + Fib(n+1)**2 Lösung: Lösungen zu Kapitel 15 (Rekursive Funktionen). dass die Fibonacci-Zahlen als Faktoren von a und b erscheinen. Das n-te Element dieser Folge kann mit folgender Formel berechnet werden: F(n) = Fib(n-1)* a + Fib(n) * b Daraus folgt. Für eine Fibonacci-Zahl n gilt also: fib(find_index(n)) == n Lösung: Lösungen zu Kapitel 15 (Rekursive Funktionen). Benutze die Funktion aus der vorigen Aufgabe. -1 zurückliefert. Seite 396 . die für einen Wert n den Index aus der Fibonacci-Folge zurückliefert. also wenn n kein Element der Folge ist. Die Fibonacci-Folge die mit „a” startet. Mathematische Erklärung: Seien a und b zwei aufeinander folgende Fibonacci-Zahlen. Man sieht dies zum Beispiel bei 2 und 3. Aufgabe: Die Summe der Quadrate zweier aufeinander folgender Fibonacci-Zahlen ist ebenfalls wieder eine Fibonacci-Zahl. was Fib(7) entspricht. Aufgabe: Schreibe eine rekursive Funktion find_index(). falls n eine Fibonacci-Zahl ist. denn 2*2 + 3*3 ergibt 13. und ansonsten. Seite 395 7.126 15 Rekursive Funktionen 6.

d.1 Mond und Erde nes Funktionsparameters realisieren oder durch die Rückgabe eines Werts mit der return-Anweisung. kann man den gewünschten Effekt besser mittels ei. Das bedeutet. keinen Einfluss auf andere Variablen außerhalb der Funktion hat. auch wenn diese den gleichen Namen haben. dass jede Variable.h. Variablen werden in Python implizit deklariert. in denen man versucht ist. automatisch einen lokalen Gültigkeitsbereich hat.BILD 16. Eine Variable erhält automatisch den richtigen Datentyp. ihnen einen Wert zuweist. ist dies in Python genau anders herum. weil dadurch viele Fehler und Nebeneffekte auftreten können. Während in vielen anderen Programmiersprachen Variablen automatisch als global gelten. Wie auch in vielen anderen Fällen wird hier durch das Design von Python ein guter Programmierstil gewissermaßen erzwungen.1 Globale und lokale Variablen Einführung Python behandelt globale und lokale Variablen auf eigenwillige Art. die man innerhalb einer Funktion definiert. Um keine Missverständnisse aufkommen zu lassen: Variablen müssen nicht deklariert werden.16 16. wie dies in anderen Sprachen wie C und Java üblich ist. Und das heißt wiederum. dass was immer man mit dieser Variable innerhalb der Funktion anstellt. In den meisten Fällen. Die zugrunde liegende Idee besteht darin. eine globale Variable zu verwenden. Der Funktionsrumpf ist also der Gültigkeitsbereich einer solchen Variablen. wenn man sie nicht explizit als lokal deklariert hat. wenn man sie definiert. . dass die Benutzung von globalen Variablen generell als schlechter Programmierstil betrachtet wird.

Es wird also der String „I love Paris in the summer!” ausgegeben. wenn wir das erste Beispiel mit dem zweiten Beispiel kombinieren. wie wir weiter unten in diesem Kapitel sehen werden.128 16 Globale und lokale Variablen 16.h. wie wir im folgenden entsprechend angepassten Beispiel sehen können: def f(): print(s) s = "I love London!" . Dieser Wert kann natürlich nicht verändert werden. und dann s einen neuen Wert zuweisen? Indem wir s einen Wert zuweisen könnten. wie globale Variablen innerhalb des Funktionsrumpfs einer Funktion benutzt werden können. d. was passiert. und es kommt zu einer Fehlermeldung. den globalen Wert zu erhalten. indem ihr die Zeichenkette „I love Paris in the summer!” zugeordnet wird. Wird dies eine Auswirkung auf die globale Variable s haben? Wir testen dies im folgenden kleinen Skript: def f(): s = "I love London!" print(s) s = "I love Paris!" f() print(s) Starten wir das Skript. wenn wir also zuerst auf s mittels print zugreifen in der Hoffnung. Der Funktionsrumpf von f() besteht nur aus der „print(s)”-Anweisung. wenn wir den Wert von s innerhalb der Funktion von f() verändern.py I love London! I love Paris! Wie sieht es aber aus. Python lässt diese Mehrdeutigkeit nicht zu. Es stellt sich aber die Frage. keine Zuweisung an s innerhalb des Funktionsrumpfs von f. erhalten wir folgende Ausgabe: $ python3 global_lokal2.h.2 Globale und lokale Variablen in Funktionen Im folgenden Beispiel zeigen wir. wird der Wert der globalen Variablen s benutzt. also ohne den Wert zu ändern: def f(): print(s) s = "I love Paris in the summer!" f() Die Variable s wird definiert. Weil es keine lokale Variable s gibt. Diese Definition erfolgt vor dem Funktionsaufruf f(). Dadurch gäbe es s innerhalb des Funktionsrumpfs sowohl als globale als auch als lokale Variable. machten wir s zu einer lokalen Variable. allerdings nur „lesend”. d.

py". Wir demonstrieren dies im folgenden Beispiel: def f(): global s print(s) s = "Zur Zeit nicht. erhalten wir folgende Fehlermeldung: $ python3 global_lokal3.py Traceback (most recent call last): File "global_lokal3.16. in f print(s) UnboundLocalError: local variable 's' referenced before assignment Eine Variable kann nicht sowohl lokal als auch global innerhalb des gleichen Blocks.py". aber Berlin ist auch toll! Im folgenden Beispiel wollen wir nun noch zeigen. Da nun auf diese lokale Variable zugegriffen wird. in <module> f() File "global_lokal3.2 Globale und lokale Variablen in Funktionen 129 print(s) s = "I love Paris!" f() print(s) Rufen wir das Programm auf. sein. Man kann jedoch auf globale Variablen „schreibend” innerhalb einer Funktion zugreifen. bevor sie definiert worden ist – sie also zum Zeitpunkt der print-Anweisung noch keinen Wert erhalten hat –. Deswegen betrachtete Python s als eine lokale Variable innerhalb des Rumpfs. hier der Funktionsrumpf.py Gibt es einen Kurs in Paris? Zur Zeit nicht. erfolgt die Fehlermeldung. aber Berlin ist auch toll!" print(s) s = "Gibt es einen Kurs in Paris?" f() print(s) Als Ausgabe erhalten wir: $ python3 global_lokal4. dass man auf lokale Funktionsvariablen von außerhalb nicht zugreifen kann: def f(): s = "I am globally not known" print(s) f() print(s) . line 7. aber Berlin ist auch toll! Zur Zeit nicht. Dazu muss man sie jedoch explizit mittels des Schlüsselworts global als global deklarieren. line 2.

y Die Ergebnisse sollten mit den bisherigen Erläuterungen keine Überraschungen beinhalten: $ python3 global_lokal6. um die obigen Sachverhalte nochmals per Beispiel zu vertiefen: def foo(x.x.py I am globally not known Traceback (most recent call last): File "global_lokal5.x b = 33 b = 17 c = 100 print(a.x.15.4) print(a. erhält man folgende Ausgabe mit Fehlermeldung: $ python3 global_lokal5. y): global a a = 42 x.b.y) a.y = 1. in <module> print(s) NameError: name 's' is not defined Das folgende Beispiel zeigt eine wilde Kombination von lokalen und globalen Variablen und Funktionsparametern.4 foo(17.py".y = y. line 6.b.3.py 42 17 4 17 42 15 3 4 .x.130 16 Globale und lokale Variablen Wenn man dieses Skript startet.b.

der Musik oder die Bademode. dass heutzutage ein Großteil der Probleme auf Texten also Strings basieren. '__reduce_ex__'. '__mod__'. . '__getitem__'. '__str__'. also help(str). '__ne__'. sieht man. Damals konnten sich viele noch nicht einmal vorstellen. fast alles In den vorigen Kapitel haben wir bereits Strings kennengelernt und einiges über sie erfahren. '__lt__'. 'format'. Die ersten Computer wurden entwickelt. '__subclasshook__ '. '__mul__'.. '__class__'. sondern auch komplexe Textverarbeitung betreiben könnte.1 Alles über Strings . was im Deutschen „berechnen” bedeutet. '__ge__'. '__gt__'. 'isalnum'. ' . '__len__'. ' __le__'. Hier geht es nur um Textstrings in Python und nicht um die aus der Physik.17 17. '__getattribute__'. um numerische Probleme zu lösen. 'capitalize'. '__repr__'. Mit dir(str) erhalten wir die Namen der vorhandenen Methoden und Attribute. wie es der Titel andeutet. '__delattr__'. 'endswith'. dass man mit einem Computer nicht nur rechnen. 'index'. ' __rmul__'. '__rmod__'. '__iter__'. dass Python insbesondere für den Datentyp string mächtige Werkzeuge bereitstellt. 'encode'. '__setattr__'. '__sizeof__'. . Wenn man nur an die Suchmaschinen alleine denkt.1 Alles Strings So ist es nicht verwunderlich. aber nicht alle. 'isalpha'. 'center'. damit man mit Programmen automatisch Textdateien bearbeiten kann. 'format_map'. 'expandtabs '. Einen guten Überblick über die Klasse „str” können wir uns mit der help-Funktion verschaffen. '__init__'. . '__doc__'. ' __eq__'. Schließlich stammt das Wort Computer auch vom lateinischen „computare”. '__hash__'. '__reduce__'. Nun möchten wir Ihnen weitere Details über Strings bieten. 'count'. ' __new__'. '__contains__'. '__format__'.. ' __getnewargs__'. BILD 17. Insgesamt immerhin 74: >>> dir(str) ['__add__'. 'find'.

'isspace'." 1 aus „The Devil’s Dictionary” (Des Teufels Wörterbuch) von Ambrose Bierce . 'translate'. 'rsplit'. 'rjust'. . 'isdigit'. 'strip'. . 'lstrip'. 'islower'. wo Leerzeichen. 'startswith'. hat man eine Zerlegung in Wörter. ist es sehr häufig nötig. wir haben einen String. 'zfill'] >>> len(dir(str)) 74 >>> 17. 'partition'. ■ BILD 17. 'istitle'. 'ljust'. ' splitlines'. Wir demonstrieren die Arbeitsweise von split mit einer bissigen Definition von Ambrose Bierce1 : >>> mammon = "The god of the world's leading religion.132 17 Alles über Strings . Tabs oder ganz allgemeine nicht druckbare Zeichen stehen. maxsplit]]) splitlines([keepends]) partition(sep) rpartition(sep) ■ ■ ■ ■ 17. Eine solche Funktionalität gibt es in fast allen modernen Programmiersprachen. 'swapcase'. 'rpartition'.2 Aufspalten von Zeichenketten Nehmen wir an. ' lower'. ' rindex'.1 split Die Methode split kann ohne Parameter aufgerufen werden. maxsplit]]) rsplit([sep[. The chief temple is in the holy city of New York. 'maketrans'. 'rstrip'. der eine Zeile. 'title'. 'isupper'. 'isidentifier'. dass an manchen Wörtern noch Satzzeichen wie Kommas oder Punkte „kleben”. z. Python bietet für diesen Zweck mehrere String-Methoden.2.2 Zerlegung von Strings split([sep[. ' isprintable'. 'split'. Zerlegt man einen solchen String überall dort. ihn in kleinere Einheiten zu zerlegen. 'join'. wenn man davon absieht. in einzelne Wörter. isdecimal'. 'replace'. Um einen solchen String zu bearbeiten. einen Satz oder vielleicht ein ganzes Buch enthält. 'isnumeric'. 'rfind'. 'upper'.B.

ist eine andere Eigenschaft des Default-Verhaltens von split. 'of'. .'. 'god'. 'religion. die nur aus Leerzeichen. ' chief'. 'the'.split('. 'The'.h.Rosenheim. 'city'. chief'.') print(firstname + " " + lastname + ".Huber.Lindner. 'The'. 'leading'.Rabe.089/3434544 Anna. phone) = address.07531/70021 Ottmar. 'of'.List.Rabe. 'city'.08031/787878 Sarah. 'holy'.089/3434544 Franziska.Konstanz.Konstanz. ' York.txt".07732/2343 Oskar. Telefonnummern sind rein zufällig und nicht beabsichtigt.'] >>> Man kann erkennen. "world's". zu einer Trennstelle zusammengefasst: >>> mammon = "The god \t \t chief temple is in the >>> mammon.Konstanz. 'temple'.split() ['The'. spaltet die Zeilen an den Strichpunkten und gibt die Zeilen in der Form „Nachname Vorname. " + city + ". 'temple'. Ort. 'of'.07732/43452 Peter.Radolfzell. 'New'.py” in unserem Beispielverzeichnis. Mit diesem Parameter können wir das Standardverhalten von split ändern.'] >>> of the world's \t leading religion. 'is'.'.17. Es werden auch Teilstrings.Meyer.split() ['The'. Folgende Adressen mit Telefonnummer3 könnten aus einer Excel-Datei stammen und sollen nun in ihre einzelnen Komponenten zerlegt werden.Rabe. encoding="iso-8859-1") for address in fh: address = address. 'of'.Huber. dass split den String in einzelne Komponenten aufgespalten und dafür Leerzeichen als Trenner verwendet hat. Das folgende Python-Programm4 liest diese Datei Zeile für Zeile ein. firstname. 'New'.list.txt” gespeichert. 'in'.08031/7877-0 Anna. 'the'.Rosenheim. Was man nicht erkennen kann. ein neues Trennzeichen definieren.07531/343454 Die Daten sind in der Datei „adressen. " + phone) 2 3 4 eine Abkürzung für separator Mögliche Ähnlichkeiten mit real existierenden Personen bzw. ' Die split-Methode verfügt noch über einen optionalen Parameter „sep”2 ." "world's". 'holy'.07531/890 Anna. 'leading'. city. 'is'. d. York. 'religion.Radolfzell. Frank. Sie finden es unter dem Namen „split_addresses.2 Aufspalten von Zeichenketten 133 >>> mammon. ' 'in'.München.strip() (lastname. 'god'. 'the'.München. Telefonnummer” wieder aus: fh = open("addresses. also nicht druckbaren Zeichen bestehen. Tabs (’\n’) oder anderen sogenannten Whitespaces. \n\r The holy city of New York. 'the'.

'green. 'pink'.brown.2 Standardverhalten und „maxsplit” Man möchte gerne die Anzahl der Aufsplittung begrenzen.black. München.white" >>> for i in range(1. beginnend von links: >>> s = "red. 'green'.white'] 4 ['red'. 'blue'. 'yellow'.134 17 Alles über Strings .white'] 8 ['red'. 'blue. Dies ist eine Problemstellung.8): . 07531/343454 bernd@saturn:~/bodenseo/python/beispiele$ Nehmen wir an.". aber gleichzeitig will man die Standardeinstellung für den Trenner erhalten. Rosenheim.. 089/3434544 Huber Franziska. 07732/2343 Lindner Oskar. .black.. „maxsplit” als Schlüsselwortparameter zu benutzen. x = s.brown. 'pink. 'yellow'.white'] 6 ['red'. 2 ['red'. 'brown'.2. 07732/43452 Rabe Peter. Die Wert von „maxsplit” bestimmt. 'yellow'. die häufig auftritt und häufig falsch gelöst wird: Viele kommen zuerst auf folgende Idee..pink.yellow.yellow. 'green'. 'yellow. 'black'. Radolfzell. 'brown'. 'black. 'green'. 'green'. aber die Fehlermeldung weist einen darauf hin. 'brown.white'] 3 ['red'. 089/3434544 List Anna. 'pink'. die sich aber sofort als falsch erweist. 'green'.split(maxsplit=2) Traceback (most recent call last): File "<stdin>". Radolfzell. Dann ist die Aufspaltung zwischen Ort und Telefonnummer unnötig.pink.blue. line 1. 07531/70021 Huber Ottmar.i) . in <module> TypeError: split() takes no keyword arguments >>> .brown.py Meyer Frank.pink.. 'white'] >>> 17. print(len(x). 'blue'. Für diesen Zweck stellt die Methode split den optionalen Parameter „maxsplit” zur Verfügung.split("... 08031/7877-0 Rabe Anna. 'pink'. Man versucht. 'green'.black. Rosenheim.yellow. .brown. 08031/787878 Rabe Sarah. 'blue'.brown. dass split keine Schlüsselwortparameter kennt: >>> s = "red\tgreen blue\nyellow \t pink brown" >>> s. Konstanz. Konstanz. wie oft ein String aufgespaltet werden soll. 'blue'. dass wir lediglich den Vornamen und den Nachnamen aus den Zeilen der obigen Datei benötigen.white'] 5 ['red'. Das Programm liefert folgende Ausgabe: bernd@saturn:~/bodenseo/python/beispiele$ python3 split_addresses.black.green.blue.black. Konstanz. 07531/890 List Anna. x) . 'yellow'.white'] 7 ['red'.black. 'blue'.pink. München.

'\t pink brown'] >>> Man sieht. Will man einen Parameter nicht angeben und möchte haben. Tab-Zeichen oder ein Newline-Zeichen. 'green blue yellow pink brown'] >>> s = "red\tgreen blue\nyellow \t pink brown" >>> s.2) ['red'. 'blue\nyellow'. dass der Default-Wert genommen wird.2 Aufspalten von Zeichenketten 135 Den Eingabe für den Parameter einfach leer zu lassen und zu hoffen.2) ['red'.h. also auch nicht in anderen Methoden und Funktionen: >>> s = "red\tgreen blue\nyellow \t pink brown" >>> s.split(None. 'blue yellow pink brown'] >>> s = "red green blue yellow pink brown" >>> s. 'blue yellow pink brown'] >>> s = "red green blue yellow pink brown" >>> s. Dies ist übrigens nie möglich.split(. 'green'. d. dann gibt man an der entsprechenden Position einfach den speziellen Wert „None” ein. Damit können wir alle obigen Beispiele korrekt aufspalten: >>> s = "red green blue yellow pink brown" >>> s. Nun kommen wir endlich zu der korrekten Lösung.split(" ". funktioniert auch nicht. dass es nur im ersten Fall funktioniert hatte.2) ^ SyntaxError: invalid syntax >>> Die nächste „Lösung” funktioniert zwar syntaktisch.17. dass Python dann automatisch den Default-Wert einsetzt. ''. 'blue yellow pink brown'] >>> s = "red\tgreen blue\nyellow \t pink brown" >>> s. 'green'. Gibt es mehrere Leerzeichen.split(" ". 'green'.2) File "<stdin>". 'green'.split(None. löst aber unser Problem nur teilweise. 'blue\nyellow \t pink brown'] >>> .split(. line 1 s. funktioniert es nicht mehr. wenn alle Wörter nur durch genau ein Leerzeichen getrennt sind. Man setzt an die erste Stelle für den Separator ein Leerzeichen ein: >>> s = "red green blue yellow pink brown" >>> s.split(" ".split(None.2) ['red\tgreen'.2) ['red'.2) ['red'.2) ['red'.

'white'] >>> Ganz anders sieht es aus. 'black'. wenn man nur wenige Elemente eines Strings von links oder rechts braucht.". 'green'. x) .pink'..green. 'black'.yellow. 'green'. 'brown'. 'brown'.brown.3 rsplit rsplit ohne den Parameter „maxsplit” zu betrachten. 'yellow'.blue. 'white'] 6 ['red.") ['red'. 'brown'.append([0]) return res def splitter_maxsplit(): fh = open("ulysses.blue. 'pink'. print(len(x). In der Funktion .green.blue.green.txt") res = [] . wenn wir mit „maxsplit” arbeiten. . 'green'. 'blue'.") ['red'.blue. 'yellow'.black'.. 'yellow'.splitter_total” splitten wir jeweils die komplette Zeile. 'blue'.blue'.rsplit(". 'black'. 'blue'.split(".split() if len(x): res.pink. 'white'] 8 ['red'.2. sind die Ergebnisse von split und rsplit nicht unterscheidbar.blue.i) .. 'pink'. 'white'] 7 ['red. 'black'. 'pink'.. 'yellow'.pink. 'blue'.black.green. x = s. 'black'.rsplit(". 'yellow'.green'. 'white'] 4 ['red... Zur Demonstration des Unterschieds wiederholen wir das vorletzte Beispiel mit rsplit: >>> s. 'white'] >>> Es bringt einen großen Zeitvorteil. 'pink'. 'white'] 3 ['red. 'white'] >>> s. während wir in der Funktion „splitter_maxsplit” nur das erste Wort abspalten: import time def splitter_total(): fh = open("ulysses. Gibt man für maxsplit keinen Parameter an..pink.white" >>> for i in range(1.green.") ['red'. 'black'. 'white'] >>> >>> s = "red.yellow'. 'brown'.8): .brown. 'yellow'.green.rsplit(". . 'pink'. macht wenig Sinn. Im folgenden Programm sammeln wir jeweils das erste Wort von jeder Zeile des Romans Ulysses.brown'. 'pink'.136 17 Alles über Strings .yellow. 'pink'. 'brown'. 'green'. 'black'. 'black'. rsplit spaltet einen String von rechts beginnend auf.yellow.yellow. 'brown'. 'brown'. wenn man konsequent „maxsize” benutzt. 'brown'. 'white'] 5 ['red. 17. 'blue'. 2 ['red.txt") res = [] for line in fh: x = line. >>> s. 'black'.

5 schneller ist: bernd@saturn:~/bodenseo/python/beispiele$ python3 splitter_test.4926355824258624 0.2 Aufspalten von Zeichenketten 137 for line in fh: x = line. 'blue'. 'brown'] >>> Wir sehen.4 Folge von Trennzeichen Wir hatten gezeigt. 1) if len(x): res. ''.split(None. wenn man den Trenner explizit als Parameter angibt? >>> s = "red green blue yellow pink brown" >>> s.t2 print(t1. ''.") ['red'.time() .04128098487854004 1.py 0.476098006071276 0. dass das Zusammenfassen mehrerer Trenner zu einem Trenner nur beim Standardtrenner von split funktioniert.. dass mehrere Leerzeichen. 'blue'. ''. 'pink'. t1/t2) Starten wir das Programm.brown" >>> s. ''.03992414474487305 1. ''. t2.blue.039869070053100586 1. 'green'.split(" ") ['red'. 'brown'] >>> s.append([0]) return res for i in range(5): t1 = time.pink.05954909324645996 0.split() ['red'. 'blue'.06016898155212402 0.time() splitter_maxsplit() t2 = time.03962898254394531 1.time() splitter_total() t1 = time. ''. 'brown'] >>> s = "red. 'pink'. 'pink'.06169414520263672 0. Tabs und so weiter beim Standardverhalten von split und rsplit als ein einziger Trenner aufgefasst werden.2. 'yellow'. .4944930549539404 0. Wie sieht es aber aus.yellow. erkennen wir aus der Ausgabe. ''.green.04076218605041504 1. 'yellow'.5409724461643197 0.06152200698852539 0.split("..time() .502665206718968 bernd@saturn:~/bodenseo/python/beispiele$ 17. 'green'. dass die Version mit „maxsplit” ziemlich stabil in jedem Lauf um etwa den Faktor 1.17.059509992599487305 0. 'green'. 'yellow'.t1 t2 = time..

erhalten wir jeweils Listen der Länge 4. ''. 'Radolfzell'.Konstanz.Rabe. so heißt dies.py” können wir dieses Verhalten überprüfen: fh = open("addresses2. So wie beispielsweise in den folgenden Adresszeilen. Mit dem Programm „split_addresses_4.csv. encoding="iso-8859-1") for address in fh: address = address.Meyer. '07531/343454'] bernd@saturn:~/bodenseo/python/beispiele$ 17.5 splitlines splitlines ist eine String-Methode. '07531/70021'] ['Ottmar'. „\r” beim Mac und „\r\n” unter Windows. erhalten wir die erwartete Ausgabe: bernd@saturn:~/bodenseo/python/beispiele$ python3 split_addresses_4. '089/3434544'] ['Franziska'. Fehlende Einträge sind mit leerem String markiert. 'Rabe'. Die Dateinamenserweiterung lautet überlicherweise . Befinden sich zwischen zwei Trennern keine Zeichen. 'Konstanz'.08031/7877-0 Anna.138 17 Alles über Strings .089/3434544 Franziska.Konstanz.strip() elements = address. Es handelt sich um ein Datenaustauschformat. 'Rabe'. 'München'.. 'München'. . in dem häufig Kommas zur Trennung von Datenfeldern (Spalten) in einer Zeile verwendet werden. Anna. . In der zweiten Zeile fehlt der Vorname.Rosenheim.08031/787878 Sarah. 'Konstanz'.split('. .07531/343454 Wenden wir split(".List. '08031/7877-0'] ['Anna'. 'list'. 'Rabe'. 'Konstanz'.List. 'Huber'. '08031/787878'] ['Sarah'.Rosenheim. in der vierten Zeile fehlt der Ort und in der fünften Zeile die Telefonnummer: Frank.txt".Radolfzell. Dieses Verhalten ist sinnvoll.Huber. also „\n” unter Unix.07732/2343 Oskar.07732/43452 . 'Lindner'.py ['Frank'.') print(elements) Starten wir dieses Skript. 'List'.Huber.Rabe.München. '089/3434544'] ['Anna'. 'Rosenheim'. Zeilenenden können auch von unterschied5 Der Name des Dateiformats CSV steht für Comma-separated values.München. dass dieses Datenfeld leer ist. '07732/2343'] ['Oskar'. 'Huber'.07531/70021 Ottmar.2.Lindner. die einen Text mit Zeilenbegrenzern. wenn man beispielsweise an Dateien im CSV-Format5 denkt.089/3434544 Anna.") darauf an. ''] ['Anna'. 'Rosenheim'.Konstanz. 'Meyer'. Statt Kommas können natürlich auch andere Zeichen wie beispielsweise ein Strichpunkt zur Trennung benutzt werden. '07732/43452'] [''.Rabe.

und als Max-Zeilenende erkannt.splitlines(True) ['line1\n'. '. Im folgenden Beispiel wird „\r\n” korrekterweise als Windows-Zzeilenende erkannt. ' hungert nicht!') 17. ' die jagt. 'line2\n'. '.join(x) 'Python-Perl-Java' >>> x = "48772" >>> ". hungert nicht!') >>> spruch.join(iterable) Zurückgeliefert wird die Konkatenation der Elemente des iterierbaren Objekts „iterable”.3 Zusammenfügen von Stringlisten mit join 139 lichen Betriebssystemen in einem String gemischt sein.partition(".6 partition Mit der Methode „partition” wird ein String an der ersten Stelle von links nach rechts aufgespaltet."."Perl". die jagt.7. die jagt'.17.splitlines() ['line1'. auf den die Methode „join” angewendet wird.'.'.8.7. '\r'. die als leerer String in die Ergebnisliste eingeht: >>> s = "line1\nline2\n\rline3\r\nline4\rline5\n" >>> s. d. und „\n\r” hinter line2 werden als Unix.join(x) '4. „s” ist dabei das String-Objekt. 'line4\r'.") ('Eine Katze'."Java"] >>> "-". dass zwischen den Elementen jeweils der String „s” eingefügt wird. Das Ergebnis ist ein Tupel. 'line5\n'] 17. 'line3\r\n'.rpartition(". nach line2 kommt also eine Leerzeile. und splitlines erkennt sie als Zeilenende. ''. dessen erste Komponente der Teilstring vor dem sep ist. an der der Trennstring „sep” steht.3 join join ist eine String-Methode. 'line4'.") ('Eine Katze. 'line2'. Beispiele: >>> x = ["Python". 'line5'] >>> s. 'line3'. hungert nicht!" >>> spruch.2.2' . Die Elemente von „iterable” werden dabei so zusammengefügt. Allgemeine Syntax: s.h. die zweite Komponente der String sep ist und die dritte Komponente der nach dem Vorkommen von sep stehende Teilstring: >>> spruch = "Eine Katze.

2) 3 . wo der Unterstring vorkommt. >>> rhyme = 'Little Jack Horner sat in a corner. end]]) Mit der Stringmethode „find” kann man prüfen.\nHe put in his thumb and pulled out a plum.4.find(substring[. .140 17 Alles über Strings . Wird nur ein Wert für „start” angegeben. .4 Suchen von Teilstrings Für die Suche von Teilstrings gibt es verschiedene Möglichkeiten in Python: 17.find("x") 3 >>> s. Der Name „Jill” kommt nicht in unserem String vor. wenn man nicht daran interessiert zu wissen. ab der „substring” in „s” beginnt: >>> rhyme = 'Little Jack Horner sat in a corner.\nHe put in his thumb and pulled out a plum. wird in dem Teilstring s[start:] gesucht.\nEating a Christmas pie .2 s. Wir verdeutlichen dies in folgendem Beispiel: >>> s = "annxbny" >>> s.4. „find” liefert eine -1 zurück.\nAnd said. "What a good boy am I!" ' >>> "corner" in rhyme True >>> "corner" not in rhyme False >>> 17. "What a good boy am I!" ' >>> pos = rhyme. um die reine Existenz eines Substrings zu testen. Mit den optionalen Parametern „start” und „end” kann man die Suche innerhalb des String „s” einschränken. dann wird in dem Teilstring s[start:end] gesucht.find("orner") >>> pos 13 >>> pos = rhyme. deshalb liefert „find” ein -1 zurück. start[.find("Jill") >>> pos -1 >>> Gefunden wird das „orner” in dem Wort „Horner”. Wird sowohl ein Wert für „start” und „end” angegeben.1 „in” oder „not in” „in” ist ideal.\nEating a Christmas pie . wenn „substring” nicht vorkommt. ob ein String „substring” in einem String „s” vorkommt.\nAnd said. ansonsten liefert sie die Position zurück.find("x". 17.

index("Jill") Traceback (most recent call last): File "<stdin>".rindex(substring[. außer wenn „substring” nicht in „s” vorkommt. end]]) Funktioniert genau wie „find”. 17.rfind("orner") >>> pos 29 >>> Gefunden wird das „orner” in dem Wort „corner”.2.5 s. Der Name „Jill” kommt nicht in unserem String vor.4.\nEating a Christmas pie . "What a good boy am I!" ' .index("orner") >>> pos 13 >>> rhyme.\nEating a Christmas pie . "What a good boy am I!" ' >>> pos = rhyme. start[.\nHe put in his thumb and pulled out a plum.4.\nAnd said. "What a good boy am I!" ' >>> pos = rhyme.\nAnd said. deshalb liefert „find” ein -1 zurück.\nHe put in his thumb and pulled out a plum. start[.17.4 Suchen von Teilstrings 141 >>> s. allerdings erfolgt die Suche von rechts. also vom Ende des Strings: >>> rhyme = 'Little Jack Horner sat in a corner. >>> rhyme = 'Little Jack Horner sat in a corner.4 s.3) -1 >>> 17.index("orner") == rhyme. in <module> ValueError: substring not found >>> 17.4.index(substring[.find("x".\nAnd said. In diesem Fall wird ein Ausnahmefehler generiert: >>> rhyme = 'Little Jack Horner sat in a corner. start[.\nHe put in his thumb and pulled out a plum. line 1.3 s.\nEating a Christmas pie .rfind(substring[.find("orner") True >>> rhyme. end]]) Die Stringmethode „rfind” funktioniert analog zu „find”. end]]) Funktioniert analog zu „index” und „rfind”.

6 s. in <module> ValueError: substring not found >>> 17. new[.count("Horner") 1 >>> rhyme.rindex("orner") 29 >>> rhyme.\nEating a Christmas pie .count("Jill") 0 >>> rhyme.count("orner") 2 >>> rhyme.replace("e". Man benutzt einen alten Brief und tauscht nur Name und Adresse des Empfängers aus. muss. Aber zurück zu Python und zum Programmieren: Zum Ersetzen eines Teilstrings „old” in einem String „s” durch einen anderen Teilstring „new” gibt es die Methode replace: s. >>> rhyme. dass man eine Zeichenkette durch eine andere ersetzen will bzw. . besteht darin. start[."a") 'Drai Chinasan mit dam Kontrabass' . Beispiel: >>> ch = "Drei Chinesen mit dem Kontrabass" >>> ch.rindex("Jill") Traceback (most recent call last): File "<stdin>".count("in") 3 >>> 17.replace(old. count]) Ohne Angabe des optionalen Parameters „count” werden alle Vorkommen von old durch new ersetzt.count(substring[. wieviele Vorkommen von old durch new ersetzt werden sollen. end]]) Zählt die Vorkommen eines Teilstrings „substring” in s. wenn man mit Texten arbeitet. .142 17 Alles über Strings .\nHe put in his thumb and pulled out a plum.\nAnd said. Dies gilt auch für Bereiche.4. die nichts mit dem Programmieren zu tun haben: So beispielsweise beim Erstellen von Briefen oder Rechnungen. „start” und „end” verhalten sich genau wie bei „find” und „index”: >>> rhyme = 'Little Jack Horner sat in a corner. line 1. Mit dem optionalen Parameter „count” kann man steuern.5 Suchen und Ersetzen Eine häufige Aufgabe. "What a good boy am I!" ' >>> rhyme.

"a").capitalize() 'Drei chinesen mit dem kontrabass' >>> ."a").17. Der Anfangsbuchstabe wird in einen Großbuchstaben gewandelt.replace("e". „title” wandelt alle Buchstaben.replace("i".replace("o". >>> ch = "Drei Chinesen mit dem Kontrabass" >>> ch.title() 'Drei Chinesen Mit Dem Kontrabass' >>> ch = "Drei Chinesen mit dem kONTRABASS" >>> ch. die nicht Anfangsbuchstaben eines Wortes sind in Kleinbuchstaben und alle Anfangsbuchstaben eines Wortes in einen Großbuchstaben um. Ebenso kann man einen String mit Hilfe der Stringmethode „lower” komplett in Kleinbuchstaben wandeln: >>> ch = "Drei Chinesen mit dem Kontrabass" >>> ch.upper() 'DREI CHINESEN MIT DEM KONTRABASS' >>> 17."a"). falls es sich um einen Kleinbuchstaben handelt.title() 'Drei Chinesen Mit Dem Kontrabass' >>> ch. die alle Buchstaben außer dem Anfangsbuchstaben eines Strings in Kleinbuchstaben wandelt.capitalize() 'Drei chinesen mit dem kontrabass' >>> ch."a") 'Draa Chanasan mat dam Kontrabass' >>> ch.6 Kleinbuchstaben und Großbuchstaben Man kann einen String mit Hilfe der Stringmethode „upper” komplett in Großbuchstaben wandeln."a") 'Draa Chanasan mat dam Kantrabass' >>> 17.lower() 'drei chinesen mit dem kontrabass' >>> ch.replace("i".7 capitalize und title „capitalize” ist eine Funktion.6 Nur noch Kleinbuchstaben oder Großbuchstaben 143 >>> ch.replace("e".

center(laenge[. links auf die Länge laenge gebracht. fillchar]) Der String str wird mit fillchar bzw Leerzeichen. dass unerwünschte Zeichen am Anfang oder am Ende eines Strings stehen.center(15) ■ ■ ■ .strip() 'Morgen kommt der Weihnachtsmann' >>> s.lstrip() 'Morgen kommt der Weihnachtsmann \t\n' >>> s. wie Zeilenende. Um diese Zeichen loszuwerden. str.strip([chars]) unerwünschte Zeichen werden auf beiden Seiten des Strings entfernt s. gibt es die Stringmethoden „strip”.rstrip() ' \t \n \rMorgen kommt der Weihnachtsmann' >>> >>> s = "69023 Frankfurt" >>> s. gleichermaßen von links und rechts auf die Länge laenge gebracht. Allgemeine Syntax: ■ s. fillchar]) analog zu ljust von rechts. „lstrip” und „rstrip”. >>> s = "Hallo" >>> s.rstrip([chars]) unerwünschte Zeichen werden nur auf der rechten Seite des Strings entfernt ■ ■ Beispiele: >>> s = " \t \n \rMorgen kommt der Weihnachtsmann \t\n" >>> s.ljust(laenge[. 17.9 ■ Strings ausrichten str. Meistens sind es „Whitespaces“.lstrip([chars]) unerwünschte Zeichen werden nur auf der linken Seite des Strings entfernt s.. fillchar]) Der String str wird mit fillchar bzw Leerzeichen. Der String wird rechts ausgerichtet und von links mit Nullen gefüllt. . die auf der rechten Seite eines String stehen.rjust(laenge[. falls kein fillchar gegeben ist. str. Tabs usw.144 17 Alles über Strings . .8 Stripping Strings Häufig kommt es vor. str.zfill(laenge) Spezialfall für numerische Werte. falls kein fillchar gegeben ist.strip("0123456789 ") 'Frankfurt' >>> 17.

"Hallo".... mp3 : False Hallo : False hello : False .isalnum())) .isalnum() True. "Hallo". print("%6s : %s" % (word. word. wenn alle Zeichen in s Buchstaben sind. mp3 : False Hallo : True hello : True 343 : False 767. "767. "hello".43 : False >>> ■ s. "hello". "767.99' >>> 17..10 ■ String-Tests s.isdigit())) . >>> for word in ("mp3". "Hallo"..43 : False >>> ■ s. mp3 : True Hallo : True hello : True 343 : True 767. print("%6s : %s" % (word. "767.. >>> for word in ("mp3".ljust(15) 'Hallo ' >>> s..isalpha() True.10 String-Tests 145 ' Hallo ' >>> s. "343".17.zfill(10) '0000123. word. >>> for word in ("mp3".. "343". print("%6s : %s" % (word.rjust(15) ' Hallo' >>> >>> z = "123. wenn alle Zeichen in s Buchstaben oder Ziffern sind.43"): .. "343". word.43"): ..isdigit() True. "hello".isalpha())) .43"): ... wenn alle Zeichen in s Ziffern sind.99" >>> z.

" MP3"): .. "hello". >>> for word in ("mp3".isspace() True.. print("%6s : %s" % (word..islower() True. "Hallo". . "767. "hello". "hello". print("%6s : %s" % (word. >>> for word in ("mp3". wenn alle Buchstaben in s Kleinbuchstaben sind.isupper())) .43". wenn alle Wörter in s groß geschrieben sind. mp3 : False Hallo : False hello : False 343 : False 767.. wenn alle Zeichen in s Whitespaces sind. "767. "343".. .islower())) .43 : False HALLO : True MP3 : True >>> ■ s. >>> for word in ("mp3". print("%6s : %s" % (word. . "Hallo". mp3 : False Hallo : False hello : False 343 : False 767. wenn alle Buchstaben in s Großbuchstaben sind..146 17 Alles über Strings ... mp3 : True Hallo : False hello : True 343 : False 767.43 : False >>> ■ s.isupper() True.43 : False : True : True >>> ■ s.43 : False >>> ■ s. " "): .istitle() True. "767.isspace())) . "343". "Hallo"..43"): ..43". word.. word. "343". "HALLO". word.. " \t\n". 343 : True 767.

Rabe. "767.08031/7877-0 Anna.07531/70021 Ottmar.Huber.Rosenheim.München. Seite 397 2. "343". mp3 : False Hallo : True hello : False 343 : False 767.Rosenheim.List.txt”: Frank. Aufgabe: Aufgaben Folgende Adressendatei (siehe addresses_mixed.Rabe.Konstanz.17.txt) ist gegeben: Frank. " MP3"): .07531/343454 .List.Meyer.089/3434544 Anna.07531/890 Anna.Rosenheim.43".Konstanz.Radolfzell. ).Rosenheim.Huber.Konstanz. "Hallo".Radolfzell.07531/70021 Ottmar.08031/787878 Sarah.07732/2343 Oskar.Huber.Radolfzell.07732/43452 Peter.. Aufgabe: Für die folgende Aufgabe benutzen wir wieder die Daten der Datei „adressen. Ort.07531/343454 Schreiben Sie ein Python-Programm..istitle())) .München.08031/787878 Sarah.11 Aufgaben 147 >>> for word in ("mp3".089/3434544 Franziska.Meyer.Konstanz. "HALLO".. print("%6s : %s" % (word.München.List.Rabe.089/3434544 Anna.Lindner. word.089/3434544 Franziska.München.07732/43452 Peter. Telefonnummer” ausgibt.Lindner.08031/7877-0 Anna.Rabe. "hello".Konstanz.Rabe. .Konstanz..Rabe. das diese Adressen zeilenweise in der Form „Vorname Nachname.List.Radolfzell.07732/2343 Oskar.Huber. Lösung: Lösungen zu Kapitel 17 (Alles über Strings .43 : False HALLO : False MP3 : False >>> 17. .07531/890 Anna.11 1.

soll der unveränderte Original-String zurückgegeben werden. Lösung: Lösungen zu Kapitel 17 (Alles über Strings . Schreiben Sie ein Python-Programm. Seite 398 5. Seite 398 4. bzw. "xyz". die jeweils aus dem ersten und letzten Element einer Adresse. . . bestehen: [('Frank'. Die Funktion soll als Ergebnis den veränderten String zurückliefern. . ). soll -1 zurückgeliefert werden. Lösung: Lösungen zu Kapitel 17 (Alles über Strings . Seite 399 . dass jede Zeile nur von einem \n beendet wird.\n Bringen Sie diesen String mittels Python in eine Linux/Unix-Form. die die Position des n-ten Vorkommens eines Strings „sub” in einem anderen String ausgibt. '08031/7877-0'). Aufgabe: Schreiben Sie eine Funktion. Aufgabe: Schreiben Sie eine Funktion. Linux kommen: Hat der alte Hexenmeister\nSich doch einmal wegbegeben!\r\nUnd nun sollen seine Geister\r Auch nach meinem Willen leben. ). '07531/343454')] Lösung: Lösungen zu Kapitel 17 (Alles über Strings . Falls „sub” nicht vorkommt. '07531/890'). Aufgabe: Der folgende String enthält Zeilenenden. ('Anna'. ('Franziska'. 1) findnth("abc xyz abc xyz abc xyz". '07531/70021'). . '089/3434544'). "xyz". . falls replacement nicht im String vorkommt. ('Anna'. . ). ('Peter'. das aus dieser Adressendatei eine Liste mit Zweiertupels erstellt. '07732/43452').h. '07732/2343'). ('Anna'. . die sowohl vom Mac als auch von Windows und Unix bzw. '08031/787878').148 17 Alles über Strings . '089/3434544'). . ('Sarah'. ('Oskar'. . Seite 397 3. die das n-te Vorkommen eines Strings „sub” durch einen String „replacement” ersetzt. ). >>> >>> 4 >>> 12 >>> 20 >>> from findnth import findnth findnth("abc xyz abc xyz abc xyz". ('Ottmar'. also dem Vornamen und der Telefonnummer. 2) findnth("abc xyz abc xyz abc xyz". 3) Lösung: Lösungen zu Kapitel 17 (Alles über Strings . d. "xyz". .

■ ■ . Damit ist es möglich. e) print "Error. Traditionelle Fehlerbehandlung bzw.18 if y != 9: z = x / y Ausnahmebehandlung Fehler werden häufig in anderen Sprachen mit Fehlerrückgabewerten oder globalen Statusvariablen behandelt. Tritt eine Ausnahme während der Ausführung der try-Klausel auf. mit Fehlern umzugehen. Keine Zahl!" Funktionsweise: ■ Ausführung der try-Klausel (Anweisungen zwischen den Schlüsselworten try und except) Die except-Klausel wird übersprungen. so wie im folgenden Codefragment. die solange wartet. bis eine Zahl eingegeben wurde: while True: try: zahl = raw_input("Zahl eingeben: ") zahl = int(zahl) break except ValueError as e: print("error message: ". BILD 18. wird der Rest der Klausel übersprungen. wenn keine Ausnahme auftritt. Fehlervermeidung wird meistens in bedingten Anweisungen behandelt. Das folgende Skript implementiert unter Verwendung einer Ausnahmebehandlung eine robuste Eingabeaufforderung. wann immer eine Fehlerbedingung entstehen könnte. Syntaxfehler zur Laufzeit abzufangen und zu behandeln. Die Ausnahmebehandlung (Exception Handling) ist ein Mittel. in dem eine Division durch 0 verhindert werden soll: Eleganter geht es mit den in Python vorhandenen Ausnahmebehandlungen. wird die except-Klausel ausgeführt. Stimmt der Typ der Ausnahme mit dem Schlüsselwort von except überein.1 Ausnahmebehandlung Sie sind Thread-sicher und können leicht bis in die höchste Programmebene weitergegeben oder an einer beliebigen anderen Ebene der Funktionsaufruffolge behandelt werden. Der Python-Ansatz legt den Einsatz von Ausnahmen nahe.

8. print(x.9 0.11764705882352941 1. 1.5 0.5263157894736842 0 hat kein inverses Element 4. Dort befindet sich Code. wird sie nach außen an weitere try-Anweisungen weitergereicht. 1. Ein Beispiel zum Abfangen von Divisionen durch die Zahl 0: >>> zahlen = [3.5 0..9. Im Folgenden verlangen wir solange die Eingabe eines Dateinamens. der ausgeführt wird..close() break Starten wir obiges Programm.7832 0..5] >>> for x in zahlen: . 0. " lässt sich nicht öffnen") else: print(filename.readlines()).5. die nach allen except-Klauseln stehen muss. print(str(x) + " hat kein inverses Element") .1 Die optionale else-Klausel Die try . ' hat '.txt ulysses. die nicht mit der Ausnahme in der except-Klausel übereinstimmt. Deshalb dürfen wir dann auch auf das Datei-Handle f zugreifen: while True: filename = input("Dateiname: ") try: f = open(filename. bis sich dieser zum Lesen öffnen lässt.. wenn die try-Klausel keine Ausnahme auslöst.txt lässt sich nicht öffnen Dateiname: ulysses... 4. ' Zeilen ') f. except-Anweisung hat eine optionale else-Klausel..150 18 Ausnahmebehandlung ■ Tritt eine Ausnahme auf...py Dateiname: ulisses. Wenn keine Behandlung erfolgt. erhalten wir folgende Ausgaben: bernd@saturn:~/bodenseo/python/beispiele$ python3 try_else.. so ist es eine unbehandelte Ausnahme. 'r') except IOError: print(filename.. Der else-Teil der try-Anweisung wird nur ausgeführt. except ZeroDivisionError: .0/x) . len(f.7832.txt hat 33025 Zeilen bernd@saturn:~/bodenseo/python/beispiele$ . try: .txt ulisses..2222222222222222 >>> 18. 3. wenn es keinen Ausnahmefehler gegeben hat.2643264960879679 8.

18. value.exc_info 151 18.2 Fehlerinformationen über sys.txt') s = f. strerror) = err.strip()) except IOError as err: (errno. py Unexpected error: Type: <class 'ValueError'> Value: invalid literal for int() with base 10: 'Hallo' traceback: <traceback object at 0xb728834c> Traceback (most recent call last): File "exception_sys_exc_info.exc_info Die genauen Fehlerinformationen kann man sich mit der Methode exc_info des sysModuls anzeigen lassen: import sys try: i = int("Hallo") except: (type.3 Abfangen mehrerer Exceptions Es können auch mehrere Exceptions nach einer try-Anweisung abgefangen werden.2 Fehlerinformationen über sys. traceback) = sys. type) print("Value: ". in <module> i = int("Hallo") ValueError: invalid literal for int() with base 10: 'Hallo' bernd@saturn:~/bodenseo/python/beispiele$ 18.exc_info() print("Unexpected error:") print("Type: ".args .readline() i = int(s. wie wir im folgenden Beispiel zeigen: import sys try: f = open('integers. traceback) raise Die Ausgabe des obigen Programms: bernd@saturn:~/bodenseo/python/beispiele$ python3 exception_sys_exc_info.py". line 4. value) print("traceback: ".

sys. mein Fehler!") Traceback (most recent call last): File "<stdin>". ValueError): print("An I/O error or a ValueError occurred") except: print("An unexpected error occurred") raise 18.strip()) except (IOError.txt') s = f. die verschiedenen Fehlerarten werden dann in einem Tupel gelistet.6 Finalisierungsaktion Bisher haben wir die try-Anweisungen immer nur im Zusammenspiel mit except-Klauseln benutzt.152 18 Ausnahmebehandlung print("I/O error({0}): {1}".5 Exceptions generieren Man kann auch selbst Exceptions generieren: >>> raise SyntaxError("Sorry. .readline() i = int(s. wie wir im folgenden Beispiel sehen: try: f = open('integers.") except: print("Unexpected error:".format(errno.exc_info()[0]) raise 18.4 except mit mehrfachen Ausnahmen Eine einzelne except-Anweisung kann auch gleichzeitig mehrere Fehler abfangen. Aber es gibt noch eine andere Möglichkeit für try-Anweisungen. line 1. mein Fehler! >>> 18. strerror)) except ValueError: print("No valid integer in line. in <module> SyntaxError: Sorry. Die try-Anweisung kann von einer finally-Klausel gefolgt werden.

weil sie immer unter allen Umständen ausgeführt werden müssen. ob eine Ausnahme im try-Block aufgetreten ist oder nicht.oder Terminierungsaktionen.0 / x ZeroDivisionError: float division by zero bernd@saturn:~/bodenseo/python/beispiele$ . line 3.py". try: x = float(input("Your number: ")) inverse = 1.py Your number: 0 Ich werde immer ausgegeben. ob Fehler oder nicht Mich sieht man nur.6 Finalisierungsaktion 153 Man bezeichnet diese Form auch als Finalisierungs.py Your number: 42 Ich werde immer ausgegeben. und zwar unabhängig davon. ob Fehler oder nicht") print("Mich sieht man nur. in <module> inverse = 1. wenn es keinen Fehler gab! bernd@saturn:~/bodenseo/python/beispiele$ python3 finally_exception.0 / x finally: print("Ich werde immer ausgegeben. ob Fehler oder nicht Traceback (most recent call last): File "finally_exception.18. wenn es keinen Fehler gab!") In den folgenden Programmläufen demonstrieren wir einen Fehlerfall und einen Durchlauf ohne Ausnahmen: bernd@saturn:~/bodenseo/python/beispiele$ python3 finally_exception.

Wir haben Objekte und Methoden von Klassen benutzt. In diesem Kapitel geben wir nun eine ordentliche Einführung in den objektorientierten Ansatz von Python. aber. Funktionen. haben wir es bisher mit voller Absicht in den vorhergehenden Kapiteln unseres Tutorials vermieden. Eine Klasse darf nicht mit einem Objekt verwechselt werden. war „Simula 67” von Ole-Johan Dahl und Kirsten Nygard. ohne eigentlich von ihrer Existenz zu wissen. Das Grundkonzept der objektorientierten Programmierung besteht darin. d. Die erste Programmiersprache.19 19.1 Früchte Aber auch wenn wir die objektorientierte Programmierung vermieden haben. welche Attribute und welche Methoden sie hat. Auch wenn viele Programmierer und Informatiker die OOP für eine moderne Errungenschaft halten.h. – d. die auf diese Daten angewendet werden können –. muss man sie dennoch nicht nutzen. man kann auch mächtige und effiziente Programme ohne OOP-Techniken schreiben.h. die Objekte verwendete. wie ein Objekt beschaffen ist. in einem Objekt zusammenzufassen und nach außen zu kapseln. BILD 19. d. Objekte werden über Klassen definiert. .1 Objektorientierte Programmierung Einführung Auch wenn Python ohne Wenn und Aber eine objektorientierte Programmiersprache ist. Wir haben OOP ausgelassen. wie wir gesehen haben. so war sie dennoch in unseren Übungen und Beispielen präsent. dass es einfacher ist und mehr Spaß macht. Eine Klasse ist eine formale Beschreibung. so gehen ihre Wurzeln bis in die 1960er-Jahre zurück. wenn man Python zu lernen beginnt. auf die objektorientierte Programmierung (OOP) einzugehen. OOP ist eine der mächtigsten Programmiermöglichkeiten von Python. weil wir davon überzeugt sind. sodass Methoden fremder Objekte diese Daten nicht manipulieren können. Statt Objekt spricht man auch von einer Instanz einer Klasse. ohne dass man über die Details der OOP Bescheid wissen muss. Daten und deren Funktionen (Methoden).h.

wie eine Instanz der Klasse beschaffen sein muss. an Unterklassen wie Erdbeerkuchen. Zum Entfernen oder Löschen von Instanzen gibt es die Destruktor-Methode. So auch in diesem Beispiel einer „Kuchenklasse”.2 Die Kuchenklasse Bei Einführungen in die objektorientierte Programmierung wird häufig und gerne auf Beispiele aus dem Alltag zurückgegriffen. 19. was wir über es wissen. . Anders ausgedrückt: Ein Objekt kann immer durch zwei Dinge beschrieben werden: ■ was es tun kann oder was wir in einem Programm mit ihm tun können. Konstruktoren sind spezielle Methoden zur Erzeugung von Instanzen einer Klasse. diesen Kuchen zu verarbeiten oder zu verändern. dass ein Kuchen sich als Nachtisch nutzen lässt. 19. aber diese Beispiele lassen sich dann nicht in Programmiercode wandeln. Objekte oder Instanzen werden mittels Konstruktoren erzeugt. Die Begriffe Objekt und Instanz werden meist synonym gebraucht und bezeichnen den gleichen „Gegenstand”. Ein nette Methode stellt übrigens in diesem Beispiel „aufessen” dar. das Rezept bestimmt.156 19 Objektorientierte Programmierung 19. Backt jemand einen Kuchen nach diesem Objekt. Das heißt. Dabei handelt es sich meistens um Beispiele. Die Klasse dient als Bauplan zur Abbildung von realen Objekten in Software-Objekte. ■ Objekte sind Instanzen oder Exemplare einer Klasse. die sogenannten Instanzen. die ihre Eigenschaften.4 Klasse Eine Klasse ist ein abstrakter Oberbegriff für die Beschreibung der gemeinsamen Struktur und des gemeinsamen Verhaltens von realen Objekten (Klassifizierung). z. dann schafft er eine Instanz oder ein Objekt dieser Klasse. die zwar helfen.BILD 19.B. Reale Objekte werden auf die für die Software wichtigen Merkmale abstrahiert. Ein Erdbeerkuchen gehört in eine übergeordnete Klasse „Kuchen”.2 Kuchenklasse chens. Torten und so weiter vererbt. objektorientierte Konzepte zu verdeutlichen. Ein solches Rezept kann man prinzipiell als eine Klasse ansehen. Es gibt dann verschiedene Methoden. Betrachten wir das Rezept eines Erdbeerku. Ein Objekt bezeichnet in der OOP die Abbildung eines realen Gegenstandes mit seinen Eigenschaften und Verhaltensweisen (Methoden) in ein Programm.3 Objekte Der zentrale Begriff in der objektorientierten Programmierung ist der des Objekts. Rührkuchen.

19. 19. und aus dieser leitet sich eine andere Klasse ab (Erdbeerkuchen). Man hat beispielsweise eine Oberklasse (Kuchen).5 Kapselung von Daten Ein weiterer wesentlicher Vorteil der OOP besteht in der Kapselung von Daten. BILD 19.3 Kontenklasse Die Klasse fasst hierfür notwendige Eigenschaften (Attribute) und zur Manipulation der Eigenschaften notwendige Methoden zusammen. So kann z. Klassen stehen häufig in Beziehung zueinander. eine Methode zum Setzen des Geburtsdatums prüfen. z. Diese Methoden können Plausibilitätstests enthalten. und sie (oder „nur” sie) besitzen „Informationen” über die eigentliche Implementierung. Der Zugriff auf Eigenschaften darf nur über Zugriffsmethoden erfolgen.5 Kapselung von Daten 157 BILD 19. Girokonto für Kinder unter 14 nicht möglich oder Kunden über 100 Jahre unwahrscheinlich. Diese abgeleitete Klasse erbt bestimmte Eigenschaften und Methoden der Oberklasse.4 Datenkapselung . ob das Datum korrekt ist und sich innerhalb eines bestimmten Rahmens bewegt.B.B.

158 19 Objektorientierte Programmierung 19. Aber auch. BILD 19. Die Vererbung dient also dazu.7 Klassen in Python Eine Klasse besteht aus zwei Teilen: dem Kopf und einem Körper. Eine neue Klasse kann dabei sowohl als eine Erweiterung als auch als eine Einschränkung der ursprünglichen Klasse entstehen.6 Vererbung In unserem Beispiel erkennt man leicht. Der Kopf besteht meist nur aus einer Zeile: das Schlüsselwort class. Der Körper einer Klasse besteht aus einer eingerückten Folge von Anweisungen. usw. unter Zugrundelegung von existierenden Klassen neue zu schaffen. dass eine Klasse „Konto” einer realen Bank nicht genügen kann. wie es in unseren anfänglichen Beispielen immer der Fall sein wird. können wir für unsere obige „sinnlose” Klasse bereits Objekte definieren: . die man auch durch eine pass-Anweisung ersetzen kann. Jetzt wissen wir genug. Es gibt verschiedene Arten von Konten: Girokonto. einer Liste von Oberklassen in Klammern und als letztes Zeichen ein Doppelpunkt. Sparkonto. wenn diese fehlen. Hat man keine spezielle Oberklasse. Gemeinsame Methoden: Einzahlen und Auszahlen Es gibt also so etwas wie ein Grundkonto. um eine einfache Python-Klasse definieren zu können: class Konto(object): pass Anstelle von pass stünde bei einer „richtigen” Klasse die Definition der Attribute und Methoden dieser Klasse. einen Kontoinhaber und einen Kontostand aufweisen. Aber allen verschiedenen Konten sind bestimmte Eigenschaften und Methoden gemeinsam. einem beliebigen Namen. Beispielsweise wird jedes Konto eine Kontonummer.5 Vererbung 19. gefolgt von einem Leerzeichen. von dem alle anderen Konten „erben”. dann gibt man als Oberklasse die Standard-Basisklasse object an.

"credits" or "license" for more information. die innerhalb einer class-Definition definiert ist. betrag): pass def kontostand(self): pass Obige Klasse können wir bereits benutzen.3 (default. von der sie aufgerufen wird.19. >>> from konto import Konto >>> x = Konto() >>> x. pass .. "copyright". Beispiel mit Methode: class Konto(object): def ueberweisen(self..2] on linux2 Type "help". dass x eine Instanz der Klasse Konto im Namensraum __main__ ist.Konto object at 0xb725a2ec> Wie wir sehen. >>> x = Konto() >>> y = Konto() >>> z = x >>> print(x) <__main__. Wir speichern sie unter dem Namen konto.7. Die Ausgabe sagt uns. Beim Aufruf wird er nicht angegeben.2.8 ■ Methoden Eine Methode unterscheidet sich äußerlich nur in zwei Aspekten von einer Funktion: Sie ist eine Funktion. Der erste Parameter einer Methode ist immer eine Referenz self auf die Instanz. betrag): pass def einzahlen(self.py und führen folgende Anweisungen in der interaktiven Python-Shell aus: $ python3 Python 3..einzahlen(12300000) >>> . ■ Der Parameter self erscheint nur bei der Definition einer Methode. Oct 19 2012.8 Methoden 159 >>> class Konto(object): .. auch wenn wir natürlich kaum etwas Sinnvolles damit anstellen können. ziel. 19:53:57) [GCC 4. können wie sogar eine Klasse ausdrucken. betrag): pass def auszahlen(self. Die Zahl nach dem at gibt den Speicherort dieser Klasse an. 19.

dass das Argument „self” automatisch generiert wird. erhält man eine Fehlermeldung. Allerdings nur. d. 1000) Wir erkennen. dass wir bei der Definition eines Objektes nun mindestens drei Parameter angeben müssen.h. kontonummer. line 1. dass das Objekt mindestens vier Argumente („takes at least 4 arguments”) erwarte. Wenn man eine Instanz einer Klasse mit del löscht. In Python ist jedoch ein Objekt bereits existent bzw.10 Destruktor Für eine Klasse kann man auch einen Destruktor __del__ definieren. falls es keine weitere Referenz auf diese Instanz gibt. Die Methode __init__ wird dazu benutzt. dass wir kein Argument übergeben haben. konstruiert. 234322. "copyright". sobald ein Objekt einer Klasse in Python instanziiert wird. mit der ein Objekt konstruiert wird. inhaber.Kontokorrent = kontokorrent Auch diese Klasse wollen wir in der interaktiven Shell ausprobieren: $ python3 Python 3.Kontonummer = kontonummer self. 19:53:57) [GCC 4. "credits" or "license" for more information. und der Meldung „1 given” kommt daher. Meistens wird __init__ als der Konstruktor einer Klasse bezeichnet. versteht man aber unter einem Konstruktor eine spezielle Methode. in anderen objektorientierten Sprachen.2] on linux2 Type "help". aber nur einen („1 given”) erhalten habe.9 Konstruktor Die Methode __init__ wird aufgerufen. ein Objekt der Klasse zu initialisieren.Kontostand = kontostand self. da man . Normalerweise. Der scheinbare Widerspruch. wird der Destruktor aufgerufen. kontokorrent=0): self. 19. kontostand. Oct 19 2012. in <module> TypeError: __init__() takes at least 4 arguments (1 given) >>> x = Konto("Bill Boe".7.160 19 Objektorientierte Programmierung 19. Die __init__-Methode wird im Prinzip wie jede andere Methode definiert: def __init__(self. Versucht man ein Objekt ohne Angabe von Argumenten zu generieren.3 (default. wie der Name vermuten lässt. wenn die Methode __init__ aufgerufen wird. >>> from konto import Konto >>> x = Konto() Traceback (most recent call last): File "<stdin>". Destruktoren werden selten benutzt.Inhaber = inhaber self.2.

kontokorrent=0): self.Kontokorrent = kontokorrent def ueberweisen(self.Kontostand .7.Kontostand = kontostand self. >>> from greeting import Greeting >>> x1 = Greeting("Bernd") >>> x2 = x1 >>> del x1 >>> del x2 Destruktor gestartet 19.name = name def __del__(self): print("Destruktor gestartet") def SayHello(self): print("Guten Tag". kontostand.3 (default. Oct 19 2012.Kontokorrent): # Deckung nicht genuegend return False else: self.Kontostand += betrag return True def einzahlen(self. betrag): if(self. 19:53:57) [GCC 4. kontonummer.Inhaber = inhaber self.2. betrag): self.Kontostand += betrag . inhaber.11 Lauffähige Version der Kontoklasse 161 sich normalerweise nicht um das Aufräumen im Speicher kümmern muss. "credits" or "license" for more information.betrag < -self. ziel. self. "copyright". Im Folgenden sehen wir ein Beispiel mit Konstruktor und Destruktor: class Greeting: def __init__(self.2] on linux2 Type "help".11 Lauffähige Version der Kontoklasse class Konto(object): def __init__(self.Kontostand -= betrag ziel. name): self.name) Diese Klasse wird nun interaktiv benutzt: $ python3 Python 3.Kontonummer = kontonummer self.19.

2] on linux2 Type "help".kontostand() 1142.0 >>> konto2.kontostand() 2000.kontostand()kuchenkl 5000.3 (default.1799999999998 >>> konto2.kontostand() 4142.4142. "credits" or "license" for more information.83) >>> konto1.1957.2. betrag): self. kann man mit der Klasse in einer python-Shell wie folgt arbeiten: $ python3 Python 3.73813.18) >>> konto1.Kontostand 1000000 Der einfache lesende Zugriff stellt natürlich im obigen Beispiel kein Problem dar.Kontostand = 1000000 >>> konto2.Kontonummer 73813 >>> konto2.Kontostand 1142.162 19 Objektorientierte Programmierung def auszahlen(self.0 >>> konto2.kontostand() 1957. "copyright".1799999999998 >>> konto2.ueberweisen(konto2.einzahlen(42. aber wenn jemand direkt den Kontostand verändert. >>> from konto import Konto >>> konto1 = Konto("Jens".82) True >>> konto1. hat das gravierende Folgen für unsere .70711.py ab.17) >>> konto2 = Konto("Maria". 19:53:57) [GCC 4. 857.18 >>> konto1.0 >>> 19. Man kann von außen direkt auf die Attribute zugreifen. was dem Prinzip der Datenkapselung widerspricht: >>> konto1.Kontostand -= betrag def kontostand(self): return self.12 Public-Attribute Leider hat unsere Klasse Konto() noch einen kleinen Schönheitsfehler. Oct 19 2012.7.Kontostand Speichert man obigen Code konto.Kontostand 5000.17 >>> konto1.

Warnmeldungen ausgeben.und schreibbar. z.__Kontostand . Die Methode Einzahlen und Überweisen müsste auch beispielsweise Maßnahmen bzgl.13 Datenkapselung Normalerweise sind alle Attribute einer Klasseninstanz öffentlich. sondern über die Namen. dass man diese Member nicht benutzen sollte. was wir in unserem Beispiel nicht getan haben.Protected.19. 19.__Kontokorrent = kontokorrent def ueberweisen(self. ziel.__Kontostand -= betrag . Selbst wenn der Kontostand korrekterweise wirklich eine Million nach einer Einzahlung betragen sollte.B. z. betrag): if(self.__Kontostand = kontostand self. des Geldwäschegesetzes ergreifen. der Gesamtbestand aller Konten. wenn ein direkter Zugriff auf die Attribute möglich ist.h. nicht mehr synchron. aber der Entwickler macht damit klar.B. kontonummer. kontokorrent=0): self. dem eigentlichen Namen vorangestellten Unterstrich für protected-Attribute und ein zweifacher vorgestellter Unterstrich für private-Attribute.h.13 Datenkapselung und die Benutzung von Public. wenn eine Einzahlung über einen bestimmten Betrag geht. All dies wäre außer Kraft gesetzt.betrag < -self. kontostand. Die Steuerung erfolgt nicht über irgendwelche speziellen Schlüsselwörter. d.__Inhaber = inhaber self. Man kann zwar auch von außen lesend und schreibend zugreifen. ein einfacher. so wären bestimmte andere Größen der Buchführung. inhaber. von außen zugänglich. Python bietet einen Mechanismus. um dies zu verhindern. Normalerweise müsste ja bei jeder Einzahlung diese Größe auch angepasst werden.__Kontokorrent): # Deckung nicht genuegend return False else: self.und Private-Attributen 163 Bank. Sind von außen nicht sichtbar und nicht benutzbar. wie man der folgenden Tabelle entnehmen kann: Namen name Bezeichnung Public Bedeutung Attribute ohne führende Unterstriche sind sowohl innerhalb einer Klasse als auch von außen les. d. _name Protected __name Private Unsere Konto-Beispielklasse sieht mit „private”-Attributen wie folgt aus: class Konto(object): def __init__(self.__Kontonummer = kontonummer self.

"credits" or "license" for more information. als gäbe es kein Attribut __Kontostand in der Klasse Konto. die so tut. line 1. Man bezeichnet dies als „nicht-statisch” oder dynamisch.2] on linux2 Type "help". 19.3 (default. in <module> AttributeError: 'Konto' object has no attribute '__Kontostand' Eigentlich würde man die Fehlermeldung erwarten.__Kontostand -= betrag def kontostand(self): return self. betrag): self. Es ist Usus. >>> from konto import Konto >>> konto = Konto("Jens".B. "copyright".2013.164 19 Objektorientierte Programmierung ziel.14 Statische Member Bisher hatte jedes Objekt einer Klasse seine eigenen Attribute und Methoden. Wie kann man aber z. die Anzahl der verschiedenen Instanzen einer Klasse zählen? In unserer Konto()-Klasse entspräche dies der Anzahl der verschiedenen Konten. ob wir wirklich nicht auf die privateAttribute zugreifen können: $ bernd@saturn:~/bodenseo/python/examples$ python3 Python 3. Oct 19 2012.00) >>> konto. wie man Instanzen mittels einer Klassenvariablen zählen kann. die statischen Member direkt unterhalb der class-Anweisung zu positionieren.__Kontostand Wir testen nun in der interaktiven Python-Shell. da sie für jedes Objekt einer Klasse dynamisch erstellt werden. 19:53:57) [GCC 4.7.__Kontostand Traceback (most recent call last): File "<stdin>". dass man auf das Attribut __Kontostand nicht zugreifen darf.__Kontostand += betrag def auszahlen(self. Stattdessen kommt die obige Meldung. Dazu erhöhen wir die Variable counter bei der Initialisierung jeder neuen Instanz. Wird eine Instanz gelöscht. die sich von denen anderer Objekte unterschieden. Statische Attribute werden außerhalb des Konstruktors direkt im class-Block definiert. betrag): self. da es private ist. Im folgenden Beispiel zeigen wir.70711.2.__Kontostand += betrag return True def einzahlen(self. in der in unserem Beispiel die Klassenvariable counter um 1 vermindert wird: . wird die Methode __del__ aufgerufen.

counter)) " + str(C.19. dass wir die Variablen nicht explizit mittels __del__ zerstören.14.py Anzahl der Instanzen: 1 Anzahl der Instanzen: 2 .counter)) y = C() print("Anzahl der Instanzen: " + str(C.1 __del__ class C(object): counter = 0 def __init__(self): C.py Anzahl der Instanzen: Anzahl der Instanzen: Anzahl der Instanzen: Anzahl der Instanzen: 1 2 1 0 Allerdings gibt es hierbei einen Haken.counter)) erhalten wir eine Fehlermeldung: $ python3 counter.counter)) Starten wir das obige Programm. Nehmen wir an. erhalten wir folgende Ausgabe: $ python3 counter.counter += 1 def __del__(self): C.counter -= 1 if __name__ == "__main__": x = C() print("Anzahl der Instanzen: y = C() print("Anzahl der Instanzen: del x print("Anzahl der Instanzen: del y print("Anzahl der Instanzen: " + str(C.counter -= 1 if __name__ == "__main__": x = C() print("Anzahl der Instanzen: " + str(C.counter += 1 def __del__(self): C.14 Statische Member 165 19. also die letzten vier Zeilen löschen: class C(object): counter = 0 def __init__(self): C.counter)) " + str(C.counter)) " + str(C.

In den meisten Fällen muss man ein Attribut lesen und ändern können. Dazu muss man dann zwei Methoden schreiben: eine. Eine Lösung des Problems besteht darin.C object at 0xb71af20c>> ignored Exception AttributeError: "'NoneType' object has no attribute 'counter'" in <bound method C. wenn ein Programm endet.C object at 0xb71af1ac>> ignored Die Fehlermeldungen resultieren daher. werden zuerst gelöscht. wenn die Klasse bereits gelöscht ist. um diesen Wert ändern zu können (in unserem Fall „setX()”).__del__ of <__main__. die mit einem Unterstrich beginnen.__x = x def getX(self): .__del__ of <__main__. Diese Abfragemethoden werden allgemein auch als „getter” und die Änderungsmethoden als „setter” bezeichnet. dass die Methode __del__ in diesem Fall erst aufgerufen wird. class C(object): counter = 0 def __init__(self): C. Variablen. wie man korrekt im Sinne der Datenkapselung auf private Attribute zugreift. class P(object): def __init__(self.x): self.py Anzahl der Instanzen: 1 Anzahl der Instanzen: 2 19. um einen Attributwert lesen zu können (in unserem Fall „getX()”).counter)) Obiges Skript liefert nun die folgende Ausgabe: $ python3 counter. die globalen Variablen mit einem Unterstrich zu versehen.counter)) _y = C() print("Anzahl der Instanzen: " + str(C.counter -= 1 if __name__ == "__main__": _x = C() print("Anzahl der Instanzen: " + str(C.15 Properties In der folgenden Klasse P wollen wir zeigen.166 19 Objektorientierte Programmierung Exception AttributeError: "'NoneType' object has no attribute 'counter'" in <bound method C. und eine.counter += 1 def __del__(self): C.

getX() 19 >>> a.56 schreiben könnten.__x * 0. als wäre es eine öffentliche Variable: >>> >>> >>> >>> >>> from p import P a = P(19) b = P(10) c = a. wenn wir direkt b = a.setX(42) >>> b = a. also in unserem Fall der Methode getX(). und wir wollen ja keinesfalls das Konzept der Datenkapselung aufweichen oder verletzen.19.56 >>> b 23.__x = x x = property(getX.getX() * 0. Jetzt können wir x benutzen.56 statt b = a.15 Properties 167 return self.__x = x def getX(self): return self. was einem einen leichteren Zugriff auf privateAttribute ermöglicht. Dies geht jedoch nicht. wie man mit diesen Methoden arbeitet: >>> from p import P >>> a = P(19) >>> a.__x def setX(self. weil __x ein private-Attribut ist.__x = x In der folgenden interaktiven Beispielsitzung zeigen wir.__x def setX(self. setX) Das erste Argument von property muss dem „getter”. also „setX()” in unserem Beispiel.x + b.x c . x): self. x): self. Das zweite Argument enthält den Namen der „setter”-Methode.getX() * 0.x): self. Mit den Properties bietet Python ein Sprachkonstrukt.520000000000003 >>> Deutlich bequemer wäre es natürlich. entsprechen. Wir erweitern obiges Beispiel um eine Property x: class P(object): def __init__(self.

Es ist Usus. also in unserem Fall die Anzahl der verschiedenen Konten der Klasse Konto. Wie kann man jedoch Informationen speichern. >>> from p import P >>> a. also der „getter”-Methode auf: class P(object): def __init__(self. da sie für jedes Objekt einer Klasse dynamisch erstellt werden. line 1.__x = x def getX(self): return self.__x = x x = property(getX) Wir können in obiger Beispielanwendung sehen. Instanzattribute werden für jedes Objekt angelegt. Statische Attribute werden auch als Klassenattribute bezeichnet. Möchte man lediglich einen lesenden Zugriff auf ein privates Attribut erlauben.168 19 Objektorientierte Programmierung 29 >>> Ohne Zweifel ist dies in der Benutzung angenehmer. die statischen Member direkt unterhalb der class-Anweisung zu positionieren. also setX() und getX(). . Ein Klassenattribut existiert pro Klasse nur einmal. in <module> AttributeError: can't set attribute >>> 19. dass wir lesend zugreifen können. erhalten wir eine Fehlermeldung. dann ruft man die Property nur mit einem Argument. die für die ganze Klasse gelten und nicht nur für einzelne Objekte der Klasse. die sich nicht auf ein bestimmtes Objekt beziehen.__x def setX(self. wird also nur einmal angelegt. der Property x etwas zuzuweisen. die sich von denen anderer Objekte unterschieden. Man bezeichnet dies als „nicht-statisch” oder „dynamisch”.16 Dynamische und statische Attribute Bisher hatte jedes Objekt einer Klasse seine eigenen Attribute und Methoden. sondern für die ganze Klasse relevant sind? Eine solche Information wäre beispielsweise die Anzahl aller Objekte einer Klasse. Dennoch erfolgen alle Zugriffe auf das private Attribut _x nur über die korrekten Zugriffsmethoden.x = 42 Traceback (most recent call last): File "<stdin>". Eigenschaften bezeichnen. werden Instanzattribute innerhalb der __init__-Methode angelegt. Wie wir bereits gesehen haben.x): self. weil sie wie bereits gesagt. Außerdem muss jedem Klassenattribut ein Initialwert zugewiesen werden. wohingegen statische Attribute außerhalb dieser Methode direkt im class-Block definiert werden. Versuchen wir jedoch. x): self.

__counter -=1 def getCounter(): return P. def __init__(self.1 Vererbung Oberbegriffe und Oberklassen Jeder kennt die Oberbegriffe aus der natürlichen Sprache.__counter += 1 def __del__(self): P. Autos kann man auch wieder nach verschiedenen Kriterien klassifizieren.17 19. . Busse. mit Diesel oder mit Strom angetriebene Autos. dann können dies Autos.17 Vererbung 169 Wir erläutern dies in einem kleinen Beispiel: class P(object): __counter = 0. z. nach der Antriebsart. Benziner.getCounter() del y P.__x = x P. Züge. Lastwagen.B.getCounter() z = x P.17. Flugzeuge oder auch Fahrräder und Roller sein. zeigen wir in der folgenden interaktiven Sitzung: >>> >>> >>> 1 >>> >>> 2 >>> >>> 2 >>> >>> 2 >>> >>> 1 >>> >>> 0 >>> from p_counter import P x = P(42) P. In der objektorientierten Programmierung spricht man hierbei von Vererbung und von Ober.__counter Wie das Zählen funktioniert.und Unterklassen.getCounter() del x P.getCounter() 19. Schiffe.getCounter() y = P(44) P. Motorräder.x): self.getCounter() del z P. Wenn wir von Fahrzeugen reden.19.

Eine reale Bank hat viele verschiedene Kontenarten. dass nun die Information über die Religionszugehörigkeit. Ebenso sieht es bei der Kundenklasse aus. Häufig werden auch Klassen modelliert.170 19 Objektorientierte Programmierung Ein weiteres Beispiel eines Oberbegriffes stellt Person dar. Ein Sparbuch ebenso wie ein Girokonto erben also von der Basisklasse „Konto”. so wie beispielsweise Sparbücher und Girokonten. Nehmen wir nun Personeneigenschaften an. und ihre Kopfzeilen enthalten den Namen der Basisklasse. Kunden. die Personenklasse als Oberklasse für die Angestellten-. In der Kopfzeile hatten wir immer eine Basisklasse angegeben. Hier machen Information wie Religionszugehörigkeit. nämlich „object”.2 Vererbung in Python Bisher haben wir im Prinzip immer Unterklassen definiert. Wohnort.17. Geschlecht und so weiter. 19. aber zum Beispiel die bevorzugte Zahlungsmethode oder Ähnliches.6 Vererbung von oder Ähnliches ausnehmen. Ganz allgemein kann man sagen. Geburtsdatum. Vorname.und Lieferantenklasse einzuführen. sondern an einer abstrakten Oberklasse mit abstrakten Unterklassen demonstrieren. Wir definieren eine Klasse A mit einer __init__-Methode und einer Methode m: . class Sparbuch(Konto): pass class Girokonto(Konto): pass Einige Konzepte der Vererbung möchten wir jedoch nicht an einem praktischen Beispiel wie der Kontenklasse. die Steuerklasse oder Kinderzahl fehlt. Wahrscheinlich würde man jedoch nicht Daten wie Steuernummer. In der Einführung zur objektorientierten Programmierung hatten wir bereits allgemein über mögliche Unterklassen einer allgemeinen Klasse „Konto” gesprochen. um das Nettogehalt korrekt zu berechnen. Man merkt schnell. Also beispielsweise bei der Definition unserer Kontoklasse: class Konto(object): pass Jede Klasse erbt in Python von der Klasse „object”. Steuerklasse oder Kinderzahl keinen Sinn. Religionszugehörigkeit BILD 19. die Eigenschaften von Personen in Datenstrukturen abbilden. dass man diese Klasse für die Firmenbuchhaltung benutzen will. Es macht also Sinn. dass die Vererbung eine Beziehung zwischen einer allgemeinen Klasse (einer Oberklasse oder einer Basisklasse) und einer spezialisierten Klasse (der Unterklasse. Allgemeine Daten für Personen sind Name. manchmal auch Subklasse genannt) definiert.

Was passiert.py __init__ von A wurde ausgeführt m von A wurde aufgerufen __init__ von B wurde ausgeführt m von B wurde aufgerufen . wie dies in der Anweisung „y = B()” geschieht. denn B hat keine Methode m. wenn wir die Klasse B nun auch mit einer __init__-Methode und einer Methode m ausstatten? Wir testen dies im folgenden Beispiel. erhalten wir folgende Ausgabe: $ python3 inheritance1.content = "42" print("__init__ von A wurde ausgeführt") def m(self): print("m von A wurde aufgerufen") class B(A): pass if __name__ == "__main__": x = A() x. erhalten wir die folgende Ausgabe: $ python3 inheritance2.content = "43" print("__init__ von B wurde ausgeführt") def m(self): print("m von B wurde aufgerufen") Rufen wir das veränderte Skript nun auf. Aber wenn wir ein Objekt der Klasse B erzeugen. Ebenso erkennen wir. dass beim Aufruf der Methode m für das Objekt y der Klasse B die Methode m von A aufgerufen wird.m() Ruft man diese Klasse direkt auf.py __init__ von A wurde ausgeführt m von A wurde aufgerufen __init__ von A wurde ausgeführt m von A wurde aufgerufen Die Ergebnisse der ersten beiden Anweisungen hinter der if-Anweisung stellen nichts Neues dar.m() y = B() y.17 Vererbung 171 class A(object): def __init__(self): self. wir ändern lediglich die Klasse B wie folgt: class B(A): def __init__(self): self.19. Die Klasse A und unsere Tests bleiben gleich. dann können wir an der Ausgabe erkennen. da B keine eigene __init__-Methode besitzt. dass die __init__-Methode der Klasse A ausgeführt wird.

overwriting .contentA)) AttributeError: 'B' object has no attribute 'contentA' Wie erwartet erhalten wir für self.m() print("self. class A(object): def __init__(self): self.contentA)) Starten wir obiges Programm.m() y = B() y. Wir haben in A ein Attribut self.py __init__ von A wurde ausgeführt m von A wurde aufgerufen __init__ von B wurde ausgeführt m von B wurde aufgerufen self. sind eigentlich nur die beiden letzten Print-Anweisungen von Interesse. was wir später behandeln werden.py". $ python3 inheritance3. Man darf dies nicht mit Überladen verwechseln. dass wir beim 1 engl.contentA von y: " + str(y. Im folgenden Beispiel ändern wir nun die Instanzattribute der Klassen A und B. Da die __init__Methode der Klasse A nicht aufgerufen wird.contentB den Wert 43 als Ausgabe.172 19 Objektorientierte Programmierung Wir erkennen nun. line 25. sollte es uns nicht wundern.contentA von y: " + str(y.contentB von y: " + str(y.contentA = "42" print("__init__ von A wurde ausgeführt") def m(self): print("m von A wurde aufgerufen") class B(A): def __init__(self): self. Außerdem wird nun die Methode m von B statt der Methode m von A benutzt. Man bezeichnet dies als Überschreiben1 einer Methode. in <module> print("self.contentA und in B eines mit dem Namen self.contentB.contentB von y: 43 Traceback (most recent call last): File "inheritance3.contentB = "43" print("__init__ von B wurde ausgeführt") def m(self): print("m von B wurde aufgerufen") if __name__ == "__main__": x = A() x.contentB)) print("self. dass die __init__-Methode von B und nicht mehr die von A beim Erzeugen einer Instanz von B aufgerufen wird.

19. B >>> y = B() __init__ von A wurde ausgeführt __init__ von B wurde ausgeführt >>> y. Im Folgenden rufen wir in m von B auch die Methode m von A auf: def m(self): A. Dies geschieht durch die Anweisung „A.contentB = "43" print("__init__ von B wurde ausgeführt") Ruft man das gesamte Programm mit obiger Änderung auf.__init__(self) self. Die Klasse A und die Tests bleiben gleich. die wir bei der Initialisierung eines Objektes einer Basisklasse einführen. Wir können dies erreichen. Also in unserem Beispiel hätten wir vielleicht gerne das Attribut contentA. einen AttributeError mit dem Text . dass wir spezielle Attribute. Wir können uns auch vorstellen. d.m(self) print("m von B wurde aufgerufen") Wir testen dieses Skript. denn es gibt ja kein Attribut self.__init__(self)”.py __init__ von A wurde ausgeführt m von A wurde aufgerufen __init__ von A wurde ausgeführt __init__ von B wurde ausgeführt m von B wurde aufgerufen self.B’ object has no attribute .contentB von y: 43 self. dass die Instanz von y sowohl ein Attribut contentB als auch ein Attribut contentA enthält: $ python3 inheritance4.h. sehen wir. indem wir in der __init__-Methode von B die __init__-Methode von A aufrufen.contentA von y: 42 Dieses Vorgehen lässt sich analog auf andere Methoden übertragen.contentA auszugeben.contentA’ erhalten. auch in der Unterklasse verwenden wollen.m() m von A wurde aufgerufen m von B wurde aufgerufen >>> . Name der Basisklasse plus Aufruf der __init__-Methode. in der interaktiven Python-Shell: >>> from inheritance5 import A. self. Außerdem erkennen wir.17 Vererbung 173 Versuch. das unter dem Namen inheritance5. dass unser AttributeError verschwunden ist.contentB in den Instanzen von B.py abgespeichert ist. Wir müssen lediglich die __init__-Methode in B wie folgt ändern: class B(A): def __init__(self): A.

Auch wenn es in Wirklichkeit komplizierter ist. wobei nicht zweimal in derselben Klasse gesucht wird. Falls ein Attribut nicht in Unterklasse gefunden wird. kann man es sich so vorstellen: Zuerst erfolge eine Tiefensuche2 .3. Man spricht in diesen Fällen von Mehrfachvererbung. Die obigen Basisklassen Basis1. können natürlich ihrerseits wieder von anderen Basisklassen geerbt haben. gibt man die Basisklassen durch Kommata getrennt in die Klammern hinter dem Klassennamen an: class UnterKlasse(Basis1. Syntaktisch realisiert man dies wie folgt: Soll eine Klasse von mehreren Basisklassen erben. BILD 19. Basis1. Dies wollen wir an folgendem Beispiel demonstrieren: 2 3 englisch: depth-first search.7 Vererbungsbaum bei Mehrfachvererbung Die Frage stellt sich nun.): pass Wie bei der einfachen Vererbung können Attribute und Methoden mit gleichen Namen in der Unterklasse und in Basisklassen vorkommen. Basis2 usw. den Vererbungsbaum... Dadurch erhält man eine Vererbungshierarchie.18. wird anschließend in Basis1 gesucht. Basis2.oder Methodennamen vorgeht. wenn eine Klasse von zwei oder mehr Basisklassen erben kann. dann rekursiv in den Basisklassen von Basis1. dann rekursiv in die Basisklassen von Basis2 usw.18 19. . Basis3. die man sich als einen Baum vorstellen kann.1 Mehrfachvererbung Theorie In unseren bisherigen Klassenbeispielen erbte eine Unterklasse immer nur von einer Basisklasse. dann wird von links nach rechts3 gesucht. geht die Suche in Basis2 weiter. Es gibt aber Problemstellungen.1. wenn eine Klasse von mehr als einer Basisklasse erbt. wenn sich die Klassenhierarchie dort überlappt.174 19 Objektorientierte Programmierung 19. in denen es sinnvoll ist. wie Python auf der Suche nach einem Attribut. DFS left-to-right search .2 und Basis1. also in unserem Beispiel Basis1. Wenn auch in all diesen Klassen nichts gefunden wurde.

py This is method m of class U This is method m of class B1 This is method m of class B12 Im Folgenden entfernen wir die Methode m aus der Klasse U und ersetzen den Klassenrumpf durch die pass-Anweisung: class B11(object): def m(self): print("This is method m of class B11") class B12(object): def m(self): print("This is method m of class B12") class B21(object): . dass die Methode m von U aufgerufen wird.B2): def m(self): print("This is method m of class U") x = U() x.m() B1. Außerdem sehen wir.m(x) Startet man dieses Programm. sieht man.m(x) B12.19.m(x) die Methode m von B1 dennoch auf ein Objekt von U anwenden können: $ python3 mehrfachvererbung. dass wir mit B1.B12): def m(self): print("This is method m of class B1") class B2(B21): def m(self): print("This is method m of class B2") class U(B1. wenn man m auf ein Objekt von U anwendet.18 Mehrfachvererbung 175 class B11(object): def m(self): print("This is method m of class B11") class B12(object): def m(self): print("This is method m of class B12") class B21(object): def m(self): print("This is method m of class B21") class B1(B11.

B2): pass x = U() x.2 Diamond-Problem Bei dem Diamond-Problem4 handelt es sich um ein Mehrdeutigkeitsproblem. so wird m aus B12 aufgerufen. sagen wir „m”. Falls D eine Methode.8 Diamond-Problem ■ ■ ■ 4 englisch: diamond problem oder „deadly diamond of death” . Es kann auftreten.176 19 Objektorientierte Programmierung def m(self): print("This is method m of class B21") class B1(B11. aufruft. wenn eine Klasse D auf zwei verschiedenen Vererbungspfaden über eine Klasse B und eine Klasse C von der gleichen Basisklasse A abstammt. dass nun die Methode m von B11 aufgerufen wird. wird anschließend m aus B2 aufgerufen.py This is method m of class B1 Entfernt man nun die Methode m auch noch aus B1 und ersetzt auch hier den Rumpf durch pass. Wir können nun so weiter fortfahren: Entfernen wir m aus B12. sieht man. was durch Mehrfachvererbung in der objektorientierten Programmierung entstehen kann.m() Nach dem anfangs Gesagten müsste nun Python die erste. für die gilt: ■ m wird in A definiert B überschreibt m C überschreibt m m wird nicht in D überschrieben. sehen wir.B12): def m(self): print("This is method m of class B1") class B2(B21): def m(self): print("This is method m of class B2") class U(B1. Starten wir das Programm.18. 19. BILD 19. dass nun wirklich m von B1 aufgerufen wird: $ python3 mehrfachvererbung. also die am weitesten links stehende Klasse der Basisklassen durchsuchen. Entfernen wir nun auch in B11 die Methode m.

min.18.set_Clock(h. min. die eine Uhr implementiert. Wir schreiben eine Klasse „CalendarClock”. Die Uhrzeit kann mit einer Methode sekundenweise weiterbewegt werden. die Uhrzeit und Datum implementiert.18 Mehrfachvererbung 177 Die Frage.9 CalendarClock Die Klasse Clock simuliert das sekundenmäßige Ticken einer Uhr. was im Englischen auch als „diamond” bezeichnet wird. sec müssen Ganzzahlen sein. dann kommt m aus C.B): definiert ist. woher der Name „Diamond-Problem” kommt: Zeichnet man die Vererbungsbeziehungen zwischen den Klassen in einem Diagramm. also das Vorwärtsschreiten der Uhr um eine Sekunde. Sicherlich fragen Sie sich noch. und es muss gelten: 0 <= h < 24 0 <= min < 60 0 <= sec < 60 """ self. Der Code der Lösung dieser Übungsaufgabe (siehe Seite 385) befindet sich nun in unserer Methode tick(). Zunächst implementieren wir zwei voneinander unabhängige Klassen: eine Klasse „Clock” und eine Klasse „Calendar”. die sich dann stellt: Von welcher Klasse wird m vererbt? In Python hängt es von der Reihenfolge der Klassen bei der Definition von D ab: Falls D als class D(B. dann kommt m aus B. bereits simuliert (siehe Seite 58). """ class Clock(object): def __init__(self. Wir möchten nun an einem praktischen Beispiel die Vererbung oder genauer sogar das Prinzip der Mehrfachvererbung demonstrieren.19.C): definiert ist. BILD 19. 19. Im Kapitel 8 (Verzweigungen) hatten wir in einer Übungsaufgabe das Ticken. min. Die komplette Klasse „Clock”: """ Die Klasse Clock dient der logischen Simulation einer Uhr.3 Beispiel: CalendarClock Bisher haben wir die Vererbung an sehr abstrakten und theoretischen Klassen erklärt.sec) . falls D ansonsten als class D(C. sec): """ Die Parameter h. so sieht das Ergebnis wie eine Raute aus. h.

d.second) def tick(self): """ Die interne Uhrzeit eines Objekts. es wird eine Methode zur Verfügung gestellt. d. self. """ return "{0:02d}:{1:02d}:{2:02d}". die Stunden-. und es muss gelten: 0 <= h < 24 0 <= min < 60 0 <= sec < 60 """ if type(h) == int and 0 <= h and h < 24: self. self. Die Methode __str__ wird auch von der Print-Funktion genutzt. Minuten.59) >>> print(x) 12:59:59 >>> x. Beispiele: >>> x = Clock(12.und Sekunden-Attribute.second = sec else: raise TypeError("Sekunden müssen Ganzzahlen zwischen 0 und 59 sein!") def __str__(self): """ Diese Methode überlädt die eingebaute Funktion str().minute = min else: raise TypeError("Minuten müssen Ganzzahlen zwischen 0 und 59 sein!") if type(sec) == int and 0 <= sec and sec < 60: self.178 19 Objektorientierte Programmierung def set_Clock(self.hour = h else: raise TypeError("Stunden müssen Ganzzahlen zwischen 0 und 23 sein!") if type(min) == int and 0 <= min and min < 60: self.minute. sec): """ Die Parameter h.h.59. min. h. um ein Objekt der Klasse Clock in einen String zu wandeln. min.hour.tick() >>> print(x) 13:00:00 .h. sec müssen Ganzzahlen sein.format(self. werden um eine Sekunde weitergerechnet. um ein Objekt der Klasse Clock auszugeben.

in <module> File "clock.18 Mehrfachvererbung 179 >>> x.hour = 0 else: self.py 12:59:59 13:00:00 <class 'str'> Was passiert.45. in <module> File "clock. in __init__ .19.minute = 0 if self. erhält man folgende Ausgabe: $ python3 clock.py".minute == 59: self.set_Clock(h.59) print(x) x.17) Traceback (most recent call last): File "<stdin>".tick() >>> print(x) 13:00:01 """ if self. line 1.py". line 18.second = 0 if self. die die Zahl 59 übersteigt? Wir wollen diese und andere Fehlerfälle in der folgenden interaktiven Python-Shell-Sitzung testen: >>> from clock import Clock >>> x = Clock(7. in set_Clock raise TypeError("Stunden müssen Ganzzahlen zwischen 0 und 23 sein!") TypeError: Stunden müssen Ganzzahlen zwischen 0 und 23 sein! >>> x = Clock(24.second += 1 if __name__ == "__main__": x = Clock(12.minute += 1 else: self.7.45. line 32.59.17) Traceback (most recent call last): File "<stdin>".py".sec) File "clock.min. wenn jemand statt Ganzzahlen Fließkommazahlen oder Strings eintippt? Oder falls jemand eine Minutenzahl eingibt.second == 59: self. in __init__ self. line 18.hour += 1 else: self. line 1.hour == 23: self.tick() print(x) y = str(x) print(type(y)) Ruft man das Modul clock standalone auf.

28. und nach dem 31. nach dem 30."17") Traceback (most recent call last): File "<stdin>".31.min.31.31. Auch bei der Schaltjahrberechnung können wir von bereits getaner Arbeit profitieren: Die Aufgabenstellung und die Beschreibung. die eine Uhrzeitfunktion mit Kalenderfunktion kombiniert."60". also z. in set_Clock raise TypeError("Stunden müssen Ganzzahlen zwischen 0 und 23 sein!") TypeError: Stunden müssen Ganzzahlen zwischen 0 und 23 sein! >>> x = Clock(23. Ein Kalenderdatum kann auf ein bestimmtes Datum gesetzt werden oder kann um einen Tag weitergeschaltet werden. in __init__ self.17) Traceback (most recent call last): File "<stdin>".31. Apropos Februar. um den Kalender weiterzubewegen oder „weiterzublättern”. in <module> TypeError: __init__() takes exactly 4 arguments (3 given) >>> Unser Ziel ist ja eine Klasse „CalendarClock”. """ Die Klasse Calendar implementiert einen Kalender.60.31] . April kommt der 1. in <module> File "clock. line 18.py".py". Wir nennen diese Methode „advance”. wie man Schaltjahre ermittelt. Dabei müssen wir die Anzahl der Tage für die bestimmten Monate berücksichtigen.py". in <module> File "clock. in set_Clock raise TypeError("Minuten müssen Ganzzahlen zwischen 0 und 59 sein!") TypeError: Minuten müssen Ganzzahlen zwischen 0 und 59 sein! >>> x = Clock("23". die . line 36.set_Clock(h. Mai.sec) File "clock.min. line 1.30.B. line 32.sec) File "clock. Ähnlich wie die tickMethode bei der Clock-Klasse brauchen wir auch bei der Calendar-Klasse eine Methode. """ class Calendar(object): months = [31. line 1.set_Clock(h. line 18. in set_Clock raise TypeError("Stunden müssen Ganzzahlen zwischen 0 und 23 sein!") TypeError: Stunden müssen Ganzzahlen zwischen 0 und 23 sein! >>> x = Clock(23. line 32.180 19 Objektorientierte Programmierung self. Dazu benötigen wir noch eine Klasse „Calendar”.17) Traceback (most recent call last): File "<stdin>". Die dazugehörige Lösung befindet sich auf Seite 383). Für die Anzahl der Monate benutzen wir eine Liste als Klassenattribut. hier haben wir ein weiteres Problem.30. Januar kommt der 1. Februar.30.py".sec) File "clock.31.py". line 1. Sie zählt zu einem gegebenen Kalenderdatum einen Tag hinzu. In unserer Klasse implementieren wir diese Funktionalität unter dem Namen „leapyear” als Klassenmethode. ob es sich um ein Datum in einem Schaltjahr handelt oder nicht. in __init__ self. befindet sich auf der Seite 58. denn wir müssen nun wissen.min.30.set_Clock(h.

m. um ein Objekt der Klasse Calendar auszugeben. y have to be integer values and year has to be a four digit year number """ if type(d) == int and type(m) == int and type(y) == int: self. """ if jahr % 4 == 0: if jahr % 100 == 0: if jahr % 400 == 0: schaltjahr = True else: schaltjahr = False else: schaltjahr = True else: schaltjahr = False return schaltjahr def __init__(self. y müssen ganze Zahlen sein!") def __str__(self): """ Diese Methode überlädt die eingebaute Funktion str(). d.18 Mehrfachvererbung 181 def leapyear(jahr): """ Die Methode leapyear liefert True zurück.month = m self.day = d self. """ .set_Calendar(d. und False. es wird eine Methode zur Verfügung gestellt. y): """ d. Die Methode __str__ wird auch von der Print-Funktion genutzt. m. um ein Objekt der Klasse Calendar in einen String zu wandeln. m. m. m. d. m.y) def set_Calendar(self. d.h. wenn nicht.19.year = y else: raise TypeError("d. y): """ d. y have to be integer values and year has to be a four digit year number """ self. wenn jahr ein Schaltjahr ist.

end=" ") x.2012) print(x. aber nicht durch 400 teilbar:") x = Calendar(28. end=" ") x.advance() print("nach advance: ".leapyear(self.182 19 Objektorientierte Programmierung return "{0:02d}.advance() print("nach advance: ". end=" ") x.{1:02d}.year += 1 else: self. weil die Zahl durch 400 teilbar ist :") x = Calendar(28.month == 12: self.year) def advance(self): """ setzt den Kalender auf den nächsten Tag unter Berücksichtigung von Schaltjahren """ max_days = Calendar.2. x) print("1900 war kein Schaltjahr: Zahl durch 100.day= 1 if self. self.month += 1 else: self.month.advance() print("nach advance: ".month = 1 self.year): max_days += 1 if self.2. x) x = Calendar(28.advance() print("nach advance: ".2013) print(x.day += 1 if __name__ == "__main__": x = Calendar(31.2. x) print("2000 war ein Schaltjahr.2.2000) print(x. self.month-1] if self.12. end=" ") x.day.2012) print(x.{2:4d}".months[self. x) . x) print("2012 war ein Schaltjahr:") x = Calendar(28.month == 2 and Calendar.day == max_days: self.1900) print(x.advance() print("nach advance: ". end=" ") x.format(self.

die eine Uhr mit integriertem Kalender repräsentiert. Man kann diese jedoch nicht mit self. line 1. y müssen ganze Zahlen sein! >>> x = Calendar(12.2012 nach advance: 01.2012) >>> x = Calendar("31". """ from clock import Clock from calendar import Calendar class CalendarClock(Clock.12. Calendar): """ Die Klasse CalendarClock implementiert eine Uhr mit integrierter Kalenderfunktion.12. aber nicht durch 400 teilbar: 28. line 47. .advance() aufgerufen werden.01.02.py 31.1900 nach advance: 01. in set_Calendar raise TypeError("d. m.2000 nach advance: 29.advance(self) möglich und richtig. Der Aufruf erfolgt deshalb mit Clock.2013 1900 war kein Schaltjahr: Zahl durch 100.2012) Traceback (most recent call last): File "<stdin>".tick() aufrufen.02.02.1900 2000 war ein Schaltjahr. da dies die tick-Methode von CalendarClock repräsentiert. Die Methode tick von Clock wird von CalendarClock überschrieben. y müssen ganze Zahlen sein!") TypeError: d. line 1.y) File "calendar.19. wenn man es selbständig startet: $ python3 calendar.2013 nach advance: 01.2012) Traceback (most recent call last): File "<stdin>". Die advance-Methode von Calendar kann jedoch direkt mit self.tick(self).2012 nach advance: 29. Wir testen die Fehlerfälle in der interaktiven Python-Shell: >>> from calendar import Calendar >>> x = Calendar(31.02. eine Klasse CalendarClock zu implementieren. Natürlich wäre der Aufruf auch mit Calendar. """ Modul. in __init__ self.02.2000 In unserem Test haben wir keine Fehlertests eingebaut.py". m.02. wenn einer der Werte für das Datum keine Ganzzahl ist.py". Die Klasse CalendarClock erbt von der Klasse Clock und der Klasse Calendar.03.18 Mehrfachvererbung 183 Obiges Skript liefert folgende Ausgabe.m.12. line 34.2013 2012 war ein Schaltjahr: 28.2012 28. das die Klasse CalendarClock implementiert. Wir sehen aber im Code der Methode set_Calendar.03. dass wir einen Fehler erheben.set_Calendar(d. weil die Zahl durch 400 teilbar ist: 28. Die neue tick-Methode muss jedoch auf die tick-Methode von Clock zugreifen. in <module> TypeError: __init__() takes exactly 4 arguments (3 given) >>> Nun geht es darum. in <module> File "calendar.

self.{1:02d}. year. self.format(self.hour.23.year. der Kalender wird. self. month.hour < previous_hour): self. year) def tick(self): """ Die Position der Uhr wird um eine Sekunde weiterbewegt.day.minute.second) return s if __name__ == "__main__": x = CalendarClock(31. month. """ def __init__(self.day. Zur Initialisierung des Kalenders wird der Konstruktor der Calendar-Klasse aufgerufen.{2:4d}". self.184 19 Objektorientierte Programmierung Die Klasse erbt sowohl von der Klasse Clock als auch von der Klasse Calendar. hour. self.tick(self) if (self.day.hour Clock. minute.59.__init__(self. second """ Clock. self. CalendarClock enthält dann die vereinigten Attribute der Clock. self.year) s += " " + "{0:02d}:{1:02d}:{2:02d}".advance() def __str__(self): """ Erzeugt die Stringdarstellung eines CalendarClock-Objekts """ s = "{0:02d}.day.month.month.12.und Calendar-Klasse: self. um einen Tag weiterbewegt. self.format(self. """ previous_hour = self. minute.hour.59) . falls Mitternacht überschritten wird. second): """ Zur Initialisierung der Uhrzeit wird der Konstruktor der ClockKlasse aufgerufen. second) Calendar. self.2013.minute.hour.__init__(self.

02.tick() print("to ".2014 01.02. Betrachten wir die folgende Python-Funktion: def f(x.2000 23:59:59 One tick from 07. end=" ") x.40) print("One tick from ".2000 07.3.02. erhält man folgende Ausgabe. x.py One tick from 31.2000.2013 23:59:59 One tick from 28.02. end=" ") x.02.tick() print("to ".13. die gleichzeitig auch die Arbeitsweise nochmals ein wenig erklärt: $ python3 calendar_clock.23. Polymorphismus bezeichnet bei Methoden die Möglichkeit.2. x) x = CalendarClock(28. x) Ruft man obiges Modul standalone auf.59) print("One tick from ".tick() print("to ".2.19.x. 43.19 Polymorphie 185 print("One tick from ".x.01.19 Polymorphie Ein wesentliches Konzept der objektorientierten Programmierung stellt die Polymorphie dar.0. y) f(42.59) print("One tick from ".59. y): print("values: ". end=" ") x. x) x = CalendarClock(28.2013 00:00:00 00:00:00 00:00:00 13:55:41 19.2. worauf wir im nächsten Abschnitt eingehen.03.23. Der Wort Polymorphie oder Polymorphismus stammt aus dem griechischen und bedeutet Vielgestaltigkeit.x. Man spricht dann vom Überladen von Methoden.12.1900 29.tick() print("to ". x) x = CalendarClock(7.1900.9) .55. 43. end=" ") x.x.2013 13:55:40 to to to to 01. Methoden und Funktionen in Python haben bereits eine implizite Polymorphie wegen des dynamischen Typkonzepts von Python.2013. dass man bei gleichem Namen Methoden mit verschiedenen Parametern aufrufen kann.59.7) f(42.43) f(42. In Python kann man auch Operatoren und Standardfunktionen überladen.43) f(42.1900 23:59:59 One tick from 28.

5)) values: [3. print("values: ".4. line 1 f({2. f(42.3.9}. die sich mittels print drucken lassen: >>> def f(x. 6] (3. In getypten Programmiersprachen wie C++ müssten wir entsprechend dieser Typ-Paarungen f in vier Varianten definieren.4. "with Strings")) values: A String ('A tuple'. 43."b":7.9).3. könnte wie folgt aussehen: #include <iostream> using namespace std. 'with Strings') >>> f({2.4.9}.5. dann (float. " << x << endl. "c"=9.04.8. 5) >>> f("A String". } Bei der Funktion f unseres Python-Programms ist der Polymorphismus nicht nur auf Integer."b"=7. Ein C++-Programm. double y ) { cout << "values: " << x << ". ("A tuple". f(42.8. int y ) { cout << "values: " << x << ". 'b': 7. 5. " << x << endl. } void f(double x. {"a"=3. int) und im vierten Aufruf mit (float. " << x << endl.(3. double y ) { cout << "values: " << x << ". f(42. x. float).3. Beim ersten Aufruf mit (int.6]."b"=7. "c"=9.04}) values: {9.9}.und Float-Werte beschränkt.04}) ^ SyntaxError: invalid syntax >>> f({2. } int main() { f(42.3.4. {"a":3. 3} {'a': 3. } void f(double x.04}) File "<stdin>". das dem obigen Python-Programm entspricht.y): . 43. 43). " << x << endl. int). float). dann mit (int. void f(int x. >>> f([3. "c":9. } void f(int x.. Wir können die Funktion auf alle Typen und Klassen anwenden. 2.186 19 Objektorientierte Programmierung Die Funktion f rufen wir mit verschiedenen Typ-Paarungen auf.8} >>> .. y) . 'c': 9.0.43).8.. {"a"=3. int y ) { cout << "values: " << x << ".7)..

Für „+” lautet der Name der Methode beispielsweise __add__.19. und für „-” lautet der Name __sub__.__and__(self.20 Operator-Überladung Die Parameterüberladung ist uns bereits häufig im Laufe dieses Buches begegnet. other) object. modulo]) object.__rshift__(self. Steht in einem Skript x+y und sind x und y von der Klasse K. also Float. other) object.__mul__(self. other[. other) % ** « » & . Für jedes Operatorzeichen gibt es eine spezielle Methode.__floordiv__(self. other) object. dass wir auch für eigene Klassen den „+”-Operator überladen können.und Integerwerten. aber auch für die Konkatenation von Strings benutzt: >>> a = 3 + 4 >>> a 7 >>> 3 + 5. in <module> TypeError: unsupported operand type(s) for +: 'K' and 'K' Binäre Operatoren: Operator + * // / Methode object.__div__(self. weshalb die Methoden auch zwei Parameter benötigen: „self” und „other”.__add__(self. other) object.__lshift__(self. Bei __add__ und __sub__ handelt es sich um binäre Operatoren. Um dies tun zu können. Wir haben beispielsweise das Plus-Zeichen „+” sowohl für die Addition von verschiedenen numerischen Werten.__pow__(self. müssen wir jedoch den internen Mechanismus verstehen. other) object. falls es eine solche Methode in der Klasse K gibt.__mod__(self. ansonsten erfolgt die Fehlermeldung Traceback (most recent call last): File "<stdin>". dann ruft Python die Methode __add__ mit x . other) object. line 1.543 >>> s = "Hello" >>> print(s + " World") Hello World >>> BILD 19.__ad d __( y ) auf.__sub__(self.543 8.20 Operator-Überladung 187 19.10 Überladen des +-Operators Python erlaubt es auch. ohne dass es uns vielleicht bewusst war. other) object. der die Überladung bewirkt. other) object.

__ilshift__(self. um neue Klassen abzuleiten.__xor__(self. dict oder list als Basisklasse verwenden. other) object. other) object.__ifloordiv__(self.__complex__(self) object.__idiv__(self.__hex__(self complex() int() long() float() oct() hex() 19. other) %= **= «= »= &= ^= |= Unäre Operatoren: Operator + abs() ~ Methode object.21 Standardklassen als Basisklassen Statt selbstdefinierter Klassen kann man auch Standardklassen wie beispielsweise int.__iand__(self.__iadd__(self. other) object.__float__(self) object. other) object. other) object.__abs__(self) object.__long__(self) object.__or__(self. Man kann beispielsweise zusätzliche Methoden für Standardklassen definieren. other) object.__imod__(self.__neg__(self) object. other) object.__irshift__(self.__invert__(self) object. other[. other) object.__ixor__(self. float.188 19 Objektorientierte Programmierung Operator ^ | Methode object.__ior__(self.__oct__(self) object. modulo]) object.__imul__(self. other) object.__ipow__(self. other) object.__isub__(self.__int__(self) object. . other) Erweiterte Zuweisungen: Operator += -= *= /= //= Methode object. other) object.__pos__(self) object.

in anderen Programmiersprachen. Uns interessiert nicht das Aussehen und die Beschaffenheit dieses Roboters.append(item) if __name__ == "__main__": x = Plist([3. Diese Landschaft soll zweidimensional sein. die genau das Gleiche macht wie append: class Plist(list): def __init__(self.push(47) print(x) 19.__init__(self. l) def push(self. BILD 19.19. d. Wir wollen im Folgenden Beispiel die Klasse „list” um eine Methode „push” erweitern. im Englischen stack deutsch: einkellern deutsch: auskellern . Sie kann durch ein Koordinatensystem beschrieben werden.22 Aufgaben 189 Die Verarbeitung von Stapelspeichern5 wird in Python.11 Roboter 5 6 7 auch Kellerspeicher genannt.h. Wir interessieren uns lediglich für seine Position in einer imaginären „Landschaft”. mittels append und pop realisiert. wie wir gesehen haben. l): list.22 1. item): self. Üblicherweise.4]) x. Aufgabe: Aufgaben In dieser Aufgabe geht es um eine Roboterklasse. werden meistens die Funktionen push6 und pop7 verwendet.

| | Falls eine unbekannte Orientierung übergeben wird. Wir brauchen also noch ein Attribut mit dieser Orientierung.east'' | und ist beispielsweise [3. Die genaue Beschreibung der benötigten Methoden können Sie der folgenden helpBeschreibung entnehmen: Help on module robot: NAME robot DESCRIPTION Roboterklasse zur Positionsbeschreibung und Veränderung von Objekten in einem zweidimensionalen Koordinatensystem CLASSES builtins. | | move(self. „east” oder „north” orientiert. Der Roboter ist in eine der vier Richtungen „west”. wird der | Roboter nicht bewegt. | | getPosition(self) | Liefert eine 2er-Liste mit [x.getPosition() == .4]. | | newOrientation(self. wobei dann 3 der x-Position und 4 der y-Position entspricht. „south”. dann bewegt er sich 10 Felder östlich und befindet | sich anschließend in Position [3.object Robot class Robot(builtins. also eine der Richtungen | "west".move(10) aufgerufen und ist dieser | Roboter östlich orientiert. "south".getOrientation() für einen Roboter x liefert | dessen aktuelle Orientierung zurück. distance) | Methode zum Bewegen eines Roboters in Richtung seiner | aktuellen Orientierung. die die x.object) | Methods defined here: | | __init__(self. diese Informationen in einer 2er-Liste zusammenzufassen.und die y-Koordinate darstellen. also x.190 19 Objektorientierte Programmierung Ein Roboter unserer Klasse hat also zwei Attribute.17]. name='marvin') | | __str__(self) | Stringdarstellung einer Instanz | | getName(self) | Liefert den Namen des Roboters zurück | | getOrientation(self) | Ein Aufruf von x. Außerdem können wir noch ein weiteres Attribut mit dem Namen des Roboters definieren. x=0. "east" oder "north". orientation='north'.y] zurück. y=0. also beispielsweise position = [3. | | Wird ein Roboter x mit x.7] die aktuelle Position des | Roboters. o) . Es empfiehlt sich natürlich..

Aber es gibt auch eine Berufsgruppe."south".oder Bierdeckelarithmetik: Üblicherweise zählen und rechnen wir im Dezimalsystem. In der folgenden Aufgabe geht es BILD 19. Seite 400 2. o has to be in {"north". in dem lediglich eine Ziffer vorhanden ist. wie unsere in Höhlen lebenden Vorfahren mit Zahlen umgegangen sind.12 Neandertal-Arithmetik um die Bierdeckelnotation oder auch Bierdeckelarithmetik.py (END) Lösung: 1. die man üblicherweise mit einem senkrechten Strich bezeichnet."east"} rename(self. Informatiker und Programmierer haben manchmal auch Kontakt mit dem Binärsystem. in der Gastronomie. name) Damit kann man dem Roboter einen neuen Namen geben. ---------------------------------------------------------------Data descriptors defined here: __dict__ dictionary for instance variables (if defined) __weakref__ list of weak references to the object (if defined) FILE /home/data/bodenseo/python/beispiele/robot. setPosition(self. pos) Damit kann man den Roboter auf eine neue Position im Koordinatensystem positionieren.19. Aufgabe. Aufgabe: Neanderthal. Es könnte auch die Art gewesen sein. Ja richtig. pos muss eine Liste oder ein Tupel mit zwei Elementen sein Ansonsten wird nichts getan. die von Berufs wegen mit einem unären Zahlsystem rechnet.22 Aufgaben 191 | | | | | | | | | | | | | | | | | | | | | | | Mit der Methode newOrientation ändern wir die Orientierung des Roboters. Also der Strich auf dem ."west". Das Unärsystem ist ein Zahlensystem.

Auch wenn die Höhlenmenschen keine Null kannten. Seite 403 3. definieren wir die Subtraktion wie folgt: x . replacement). mit der eine Folge von Elementen aus einer Liste gelöscht werden kann und durch eine Liste von anderen Elementen ersetzt wird. An die Stelle der gelöschten Elemente sollen die Elemente der Liste replacement eingefügt werden. Lösung: 3. ab dem die Elemente gelöscht werden sollen. die die vier Grundrechenarten für die Neandertalarithmetik definiert. Es gilt: 7d ezi mal = |||||||un är Schreiben Sie eine Klasse CaveInt. Aufgabe. „offset” entspricht dem ersten Index. Erweitern Sie nun die Klasse plist um eine Methode splice. Da es keine negativen Zahlen gibt. wenn x kleiner als y ist. Seite 404 . wie viele Elemente gelöscht werden sollen. splice(offset. definieren wir einen leeren String als die Null.y ist gleich dem leeren String. Aufgabe: Wir haben in diesem Kapitel die Standardklasse list um die Methode push erweitert.192 19 Objektorientierte Programmierung Bierdeckel. Außerdem soll eine Cast-Methode für die Wandlung von unär nach int bereitgestellt werden. length. eine Eins oder irgendein anderes Zeichen verwenden. Lösung: 2. In Perl gibt es noch die Methode „splice”. Man könnte aber ebenso gut eine Null. und der Parameter „length” gibt an. Aufgabe.

TEIL II Weiterführende Themen .

.

.und Code-Fehlern benötigt werden: Boehm.ÏEEE Computer.BILD 20. „I is learning Python” ist beispielsweise ein Syntaxfehler in der englischen Sprache. wurde schon vor mehr als 2000 Jahren von Cicero festgestellt.1 Dass Fehler menschlich seien. All dies sind sogenannte syntaktische Fehler oder Syntaxfehler. Auch wenn wir Fehler nie voll. Sein „errare humanum est”2 gilt häufig auch als Ausrede. Der Spruch stammt von Cicero und lautet in voller Länge: „Errare (Errasse) humanum est. sed in errare (errore) perseverare diabolicum. Die Zeit. September: 43-57. die wir machen. Während der Programmentwicklung gibt es immer wieder „kleine Fehler”. die Anzahl der Fehler. um unzureichende Arbeitsergebnisse zu entschuldigen. 1987.” In Deutsch lautet dies: „Irren ist menschlich. so zum Beispiel hinter einem „else”. die zur Fehlersuche und zum Testen eines Programms verwendet wird. Man spricht auch in natürlichen Sprachen von syntaktischen Fehlern. dass wir unseren weiterführenden Teil mit einem Kapitel über Fehler. also zum Beispiel 1 2 3 Boehm und Barry sprechen von 40 . häufig sind es kleine Tippfehler. Jones.20 20. die zum Beheben von Design. und vor allen diejenigen.1 Fehler sind menschlich ständig vermeiden werden können. . sollten wir danach trachten. die im Produkt bleiben könnten. 1986.3 Dabei handelt es sich um die Verletzung von Schreibweisen von einzelnen Wörtern. Studien sprechen von bis zu 50 %. Fehlersuche und Fehlervermeidung beginnen.50 %. Irgendwo fehlt immer mal ein Doppelpunkt. Tests und Fehlersuche gehören zum Alltag eines jeden Programmierers. Fast alle Programmiersprachen werden mittels kontextfreier Grammatiken syntaktisch beschrieben. Barry W.1 Tests und Fehler Einführung Es ist kein Zufall. Capers. ed.” Unter der Syntax einer Programmiersprache versteht man die Beschreibung der erlaubten Zeichenketten für Programme dieser Sprache. oder man hat vielleicht „true” statt True geschrieben. Es gibt unterschiedliche Fehlerarten. aber auf Irrtümern zu beharren ist teuflisch. Ïmproving Software Productivity. minimal zu halten. hat üblicherweise einen hohen Anteil an der Programmentwicklung.

print(i) . Das Codefragment ist syntaktisch korrekt. Es ist aber auch denkbar. dass der Text „So what?” nur ausgegeben werden sollte. Neben den syntaktischen Fehlern. wenn x größer als 10 ist und der Wert von y dem von x entspricht. sodass man im folgenden Satz von einem Semantikfehler ausgehen kann: „The man bites the dog!” .. die sich häufig relativ leicht finden und beheben lassen. aber sein Problem nicht richtig umgesetzt.5 Betrachten wir folgenden Programmausschnitt: x = int(input("x? ")) y = int(input("y? ")) if x > 10: if y == x: print("Fine") else: print("So what?") Es gibt zwei if-Anweisungen. Programmfragmente sind syntaktisch korrekt. also zum Beispiel der vergessene Doppelpunkt hinter dem „else” oder eckige statt runder Klammern bei einem Funktionsaufruf. Es könnte aber sein. Aber einer von beiden verstößt gegen die intendierte Semantik. dass er folgenden Code hätte schreiben müssen: x = int(input("x? ")) y = int(input("y? ")) if x > 10: if y == x: print("Fine") else: print("So what?") Beide Programme bzw. Der Programmierer hatte wahrscheinlich die Semantik der if-Anweisung korrekt verstanden. wenn x größer als 10 ist und der Wert von y dem von x entspricht.. gibt es auch die semantischen Fehler. 0 1 2 4 5 englisch: key words Die Bedeutung der einzelnen Sprachkonstrukte einer Sprache wird als die Semantik einer Programmiersprache bezeichnet..196 20 Tests und Fehler Schlüsselwörtern4 oder von Strukturregeln. Das bedeutet. dass ein Programmierer die Semantik eines Python-Konstrukts nicht richtig verstanden und deshalb einen Fehler produziert hat.. dass der Schreiber des Programmes den Text „So what?” nur ausgeben wollte. Normalerweise beißen Männer keine Hunde. aber nur eine else-Anweisungen. Betrachten wir hierzu das folgende Beispiel: >>> for i in range(7): . In der Linguistik würde man das als Satzbauregeln bezeichnen.

Niemand kann beispielsweise ein Betriebssystem vollständig auf Korrektheit prüfen. da wir ja nicht die Problemstellung kennen. Dies ist auf einem umfassenden Software-Paket in der Regel nicht mehr möglich. Modultests verwendet man in der Software-Entwicklung. Er ging irrtümlich davon aus. ■ 20. überschaubare Komplexität zeigen und die Schnittstellen BILD 20. 1. gespeichert unter „abc. dass range(7) die Zahlen von 1 bis 7 produziere. 6 und 7. d. Nehmen wir an. dass er die range-Funktion nicht richtig verstanden hat. Fehler. Häufig kann man so ein Modul vollständig auf Korrektheit prüfen. können wir nicht entscheiden. Ob sie jedoch semantisch korrekt sind. 4. also funktionale Einzelteile eines Programmes zu testen. ob sie die geforderte Funktionalität bringen.2 Modultests Für den Begriff Modultest oder Komponententest wird häufig im Deutschen der englische Begriff „Unittest” („unit test”) verwendet.2 Modultests 197 3 4 5 6 >>> Aus der Tatsache. dass der Programmierer die Zahlen von 1 bis 10 hatte ausgeben wollen. Wird die- . wir haben ein Modul mit dem Namen „abc”.2 Testen und Messen noch klar definiert sind. man prüft. Wir können also die Semantikfehler in zwei Gruppen unterteilen: ■ Fehler. d.3 Modultests unter Benutzung von __name__ Jedes Python-Modul hat einen im built-in-Attribut __name__ definierten Namen. In diesem Fall hat er einen semantischen Fehler begangen. 5. um Module. 3. ersehen wir. 20.h. da die dortigen Funktionalitäten noch eine begrenzte bzw. Nehmen wir an. die aus dem mangelnden Verständnis eines Sprachkonstrukts herrühren. der wohl daraus resultiert.py”. Es empfiehlt sich. die aus der fehlerhaften Umsetzung des Problems resultieren. dass diese Anweisungen syntaktisch korrekt sind. 2.20. dass es keinen Fehler bei der Ausführung gab.h. Tests auf Modulebene durchzuführen.

py". 1. 2. Anhand des folgenden Moduls (das sowohl eine einzelne Fibonacci-Zahl für eine bestimmte Generation n als auch die Liste der Fibonacci-Zahlen bis zu einer Generation n berechnen kann) wollen wir veranschaulichen.5) Traceback (most recent call last): File "<stdin>". 55] >>> fiblist(-8) [0. line 6. wie man mit dem built-in-Attribut __name__ einen einfachen. 13.py. line 1. Das fibonacci-Modul sieht wie folgt aus und ist unter dem Namen fibonacci.n): fib += [fib[-1]+fib[-2]] return fib Natürlich kann man dieses Modul auch „manuell” in der interaktiven Python-Shell testen: >>> from fibonacci import fib. 3. in <module> File "fibonacci.py in unserem Beispielverzeichnis zu finden: """ Modul mit wichtigen Funktionen zur Fibonacci-Folge """ def fib(n): """ Die Fibonacci-Zahl für die n-te Generation wird iterativ berechnet """ a. 8. b = 0. 1] >>> fib(-1) 0 >>> fib(0. 1 for i in range(n): a. 1.1] for i in range(1. b = b. 5. also mittels $python3 abc.198 20 Tests und Fehler ses Modul mit „import abc” importiert. 34. in fib for i in range(n): TypeError: 'float' object cannot be interpreted as an integer >>> . dann hat das built-in-Attribut __name__ den Wert „abc”. 21. aber sehr wirkungsvollen Modultest durchführen kann. Wird abc als eigenständiges Programm aufgerufen. fiblist >>> fib(0) 0 >>> fib(1) 1 >>> fib(10) 55 >>> fiblist(10) [0. a + b return a def fiblist(n): """ produziert die Liste der Fibbo-Zahlen bis zur n-ten Generation """ fib = [0. dann hat diese Variable den Wert ’__main__’.

py fib-Funktion liefert fehlerhafte Werte Dieses Vorgehen hat jedoch einen entscheidenden Nachteil. Man könnte also unser Modul direkt um eine oder mehrere if-Anweisungen erweitern: if fib(0) == 0 and fib(10) == 55 and fib(50) == 12586269025: print("Test für fib-Funktion erfolgreich") else: print("fib-Funktion liefert fehlerhafte Werte") Ruft man das Programm dann direkt auf. aber um eins versetzt. weil range nicht für Float-Werte definiert ist. 1 um.3 Modultests unter Benutzung von __name__ 199 Wir sehen.1] zurückliefert. Für negative ganze Zahlen liefert die Funktion fib nur Nullen zurück. b = 0. . dass die Tests nur gestartet werden. ob die Aufrufe für fib() und fiblist() für bestimmte Werte definierte Ergebniswerte zurückliefern. Wird unser Modul direkt gestartet. gibt es einen TypeError. erhält man folgende Ausgabe: $ python3 fibonacci. Die Lösung für dieses Problem stellt das eingangs erwähnte built-in-Attribut __name__ dar. indem wir testen. also nicht importiert. Dazu ändern wir die Zeile a. Wollen wir den n-ten Wert (für n größer als 0 berechnen). Wir können unser Modul nun so umschreiben. wenn das Modul direkt gestartet wird: 6 Im Prinzip liefert fib zwar noch die Fibonacci-Werte.py Test für fib-Funktion erfolgreich Nun wollen wir bewusst einen Fehler in unsere fib-Funktion einbauen. hat __name__ den Wert „__main__”. wenn Module solche Meldungen beim import ausgeben.20. Wenn man das Modul importiert. Module sollen sich „schweigend” laden lassen. b = 1.6 Ein Aufruf des veränderten Moduls liefert nun eine Fehlermeldung: $ python3 fibonacci. 1 in a. so müssen wir fib(n-1) aufrufen. während fiblist nur die Liste [0. Unser Modul könnten wir testen. Ruft man die Funktionen mit Float-Zahlen auf. wird auch das Ergebnis dieses oder ähnlicher Tests angezeigt: >>> import fibonacci Test für fib-Funktion erfolgreich Es ist aber störend und auch nicht üblich. dass die Funktionen auf Integer-Zahlen definiert sind.

Diese Methode ist die einfachste und am weitesten verbreitetste Methode für Modultests. im Docstring. b = 0. b = 0. a + b return a def fiblist(n): """ produziert Liste der Fibbo-Zahlen """ fib = [0. b = b. wie der Name vermuten lässt. Dann kopiert man einen Auszug aus einer interaktiven Sitzung in den Docstring einer Funktion. a + b return a .1] for i in range(1. Modultests durchzuführen. Im Folgenden zeigen wir das Vorgehen an einem simplen Beispiel. Vorgehensweise: Man muss das Modul „doctest” importieren.n): fib += [fib[-1]+fib[-2]] return fib if __name__ == "__main__": if fib(0) == 0 and fib(10) == 55 and fib(50) == 12586269025: print("Test für fib-Funktion erfolgreich") else: print("fib-Funktion liefert fehlerhafte Werte") Nun gibt es keine Ausgaben. Dazu haben wir das vorige fibonacci-Modul bis auf die Funktion fib abgespeckt: import doctest def fib(n): """ Die Fibonacci-Zahl für die n-te Generation wird iterativ berechnet """ a. 20. Der eigentliche Test befindet sich bei dieser Methode. wenn das Modul importiert wird. 1 for i in range(n): a.4 doctest-Modul Das doctest-Modul stellt eine weitere einfache Methode dar. 1 for i in range(n): a. und zwar weder im Fehlerfall noch im Erfolgsfall. b = b.200 20 Tests und Fehler """ Modul mit wichtigen Funktionen zur Fibonacci-Folge """ def fib(n): """ Iterative Fibonacci-Funktion """ a.

Damit das Modul doctest aktiv wird.4 doctest-Modul 201 Dieses Modul rufen wir nun in einer interaktiven Python-Shell auf und lassen ein paar Werte berechnen: >>> >>> 0 >>> 1 >>> 55 >>> 610 >>> from fibonacci import fib fib(0) fib(1) fib(10) fib(15) Diese Aufrufe mit den Ergebnissen kopieren wir aus der interaktiven Shell in den Docstring unserer Funktion. b = 0.testmod() Starten wir obiges Modul direkt mit dem Aufruf $ python3 fibonacci_doctest. b = b. Das vollständige Modul sieht nun wie folgt aus: import doctest def fib(n): """ Die Fibonacci-Zahl für die n-te Generation wird iterativ berechnet >>> 0 >>> 1 >>> 55 >>> 610 >>> fib(0) fib(1) fib(10) fib(15) """ a. a + b return a if __name__ == "__main__": doctest.py erhalten wir keine Ausgabe. 1 for i in range(n): a. weil alles okay ist. . Dies können wir wie üblich mit einem Test des Attributs __name__ auf den Wert „__main__” machen. falls das Modul direkt aufgerufen wird. müssen wir die Methode testmod() starten.20.

1 um.fib Failed example: fib(15) Expected: 610 Got: 987 ********************************************************************** 1 items had failures: 3 of 4 in __main__. line 14. b = 0. 20. also der korrekte Wert. Hinter „Expected:” folgt der erwartete Wert. in __main__.5 Testgetriebene Entwicklung Im vorigen Kapitel hatten wir bereits eine fertig geschriebene Fibonacci-Funktion. in __main__. und hinter „Got:” folgt der von der Funktion produzierte Ausdruck. Wir sehen jeweils den Beispielaufruf hinter der Zeile „Failed example:”. b = 1. also der Wert.py ********************************************************************** File "fibonacci_doctest. in __main__. Man kann auch so vorgehen.fib Failed example: fib(10) Expected: 55 Got: 89 ********************************************************************** File "fibonacci_doctest.py".py". line 8.fib Test Failed *** *** 3 failures.fib Failed example: fib(0) Expected: 0 Got: 1 ********************************************************************** File "fibonacci_doctest. 1 in a. die ein fehlerhaftes Ergebnis geliefert haben. Dazu ändern wir wieder die Zeile a. dass man bereits am Anfang Ergebnisse in den Docstring schreibt . Es werden alle Aufrufe angezeigt. Nun erhalten wir folgende Ausgabe beim direkten Start des Moduls: $ python3 fibonacci_doctest.py". den doctest beim Aufruf von fib erhalten hat.202 20 Tests und Fehler Deshalb bauen wir wieder einen kleinen Fehler ein. line 12.

py".testmod() fib(0) fib(1) fib(10) fib(15) Es versteht sich von selbst. Im Folgenden haben wir den Rückgabewert der Funktion fib fest auf 0 gesetzt: import doctest def fib(n): """ Die Fibonacci-Zahl für die n-te Generation wird iterativ berechnet >>> 0 >>> 1 >>> 55 >>> 610 >>> """ return 0 if __name__ == "__main__": doctest.py".20. dass ein Test dieses Moduls außer für fib(0) nur Fehler liefert: $ python3 fibonacci_TDD.fib Failed example: fib(1) Expected: 1 Got: 0 ********************************************************************** File "fibonacci_TDD. line 14. in __main__.fib Failed example: fib(15) Expected: 610 . in __main__. line 12. in __main__.5 Testgetriebene Entwicklung oder „Im Anfang war der Test” 203 und die Funktion dann erst entwickelt. line 10.py".fib Failed example: fib(10) Expected: 55 Got: 0 ********************************************************************** File "fibonacci_TDD.py ********************************************************************** File "fibonacci_TDD.

er muss jedoch mit test beginnen.assertEqual(fib(0). dass die Programmdokumentation und die Testbeschreibungen voneinander getrennt sind.6 unittest Für das Modul „unittest” standen JUnit7 von Erich Gamma und SUnit8 von Kent Beck Pate. das von Kent Beck erfunden wurde. ob der Ausdruck „first” gleich dem Ausdruck „second” ist. Wichtig ist lediglich. d. Man ändert bzw. das für automatisierte UnitTests von einzelnen Klassen und Methoden besonders geeignet ist SUnit ist ein Smalltalk-Testframework. Der Preis dafür besteht besteht jedoch in einem erhöhten Aufwand für die Erstellung der Tests. In unserer Methode „testCalculation” benutzen wir die Methode assertEqual der Klasse TestCase. Dieses Vorgehen ist eine Methode der Software-Entwicklung. msg = None) prüft. Der Name dieser Methoden ist beliebig. SUnit wurde auf Java unter dem Namen JUnit portiert. Der Name kann beliebig gewählt sein.fib ***Test Failed*** 3 failures.py einen Test mit unittest erstellen. Ein deutlicher Unterschied zum Modul doctest besteht darin. 0) 7 8 9 Dabei handelt es sich um ein Framework zum Testen von Java-Programmen. Wie immer in der SWBranche werden auch häufig nur die englischen Begriffe benutzt. d. die von unittest. „test first development” oder noch geläufiger „test-driven development” (TDD). dass die Testfälle bei dem Modul „unittest” außerhalb des eigentlichen Programmcodes definiert werden.h. also in unserem Fall fibonacci. 20. importieren.TestCase): def testCalculation(self): self. Außerdem müssen wir eine Klasse mit beliebigem Namen – wir wählen in unserem Beispiel „FibonacciTest” – erstellen.h.py9 müssen wir das Modul unittest und das zu testende Modul. import unittest from fibonacci import fib class FibonacciTest(unittest. wird msg ausgegeben. bis die Tests im Doctest „bestanden” werden. wenn msg ungleich None ist. dass der Testfall in einer separaten Datei steht. schreibt nun den eigentlichen Code der Funktion fib solange. In dieser Klasse werden die nötigen Testfälle in Methoden definiert. in einer eigenen Datei. die man als „Testgetriebene Entwicklung” oder auch „Testgesteuerte Entwicklung” bezeichnet. assertEqual(first. second.TestCase erbt. Falls die beiden Ausdrücke ungleich sind. . Der Vorteil besteht unter anderem darin.204 20 Tests und Fehler Got: 0 ********************************************************************** 1 items had failures: 3 of 4 in __main__. Wir wollen nun für unser Modul fibonacci. In einer Datei fibonacci_unittest.

py . 1) self. a + b . dass wir nur einen falschen Wert erhalten.main() Rufen wir obigen Testfall auf. 5) self.assertEqual(fib(1). erhalten wir folgende Ausgabe: $ python3 fibonacci_unittest.assertEqual(fib(0). b = 1.py F ====================================================================== FAIL: testCalculation (__main__.6 unittest 205 self. 1 um. ---------------------------------------------------------------------Ran 1 test in 0. was im Fehlerfall passiert. Wir verändern fib nun dahingehend. wenn n auf 20 gesetzt ist: def fib(n): """ Iterative Fibonacci-Funktion """ a.assertEqual(fib(10). Jetzt sieht der Test wie folgt aus: $ python3 fibonacci_unittest. 6765) if __name__ == "__main__": unittest. b = b. 55) self.assertEqual(fib(5). 1 for i in range(n): a. b = 0.py". Dazu ändern wir von neuem die Zeile a.000s OK Bei der normalen Programmentwicklung ist dies das von uns gewünschte Ergebnis. In diesem Fall wurden die weiteren assertEqual-Aufrufe nicht mehr ausgeführt.FibonacciTest) ---------------------------------------------------------------------Traceback (most recent call last): File "fibonacci_unittest. 0) AssertionError: 1 != 0 ---------------------------------------------------------------------Ran 1 test in 0.000s FAILED (failures=1) Bereits die erste Anweisung in testCalculation hat eine Ausnahme erzeugt. in testCalculation self. Hier sind wir allerdings interessiert. line 7. b = 0.20. Wir produzieren deshalb wieder unseren Fehler. 1 in a.assertEqual(fib(20).

0) self. mit der fremder Programmcode in eine bestehende Anwendung integriert werden kann.py". Wir stellen dazu einige wichtige Methoden dieser Klasse vor. allerdings generierten sie keine Ausnahme.und eine tearDown-Methode: import unittest from fibonacci import fib class FibonacciTest(unittest. die nichts tun. in testCalculation self. line 12. 5) 20.TestCase): def setUp(self): 10 Ein Hook (auch Einschubmethode) bezeichnet eine Schnittstelle. . da ihre Ergebnisse ja korrekt sind: self. 1) self.FibonacciTest) ---------------------------------------------------------------------Traceback (most recent call last): File "fibonacci_unittest. die dann in Unterklassen von Anwendern der Klasse nach eigenem Bedarf implementiert werden können.7 Methoden der Klasse TestCase Wir wollen nun näher auf die Klasse TestCase eingehen. Eine Klasse stellt leere Methoden – also Methoden.206 20 Tests und Fehler if n == 20: a = 42 return a Die Ausgabe eines Testlaufs sieht nun wie folgt aus: $ python3 fibonacci_unittest.py blabal F ====================================================================== FAIL: testCalculation (__main__.000s FAILED (failures=1) Jetzt wurden aber auch die folgenden Anweisungen durchgeführt.assertEqual(fib(0). wenn man sie aufruft – zur Verfügung.assertEqual(fib(20). In der objektorientierten Programmierung kann dies durch Vererbung geschehen. Wir erweitern unser voriges Beispiel um eine setUp.assertEqual(fib(5). Zunächst stellen wir die beiden Hook-Methoden10 setUp() und tearDown() vor.assertEqual(fib(1). 6765) AssertionError: 42 != 6765 ---------------------------------------------------------------------Ran 1 test in 0. Dadurch kann die Anwendung erweitert oder ihr Ablauf verändert werden.

first. Wird in der Methode setUp eine Ausnahme generiert. TABELLE 20. (1.fib_elems = ( (0. msg=None) . Ebenso wie bei setUp gilt. Die Methode tearDown wird nach dem Aufruf einer Testmethode gestartet. Sie wird vor jedem Aufruf der implementierten Testmethoden aufgerufen.py setUp executed! tearDown executed! .7 Methoden der Klasse TestCase 207 self. so wird diese auch als Error in der Testausgabe ausgegeben. Der Test schlägt fehl.val) in self. Dabei ist Gleichheit im Sinne von „==” gemeint. val) def tearDown(self): # Objekte können # in diesem Fall self. (3. (4.fib_elems: self.1). wenn die Parameter „first” und „second” nicht gleich sind. ---------------------------------------------------------------------Ran 1 test in 0. second.assertEqual(fib(i). Mit „msg” kann man eine zusätzliche Beschreibung für einen Fehler ausgeben.main() Ein Aufruf führt zu folgendem Ergebnis: $ python3 fibonacci_unittest2.0).3).1).1 Methoden der Klasse TestCase Methode setUp() Bedeutung Bei der Methode setUp handelt es sich um eine sogenannte Hook-Methode. (Fortsetzung nächste Seite) tearDown() assertEqual(self.5) ) print ("setUp executed!") def testCalculation(self): for (i. (5. (2.2). also Wertegleichheit und nicht nur reine Objektgleichheit.fib_elems = print ("tearDown gelöscht oder geändert werden macht es jedoch wenig Sinn: None executed!") if __name__ == "__main__": unittest.000s OK Die meisten der TestCase-Methoden verfügen über einen optionalen Parameter „msg”. Selbstverständlich wird auch bei einer Ausnahme im setUp-Code der Test abgebrochen.20. dass im Code von tearDown generierte Ausnahmen auch in der Testausgabe ausgegeben werden.

b. msg=None) assertFalse(self. Die Parameter „first” und „second” müssen hierbei sequentielle Datentypen sein. delta=None) Bedeutung Diese Methode schlägt fehl. msg=None) assertIs(self. Betrachtet die beiden Argumente als Dictionaries und prüft auf Gleichheit. ob a is b gilt. first. msg=None. Prüft. Es muss folgendes gelten: Alle Elemente müssen genauso oft in „first” wie in „second” vorkommen. Prüft. member. [0. a. ob a < b gilt. ob a in b gilt. expr1. delta=None) assertCountEqual(self. msg=None) assertIn(self. weil die 0 in der ersten Liste zweimal vorkommt und in der zweiten Liste nur einmal. a. Der Default-Wert für „places” ist 7. Prüft. Es muss folgendes gelten: Alle Elemente müssen genauso oft in „first” wie in „second” vorkommen. 1] gelten in obigem Sinne als gleich. Die Parameter „first” und „second” müssen hierbei sequentielle Datentypen sein. 0. msg=None) assertGreaterEqual(self. Prüft. b. 1] und [1. msg=None) assertAlmostEqual(self. ob der Ausdruck „expr” True ist. 1] und [1. nachdem man sie vor dem Vergleich auf „places” Nachkommastellen gerundet hatte. second. wenn die Differenz der beiden Parameter „first” und „second” gleich 0 ist. ob a <= b gilt. nachdem man sie vor dem Vergleich auf „places” Nachkommastellen gerundet hatte. second. ob a >= b gilt. Prüft. Diese Methode schlägt fehl.1 Methoden der Klasse TestCase (Fortsetzung) Methode assertAlmostEqual(self. places=None. weil die 0 in der ersten Liste zweimal vorkommt und in der zweiten Liste nur einmal. Beispiel: [0. places=None. Der Default-Wert für „places” ist 7.208 20 Tests und Fehler TABELLE 20. expr. msg=None) assertTrue(self. 0. Prüft. msg=None) assertGreater(self. Prüft. container. Prüft. second. msg=None) assertLessEqual(self. b. first. ob a > b gilt. 1. Beispiel: [0. d2. first. 1. expr2. d1. ob der Ausdruck „expr” True ist. b. 1] und [0. 1] sind verschieden. 1] gelten in obigem Sinne als gleich. 1] und [0. a. wenn die Differenz der beiden Parameter „first” und „second” gleich 0 ist. weil die 0 und die 1 jeweils gleich oft vorkommen. 0. second. msg=None) assertLess(self. 1] sind verschieden. assertCountEqual(self. 0. msg=None) assertDictEqual(self. expr. weil die 0 und die 1 jeweils gleich oft vorkommen. msg=None. a. first. [0. msg=None) .

1. expr1. msg=None) assertTupleEqual(self. ob jedes Element in jeder Liste gleich häufig vorkommt. ob isinstance(obj. Aufgabe: Betrachten Sie folgendes Beispiel für einen doctest. ob obj nicht None ist. msg=None) assertIsNotNone(self. 1] gelten nicht als gleich. obj. cls) gilt. Prüft. ob a is not b gilt. unexpected_regexp. d. Erkennen Sie ein Problem? import doctest def fib(n): """ Die Fibonacci-Zahl für die n-te Generation wird iterativ berechnet >>> fib(0) 0 >>> fib(1) 1 >>> fib(10) 55 . obj. Prüft.1 Methoden der Klasse TestCase (Fortsetzung) Methode assertIsInstance(self. expr2. wenn der Text „text” den regulären Ausdruck unexpected_regexp matched. Listen werden auf Gleichheit geprüft. 1] gelten als gleich. 1] and [0. first. Auf zwei sequentiellen Datenobjekten wird eine Gleichheit über die Anzahl der Elemente geprüft. cls. es wird geprüft. actual_seq. msg=None) assertNotRegexpMatches(self. Analog zu assertListEqual assertListEqual(self. 0. expected_seq. second. Prüft. msg=None) assertIsNot(self. da die Anzahl der Nullen in beiden Listen variiert. text.8 Aufgaben 1. 1] und [1.h. tuple2. ob obj is None gilt. msg=None) Bedeutung Prüft. msg=None) 20.20. list1. 0. Beispiel: [0. tuple1. Mehrzeilige Strings werden auf Gleichheit geprüft.8 Aufgaben 209 TABELLE 20. obj. msg=None) assertMultiLineEqual(self. list2. msg=None) assertIsNone(self. msg=None) assertItemsEqual(self. [0. Schlägt fehl.

testmod() Lösung: Lösungen zu Kapitel 20 (Tests und Fehler). Seite 405 .210 20 Tests und Fehler >>> fib(40) 102334155 >>> """ if n == 0: return 0 elif n == 1: return 1 else: return fib(n-1) + fib(n-2) if __name__ == "__main__": doctest.

So trennt auch die Shell den Kern des Betriebssys- BILD 21. Systemnahe Software wie beispielsweise das sys-Modul in Python fungiert als Abstraktionsschicht zwischen der Anwendung. mit der darunter liegenden Hardware kommunizieren müssen. Mit Hilfe dieser Abstraktionsschicht lassen sich Applikationen plattformunabhängig implementieren. Wie leicht zu erkennen ist.1 Systemprogrammierung Systemprogrammierung Unter Systemprogrammierung versteht man die Programmierung von Software-Komponenten. was im Allgemeinen für Python gilt. All das. und dem Betriebssystem. Die Funktion einer Muschelschale besteht in erster Linie im Schutz der Muschel. auch wenn sie direkt auf Betriebssystemfunktionalitäten zugreifen. die Teil des Betriebssystems sind oder die eng mit dem Betriebssystem bzw.2 Shell Shell ist ein Begriff. kommt der Name aus dem Englischen. Python eignet sich besonders gut für die Systemprogrammierung. zeichnet auch die Vorteile von Python in der systemnahen Programmierung aus: ■ Einfach und übersichtlich Gute Strukturierbarkeit hohe Flexibilität ■ ■ 21.1 Shells und Schalen . so wie zum Beispiel die Muschelschale. Die Muschelschale trennt und schützt das Innere vom Äußeren.21 21. dem Python-Programm. Shell bedeutet Schale und Hülle. der viel benutzt und doch oft unterschiedlich verstanden und auch missverstanden wird.

st_uid=1000. st_nlink=1. betriebssystemabhängige Programmteile einzubauen.stat_result'> >>> info posix.h. Das os-Modul bietet viele unterschiedliche Methoden wie beispielsweise zum Zugriff auf das Dateisystem. „644” in der letzten Zeile des folgenden Beispiels: >>> import os >>> info = os. also beispielsweise von der Bash-Shell von Unix/Linux.212 21 Systemprogrammierung tems vom Shell-Benutzer. os. In unserem Fall gibt es zwei Gründe.st_ino 63253 >>> info.3 os-Modul Das os-Modul ist das wichtigste Modul zur Interaktion mit dem Betriebssystem und ermöglicht durch abstrakte Methoden ein plattformunabhängiges Programmieren.stat("abc. Mit Hilfe des os-Modules kann man beispielsweise die Zugriffsrechte einer Datei abfragen.stat_result(st_mode=33188. d. erhalten wir die unter Linux gewohnte Sichtweise. kennen wir aus den Shells der Betriebssysteme. Die Shell gibt ihm robuste und einfach zu bedienende Funktionen an die Hand. um Python betriebssystemunabhängig zu machen. st_atime=1361559201. die wir in diesem Kapitel besprechen. Sie sind gewissermaßen eine Abstraktionsschicht über den Betriebssystemfunktionen. Dort sind Andererseits bilden die genannten Module ihrerseits im oben genannten Sinne Shells. st_ctime=1361455357) >>> info. st_mtime =1361455357. von Shells zu sprechen: ■ Die Module shutil. sys. damit er nicht die komplizierten und fehleranfälligen Betriebssystemfunktionen benutzen muss.st_ino is info[1] True >>> . Man ruft zuerst die Funktion stat aus dem os-Modul auf.py") >>> type(info) <class 'posix. Allerdings geht dies nicht direkt. so wie zum Beispiel die Bourne-Shell. st_dev=2055. st_gid=1000. Wenn wir diese in eine Oktal-Zahl wandeln. Die erste Komponente liefert die Zugriffsmaske als Integer. st_ino=63253.system() oder der exec*()-Funktionsfamile möglich. C-Shell oder Bash unter Unix. ■ 21. st_size=17. Diese liefert ein 10-Tupel mit verschiedenen Datei-Metadaten zurück. Generell unterscheidet man bei Betriebssystemen zwei Arten von Shells: ■ die Kommandozeile (CLI) und die grafischen Benutzeroberflächen (GUI) ■ In den meisten Fällen wird der Begriff jedoch als Synonym für den Kommandozeileninterpreter (CLI) benutzt. Gleichzeitig ist es auch mit Funktionen wie os.

■ ■ 21.3 os-Modul 213 21. Wir können wie üblich darauf zugreifen. default=None) Liefert den Wert einer Umgebungsvariablen zurück.py") Traceback (most recent call last): File "<stdin>". Mit dem optionalen zweiten Parameter kann man einen alternativen Default-Wert setzen.3. Alle Funktionen dieses Moduls erzeugen einen OSError. None wird zurückgeliefert.oder Dateinamen zurückgeliefert wird. Das Ergebnis ist dann vom gleichen Typ. Beispielsweise liefert uns os. wird die eingebaute Funktion open() durch os. auch unter dem Mac OS X lauffähig. Module mit Sternchen zu importieren.environ["USER"] den aktuellen Namen des Benutzers: >>> os. akzeptieren sowohl Byte. da gegebenenfalls Variablen und Funktionen überschrieben werden können.3. in <module> TypeError: open() takes at least 2 arguments (1 given) >>> Für die im Folgenden beschriebenen Funktionen des os-Moduls gilt: ■ Alle Funktionen. die ein komplett anderes Verhalten hat. übergeben werden. die einen Pfad. line 1. So führt dann beispielsweise die folgende. Falls nicht anders vermerkt.environ ist ein Dictionary.als auch String-Objekte. die nicht vom Betriebssystem akzeptiert werden.oder Dateinamen als Argument haben. falls wieder ein Pfad.getenv("USER") 'bernd' .open() überschrieben.21. wenn die Variable nicht existiert. ansonsten korrekte Anweisung zum Öffnen einer Datei zu einer Fehlermeldung: >>> from os import * >>> fh = open("abc. dass es sehr schlechter Stil ist. >>> os.environ["USER"] 'bernd' >>> Man kann dies natürlich auch über die im Folgenden beschriebene Funktion getenv erreichen: ■ getenv(key.2 Umgebungsvariablen os. Importiert man os mittel „from os import *”. die unter Unix laufen.1 Warnung: Vorbemerkungen Wir hatten bereits früher erwähnt. das alle Umgebungsvariablen enthält. sind alle Funktionen. falls ungültige oder nicht verfügbare Datei oder Pfadnamen oder andere Argumente.

value) In der Help-Funktion steht hier nur: putenv(. „default” und das Ergebnis sind Byte-Strings! >>> b = bytes("USER".getenv("ABC") '42' >>> os.) putenv(key. indem wir direkt das Dictionary os. Wir erreichen dies. 'utf-8') >>> os. value) Change or add an environment variable. „key”."w") <os.putenv("ABC".popen(command..environ["ABC"] = "42" >>> os. wenn die Variable nicht existiert.environ["ABC"] '42' >>> . Man könnte nun erwarten. neu erzeugen.214 21 Systemprogrammierung ■ getenvb( key. None wird zurückgeliefert. dass man eine Environment-Variable erzeugen und verändern kann und dies dann auch im aktuellen Prozess sichtbar ist.. Dies ist aber nicht so. default=None) Liefert den Wert einer Umgebungsvariablen zurück. wenn wir einen spawn durchführen oder ein Unterprozess gestartet wird."42") >>> os._wrap_close object at 0x8b9e7ac> >>> 42 >>> Es stellt sich natürlich die Frage. dass wir jetzt den Wert 42 erhalten: >>> command = """ echo $ABC """ >>> os. wie können wir eine Umgebungsvariable im laufenden Prozess ändern bzw. Mit dem optionalen zweiten Parameter kann man einen alternativen Default-Wert setzen. Wir sehen.getenv("ABC") >>> print(os. wie wir im Folgenden sehen: >>> import os >>> os.getenvb(b) b'bernd' >>> ■ putenv(key.getenv("ABC")) None >>> Die obige Umgebungsvariable ist erst bekannt. Wir starten im folgenden Beispiel eine Subshell und lassen uns dort mittels echo den Wert der Umgebungsvariablen ABC ausgeben.environ manipulieren: >>> os.

21.3 os-Modul

215

supports_bytes_environ( ) Wenn dieses Attribut den Wert True hat, existiert auch ein Dictionary os.environb, welches die Umgebungsvariablen als Bytestrings enthält. unsetenv( var ) Eine Umgebungsvariable wird entfernt. Hier gilt analog das zu putenv Gesagte. Die Umgebungsvariable existiert weiterhin im aktuellen Prozess, wird aber nicht mehr an Unterprozesse weitergegeben:
>>> import os >>> os.environ["ABC"] = "42" >>> os.getenv("ABC") '42' >>> os.unsetenv("ABC") >>> os.getenv("ABC") '42' >>> command = """ echo $ABC """ >>> os.popen(command,"w") <os._wrap_close object at 0x8bfd10c> >>>

21.3.3

Dateiverarbeitung auf niedrigerer Ebene

Im Kapitel 10 (Dateien lesen und schreiben) haben wir gesehen, mit welcher Leichtigkeit und Eleganz sich Dateien mit Python lesen und schreiben lassen. Es stellt sich deshalb sofort die Frage, weslhalb das os-Modul eigene Funktionen und Methoden zur Dateiverarbeitung bereitstellt. In den meisten Fällen genügen die eingebauten Python-Funktionalitäten voll und ganz, und der Großteil der Python-Benutzer wird nie die os-Funktionen benötigen. Aber die Dateiverarbeitung von os geht mehr ins Detail, d.h. sie gibt dem Benutzer mehr Möglichkeiten, direkt auf Byteebene zu arbeiten.

write Zunächst wollen wir zeigen, wie man die os.write-Funktion auch im Zusammenspiel mit einer von der eingebauten open-Funktion zum Schreiben geöffneten Datei nutzen kann:
import os fh = open("nur_text.txt","w") fh.write("Ein wenig Text\n") fh.flush() fd = fh.fileno() os.write(fd, b"Noch etwas Text") fh.close()

Startet man obiges Programm,1 erhält man eine Datei namens „nur_text.txt”. Den Inhalt können wir uns mittels cat2 oder mit irgendeinem Editor anschauen:
1 2

Das Programm befindet sich in unserer Beispielsammlung unter dem Name „os_write.py”. type unter Windows

216

21 Systemprogrammierung

bernd@saturn:~/bodenseo/python/tmp$ python3 os_write.py bernd@saturn:~/bodenseo/python/tmp$ cat nur_text.txt Ein wenig Text Noch etwas Text bernd@saturn:~/bodenseo/python/tmp$

Mit os.write lassen sich nur Bytestrings schreiben. Lässt man das „b” vor dem Ausgabestring in der Zeile „os.write(fd, b"Noch etwas Text")” weg, führt dies deshalb zu folgender Fehlermeldung:
bernd@saturn:~/bodenseo/python/tmp$ python3 os_write.py Traceback (most recent call last): File "os_write.py", line 8, in <module> os.write(fd, "Noch etwas Text\n") TypeError: 'str' does not support the buffer interface bernd@saturn:~/bodenseo/python/tmp$

Sehr wichtig ist es auch, die Methode flush auf das Dateihandle anzuwenden, da ansonsten die Ausgaben von os.write an die falsche Stelle geschrieben werden. Im Folgenden sehen wir den Inhalt der Datei „nur_text.txt” nach einem Programmlauf mit auskommentierter flush-Anweisung. Die beiden Zeilen der Datei sind vertauscht:
bernd@saturn:~/bodenseo/python/tmp$ cat nur_text.txt Noch etwas Text Ein wenig Text bernd@saturn:~/bodenseo/python/tmp$

open(file, flags[, mode]) Mit dieser Funktion wird eine Datei „file” zur Dateibearbeitung auf niedrigem Level geöffnet. Die Art der Bearbeitung ergibt sich sich aus den „flags” und gegebenenfalls dem optionalen „mode”-Parameter. – O_RDONLY Numerischer Wert: 0, gesetztes Bit: keines Datei wird nur zum Lesen geöffnet. – O_WRONLY Numerischer Wert: 1, gesetztes Bit: 0 Datei wird nur zum Schreiben geöffnet. – O_RDWR Numerischer Wert: 2, gesetztes Bit: 1 Datei wird zum Lesen und Schreiben geöffnet. – O_CREAT Numerischer Wert: 64, gesetztes Bit: 6 Datei wird erzeugt, falls sie noch nicht existiert. – O_EXCL Numerischer Wert: 128, gesetztes Bit: 7 Fehlermeldung, falls ein Erzeugen der Datei nicht erfolgreich war, weil die Datei bereits existiert.

21.3 os-Modul

217

– O_NOCTTY Numerischer Wert: 256, gesetztes Bit: 8 Falls es sich bei der Datei um ein Terminal-Device handelt, soll es nicht zum Kontrollterminal für den Prozess werden. – O_TRUNC Numerischer Wert: 512, gesetztes Bit: 9 Falls die Datei existiert, eine reguläre Datei ist und die Datei erfolgreich mittels O_RDWR oder O_WRONLY geöffnet wurde, wird ihre Länge auf 0 abgeschnitten. Die Dateirechte und die Eigentumsverhältnisse bleiben unverändert. Die Funktion sollte keine Effekte auf FIFO-Spezialdateien und auf Termindevice-Dateien haben. Effekte auf andere Dateitypen ist implementierungsabhängig. Was passiert, wenn man O_TRUNC zusammen mit O_RDONLY benutzt, ist undefiniert. – O_APPEND Numerischer Wert: 1024, gesetztes Bit: 10 Mit jedem write wird ans Ende der Datei geschrieben. – O_NDELAY und O_NONBLOCK Numerischer Wert: 2048, gesetztes Bit: 11 Diese Flags beeinflussen aufeinanderfolgende reads und writes. Wenn sowohl O_NDELAY und O_NONBLOCK gesetzt sind, hat O_NONBLOCK den Vorrang. Falls O_NDELAY oder O_NONBLOCK gesetzt ist, wird ein open für read-only ohne Verzögerung ausgeführt. Ein open for write-only führt zu einem Fehler, falls die Datei noch von keinem anderen Prozess zum Lesen geöffnet ist. Falls O_NDELAY und O_NONBLOCK nicht gesetzt sind gilt: Ein open für ein read-only wird solange geblockt, bis ein Prozess die Datei zum Schreiben öffnet. Ein open für ein write-only wird solange geblockt, bis ein Prozess die Datei zum Lesen öffnet. – O_DSYNC Numerischer Wert: 4096, gesetztes Bit: 12 – O_ASYNC Numerischer Wert: 8192, gesetztes Bit: 13 – O_DIRECT Numerischer Wert: 16384, gesetztes Bit: 14 Cache-Effekte sollen eliminiert bzw. reduziert werden. – O_LARGEFILE Numerischer Wert: 32768, gesetztes Bit: 15 – O_DIRECTORY Numerischer Wert: 65536, gesetztes Bit: 16 – O_NOFOLLOW Numerischer Wert: 131072, gesetztes Bit: 17 Symbolischen Links wird nicht gefolgt. – O_NOATIME Numerischer Wert: 262144, gesetztes Bit: 18 – O_RSYNC Numerischer Wert: 1052672, gesetztes Bit: 20 – O_SYNC Numerischer Wert: 1052672, gesetztes Bit: 20

218

21 Systemprogrammierung

Das folgende Skript öffnet eine Datei für den Write-only-Zugriff „os.O_WRONLY”. os.O_CREAT stellt sicher, dass die Datei „blabla.txt” beim Öffnen erzeugt wird, falls sie noch nicht existiert.
import os fd = os.open( "blabla.txt", os.O_WRONLY|os.O_CREAT ) os.write(fd, b"Etwas Text\n") os.write(fd, b"und noch eine Zeile\n") os.close(fd)

Falls blabla.txt noch nicht existiert und man kein „os.O_CREAT” angegeben hat, also fd = os.open( "blabla.txt", os.O_WRONLY ), dann erfolgt eine Fehlermeldung, wenn man das Skript startet, wie man im Folgenden sieht:
bernd@saturn:~/bodenseo/python/tmp$ python3 os_write.py Traceback (most recent call last): File "os_write.py", line 3, in <module> fd = os.open( "blabla.txt", os.O_WRONLY ) OSError: [Errno 2] No such file or directory: 'blabla.txt' bernd@saturn:~/bodenseo/python/tmp$

read(fd,n) Die Funktion read liest höchstens „n” Bytes vom Dateideskriptor „fd”. Sie liefert einen Byte-String zurück, der die gelesenen Bytes enthält. Falls das Dateiende der durch „fd” referenzierten Datei erreicht ist, wird ein leerer String zurückgeliefert. Im Folgenden lesen wir die ersten 80 Bytes des Romans „Ulysses” und lassen uns den zurückgelieferten Typ zusätzlich ausgeben:
import os, sys fd = os.open("ulysses.txt",os.O_RDWR) res = os.read(fd,80) print(res) print("type of returned object: ", type(res)) os.close(fd)

Das Skript liefert folgendes Ergebnis:
bernd@saturn:~/bodenseo/python/beispiele$ python3 os_read.py b'ULYSSES\r\n\r\nby James Joyce\r\n\r\n\r\n\r\n\r\n-- I --\r\n\r\ nStately, plump Buck Mulligan came ' type of returned object: <class 'bytes'> bernd@saturn:~/bodenseo/python/beispiele$

21.3 os-Modul

219

close(fd) Die mit dem Dateideskriptor „fd” referenzierte Datei wird geschlossen. Die Funktion liefert keinen return-Wert zurück. openpty( ) Die Funktion openpty() öffnet ein Pseudoterminal-Paar und liefert ein Deskriptorenpaar (master, slave) für pty und tty zurück. Im folgenden Skript sehen wir die Funktionsweise dieser Funktion:
import os master_pty,slave_tty = os.openpty() terminal_name = os.ttyname(slave_tty) print(master_pty, slave_tty, terminal_name)

Obiges Programm liefert folgende Ausgaben:
bernd@saturn:~/bodenseo/python/tmp$ python3 openpty.py 3 4 /dev/pts/3 bernd@saturn:~/bodenseo/python/tmp$

lseek(fd, pos, how) Die Funktion lseek positioniert die aktuelle Position des Dateideskriptors auf die gegebene Position „pos” in Abhängigkeit von „how”. Mittels lseek haben wir eine index-sequentielle Zugriffsmethode. Parameter: – fd Der Dateideskriptor, der bearbeitet wird. – pos Integer-Wert, der die Position innerhalb der Datei mit dem Dateideskriptor „fd” angibt. Die Position hängt vom Wert von „how” ab. Hat „how” den Wert os.SEEK_SET oder 0, berechnet sich der Wert von pos vom Beginn der Datei. os.SEEK_CUR oder 1, dann berechnet sich „pos” relativ zur aktuellen Position; os.SEEK_END oder 2 bedeutet in Relation zum Dateiende. – how Dieser Parameter bestimmt den Referenzpunkt innerhalb der Datei: os.SEEK_SET oder 0 steht für den Anfang der Datei, os.SEEK_CUR oder 1 bezeichnet die aktuelle Position, und os.SEEK_END oder 2 kennzeichnet das Ende der Datei.
import os, sys fd = os.open("customer_numbers.txt",os.O_RDWR) for customer in [2,1,4,0,3]: os.lseek(fd, customer * 7, os.SEEK_SET) res = os.read(fd,6) print("customer number " + str(customer + 1) +": " + str(res))

220

21 Systemprogrammierung

print("\nEine Iteration über die Kundennummern:") # iteration über die Kundennummern: os.lseek(fd, 0, 0) for customer in range(1,6): res = os.read(fd,6) os.lseek(fd, 1, os.SEEK_CUR) # skip the newline character print("customer number " + str(customer) +": " + str(res)) print("\n... und nun von hinten:") for customer in range(1,6): os.lseek(fd, -7 * customer, os.SEEK_END) res = os.read(fd,6) print(str(customer) + " from last: " + str(res)) os.close(fd)

In der ersten for-Schleife des obigen Programms können wir sehen, wie wir auf beliebige Kundennummern zugreifen können, ohne sie sequentiell durchlaufen zu müssen. In der zweiten for-Schleife benutzen wir os.seek mit dem how-Parameter „os.SEEK_CUR”, d.h. nachdem wir eine Kundennummer eingelesen haben, überspringen wir das nächste Byte mit dem os.seek-Kommando. In der letzten for-Schleife durchlaufen wir die Kundennummern von hinten. Die Ausgabe des Programms sieht wie folgt aus:
bernd@saturn:~/bodenseo/python/beispiele$ python3 os_seek.py customer number 3: b'ZH8765' customer number 2: b'AB9876' customer number 5: b'QW5185' customer number 1: b'JK3454' customer number 4: b'KL9878' Eine Iteration über die Kundennummern: customer number 1: b'JK3454' customer number 2: b'AB9876' customer number 3: b'ZH8765' customer number 4: b'KL9878' customer number 5: b'QW5185' ... und nun von hinten: 1 from last: b'QW5185' 2 from last: b'KL9878' 3 from last: b'ZH8765' 4 from last: b'AB9876' 5 from last: b'JK3454' bernd@saturn:~/bodenseo/python/beispiele$

dup() Liefert die Kopie eines Datei-Handles3 zurück.

3

engl. file descriptor

21.3 os-Modul

221

BILD 21.2 Systematik der exec-Familie

21.3.4

Die exec-„Familie”

Die Funktionen execl, execlp, execle, execv, execvp und execvpe des os-Moduls entsprechen den gleichnamigen UNIX/Linux-Funktionen. Jede dieser Funktionen aus der execFamilie ersetzt das aktuelle Prozessabbild durch einen neuen Prozess. Das neue Prozessabbild wird aus einer einer regulären und ausführbaren Datei konstruiert. Man nennt diese Datei „Prozessabbilddatei”. Die Prozessabbilddatei ist entweder ein ausführbares Objekt oder eine Datendatei, die von einem Interpreter ausgeführt werden kann. Führt man eine dieser Funktionen aus, gibt es keine Rückkehr (return) nach einem erfolgreichen Aufruf, denn der aufgerufene Prozess überlagert das aktuelle Prozessabbild. Schaut man sich die exec*-Funktionen in obigem Schaubild an, fällt auf, dass alle Funktionen exec als Präfix haben. Dann folgen bis zu drei der folgenden Buchstaben: „e”, „l”, „p” oder „v” Diese Buchstaben haben folgende Bedeutung:

e Ein Dictionary mit Umgebungsvariablen wird an den auszuführenden Prozess übergeben. v Kommandozeilenargumente werden als Liste oder Tupel an das Skript übergeben. l Kommandozeilenargumente für das aufzurufende Skript werden direkt und einzeln im exec*-Aufruf angegeben. p Die $PATH-Umgebungsvariable wird benutzt, um das Skript, dessen Namen als Parameter als String übergeben wurde, zu finden.

Fehler bei einer exec*-Funktion werden als OSError generiert. Zur Beschreibung der folgenden exec-Befehle benutzen wir ein Bash-Skript zum Testen. Wir nehmen an, dass dieses Skript unter dem Namen „test.sh” im Verzeichnis „/home/bernd/bin2” steht.

222

21 Systemprogrammierung

Das Bash-Skript „test.sh”:
#!/bin/bash script_name=$0 arg1=$1 current=`pwd` echo $script_name, $arg1 echo "XYZ: "$XYZ echo "PATH: "$PATH echo "current directory: $current"

Achtung: test.sh muss ausführbar sein, und bin2 sollte, damit die folgenden Beispiele funktionieren, nicht in $PATH enthalten sein.

execvp( scriptname, args ) Wie bereits eingangs erklärt, bedeutet das „p” im Namen, dass der Skriptname „scriptname” in den Pfaden der Systemvariablen $PATH gesucht wird. Das „v” bedeutet, dass wir Kommandozeilenargumente mit dem Parameter „args” übergeben können, und zwar in Form einer Liste oder eines Tupels. Wir starten unsere interaktive Python-Shell in einem Verzeichnis, was nicht gleich dem bin2-Verzeichnis ist. Außerdem ist „/home/bernd/bin2” nicht Teil unserer Umgebungsvariablen „$PATH”: Dann passiert Folgendes, wenn wir versuchen unser Test-Shellskript mit execvp aufzurufen:
>>> import os >>> args = ("test","abc") >>> os.execvp("test.sh", args) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python3.2/os.py", line 353, in execvp _execvpe(file, args) File "/usr/lib/python3.2/os.py", line 398, in _execvpe raise last_exc.with_traceback(tb) File "/usr/lib/python3.2/os.py", line 388, in _execvpe exec_func(fullname, *argrest) OSError: [Errno 2] No such file or directory >>>

execvp konnte die Skriptdatei „test.sh” nicht finden, da sie sich im Verzeichnis „/home/bernd/bin2” befindet und dieser Pfad nicht Teil von $PATH ist. Rufen wir unsere interaktive Python-Shell direkt im Verzeichnis „/home/bernd/bin2” auf, funktioniert alles:
bernd@saturn:~/bin2$ python3 Python 3.2.3 (default, Oct 19 2012, 19:53:57) [GCC 4.7.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import os >>> args = ("test", "abc")

"copyright". Dazu schreiben wir die neuen Umgebungsvariablen in ein Dictionary.sh". „filename” ist der Name des auszuführenden Skripts.sh immer gefunden – egal.execvp("test.::bin/bck_scripts/:bin/bck_scripts/ current directory: /home/bernd/bin2 bernd@saturn:~/bin2$ Alternativ kann man auch den Pfad „/home/bernd/bin2” in die $PATH-Umgebungsvariable mit aufnehmen.::/home/bernd/bin2 current directory: /home/bernd bernd@saturn:~$ ■ execvpe(scriptname.execvpe("test. wenn wir uns im bin2-Verzeichnis befinden: >>> import os >>> env = {"ABC":"Von Anfang".2."zweites") >>> os. env ) Wählen wir die execvpe-Variante unserer exec-Familie. "XYZ":"Ende"} >>> args = ("erstes". 19:53:57) [GCC 4. Deshalb funktioniert der folgende Aufruf nur.3 (default.2] on linux2 Type "help"./test. zweites XYZ: Ende PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin current directory: /home/bernd/bin2 .sh". env) test.7.execvp("test. "credits" or "license" for more information. aber beim Aufruf werden nur die in env definierten Umgebungsvariablen an das neue Skript übergeben. und „args” eine Liste oder ein Tupel mit den an „filename” zu übergebenden Argumenten. dann können wir zusätzlich noch neue Umgebungsvariablen beim Aufruf mit übergeben. args.sh. "abc") >>> os.3 os-Modul 223 >>> os. >>> import os >>> args = ("test". Oct 19 2012.sh. abc XYZ: PATH: /home/bernd/perl5/bin:/home/bernd/bin:/usr/lib/lightdm/lightdm:/ usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/ games:/usr/local/games:/home/writing/etrusker_ag/bin:/home/bernd/ bin:.sh". wo wir uns aufhalten. in unserem Fall „env”. args. "KLM":"bis zum ". Dann wird test. abc XYZ: PATH: /home/bernd/perl5/bin:/home/bernd/bin:/usr/lib/lightdm/lightdm:/ usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/ games:/usr/local/games:/home/writing/etrusker_ag/bin:/home/bernd/ bin:. args) .21. args) /home/bernd/bin2/test. also auch zum Beispiel im Home-Verzeichnis: bernd@saturn:~$ PATH=$PATH:/home/bernd/bin2 bernd@saturn:~$ python3 Python 3. Das Verzeichnis „/home/bernd/bin2” befindet sich zwar noch in unserer PATH-Umgebungsvariablen.sh.

"XYZ":"Ende"} >>> os. "zweites") >>> os. wenn das Skript sich nicht im aktuellen Arbeitsverzeichnis befindet. env ) Analog zu „execv”.sh".sh". in <module> OSError: [Errno 2] No such file or directory >>> os. line 1. Wir können dies mit der update-Methode erreichen.sh". "arg2") >>> os. da der Name nicht in den Verzeichnissen von der Umgebungsvariablen PATH gesucht wird: >>> import os >>> args = ("arg1". args.execve("/home/bernd/bin2/test. arg2 XYZ: Ende PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin current directory: /home/data/bodenseo/python bernd@saturn:~/bodenseo/python$ .::bin/bck_scripts/:/home/bernd/bin2 current directory: /home/bernd/bodenseo/python bernd@saturn:~/bodenseo/python$ ■ execve(scriptname. args.sh. "KLM":"bis zum ". zweites XYZ: Ende PATH: /home/bernd/perl5/bin:/home/bernd/bin:/usr/lib/lightdm/lightdm:/ usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/ games:/usr/local/games:/home/writing/etrusker_ag/bin:/home/bernd/ bin:. "KLM":"bis zum ".environ enthält alle definierten Umgebungsvariablen. args) Traceback (most recent call last): File "<stdin>". os. env) /home/bernd/bin2/test.sh".execv("test. args.environ) >>> args = ("erstes". env) /home/bernd/bin2/test. "XYZ":"Ende"} >>> env.sh. args) Wie „execvp”.224 21 Systemprogrammierung Wir wollen nun PATH und die anderen alten Umgebungsvariablen auch an das Skript übergeben. args) /home/bernd/bin2/test. allerdings wird bei dieser Variante noch ein Dictionary mit Umgebungsvariablen mit übergeben: >>> import os >>> args = ("arg1".sh.::bin/bck_scripts/:/home/bernd/bin2 current directory: /home/bernd/bodenseo/python bernd@saturn:~/bodenseo/python$ ■ execv( scriptname.update(os.execvpe("test. "arg2") >>> env = {"ABC":"Van Anfang".execv("/home/bernd/bin2/test. arg2 XYZ: PATH: /home/bernd/perl5/bin:/home/bernd/bin:/usr/lib/lightdm/lightdm:/ usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/ games:/usr/local/games:/home/writing/etrusker_ag/bin:/home/bernd/ bin:. sofern noch bin2 im PATH enthalten ist: >>> import os >>> env = {"ABC":"Von Anfang". der aktuellen Shell. Dann können wir unser Skript wieder von allen Orten aufrufen. aber der Skriptname „scriptname” muss den kompletten Pfad des Skripts enthalten.

"a3". "a3". "unsinn."a2". Bei „execvpe” hatten wir ein Tupel bzw. dass wir beim Aufruf den Namen des Skripts zweimal übergeben haben. eine Liste mit den Parametern als Strings übergeben. wird aber in der Implementierung nicht genutzt.. Das Bash-Skript „test_ params.. also arg0.sh a1 a2 a3 a4 bernd@saturn:~/bodenseo/python$ ■ execl( ) Analog zu „execlp”. benutzen wir ein Bash-Skript. arg0. Nun wird jeder Parameter direkt in „execlpe” durch Komma getrennt als String angegeben.3 os-Modul 225 ■ execlp( scriptname. wie die Argumente übergeben werden. damit das Skript gefunden werden kann. Allerdings müssen wir nun den kompletten Pfad angeben. .sh". „scriptname” und „env” sind wie bereits in execvpe beschrieben. "a1". wird aber von exec ignoriert. das alle übergebenen Argumente ausdruckt.sh” mit „execlpe” in der interaktiven Python-Shell auf: >>> import os >>> os.sh". arg0 sollte also auch den Namen des Skripts enthalten. "a4 ") /home/bernd/bin2/test_params.sh". arg0 entspricht dabei dem Namen des Skripts. "a1". Wir können stattdessen auch irgendetwas eingeben. arg1.execlp("test_params. Der Skriptname wird stattdessen an „scriptname” als Name übergeben.sh a1 a2 a3 a4 bernd@saturn:~/bodenseo/python$ Wir sehen. "a4") /home/bernd/bin2/test_params. Um das Verhalten dieser Funktion besser demonstrieren zu können.execlp("test_params. . arg1...sh". denn die Informationen aus der Umgebungsvariablen $PATH werden in dieser exec*-Variante nicht verwendet: ."a2". und es hat keinen Einfluss auf das Skript: >>> import os >>> os. "test_params.) Die Funktion „execlp” unterscheidet sich von „execvpe” in der Art.21.sh”: #!/bin/bash script_name=$0 echo $script_name while test $# -gt 0 do echo $1 shift done Nun rufen wir das Skript „test_params.

2/os. Unter Linux bedeutet das zunächst einmal.execl("test_params.5 ■ Weitere Funktionen im Überblick abort( ) Der Interpreter wird unmittelbar abgebrochen. dass man nach dem Abbruch die folgende Fehlermeldung erhält: >>> os.3. line 321.environ) os. aber es wird noch zusätzlich ein Dictionary mit Umgebungsvariablen übergeben: import os env = {"ABC":"Von Anfang". „scheitern” und „vorzeitig beenden”. execle( ) Analog zu execl..abort() Aborted (core dumped) bernd@saturn:~/bodenseo/python$ .sh". In der Help-Ausgabe zum os-Modul steht unter abort: „This ’dumps core’ or otherwise fails in the hardest way possible on the hosting operating system”. "KLM":"bis zum ".execle("/home/bernd/bin2/test.sh arg1 arg2 bernd@saturn:~/bodenseo/python$ ■ execlp( scriptname.. "XYZ":"Ende"} env. args) OSError: [Errno 2] No such file or directory >>> os. aber im Sinne von „fehlschlagen lassen”.py". "arg2") Traceback (most recent call last): File "<stdin>".226 21 Systemprogrammierung >>> import os >>> os. "arg2". Das bedeutet also.sh". Das englische Wort „abort” bedeutet „abbrechen”.sh". in <module> File "/usr/lib/python3.sh". . arg0. "arg1 ".::bin/bck_scripts/:/home/bernd/bin2 current directory: /home/bernd/bodenseo/python bernd@saturn:~/bodenseo/python$ >>> >>> >>> >>> ■ 21. line 1. arg1 XYZ: Ende PATH: /home/bernd/perl5/bin:/home/bernd/bin:/usr/lib/lightdm/lightdm:/ usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/ games:/usr/local/games:/home/writing/etrusker_ag/bin:/home/bernd/ bin:. nur dass noch ein Dictionary mit Umgebungsvariablen übergeben wird. env) Wie execlp. "arg1".update(os.sh. Siehe dazu die Beschreibung der Funktion „execvpe”.sh". "arg2") /home/bernd/bin2/test_params. . "arg1". arg1. env) /home/bernd/bin2/test. dass der schlimmstmögliche Fehler unter dem jeweiligen Betriebssystem erzeugt wird. "test_params.sh". "test. in execl execv(file.execl("/home/bernd/bin2/test_params. "test_params.

wenn alle für „mode” übergebenen Werte auf den Pfad zutreffen.getcwd() '/home/bernd' >>> os. Mit dem optionalen Parameter „mode” kann eine Bitmaske übergeben werden. ob der Pfad geschrieben werden darf.3 os-Modul 227 Außerdem klappen zwei Fenster auf. os.X_OK : Prüft. welche die zu überprüfenden Rechte enthält.py".0o755) . mode) Die Zugriffsrechte eines Pfads bzw. ob der Pfad überhaupt existiert. einer Datei werden entsprechend der Eingabemaske „mode” umgesetzt. os. ob der Pfad ausführbar ist.0o644) >>> os.access liefert True zurück.chmod("abc. os. os. >>> os.F_OK : Prüft.py")[0]) >>> permissions '0o100644' >>> os.21. eine Zahl mit Präfix 0o: >>> permissions = oct(os. Gilt mindestens ein Zugriffsrecht nicht. die normalerweise nur bei ernsten Systemfehlern auftauchen: ■ access(path. d.h. ob der Pfad gelesen werden darf.stat("abc. mode) Die Funktion „os. Folgende Werte können einzeln oder mit dem bitweisen ODER kombiniert übergeben werden: os. „mode” muss als Oktalzahl eingegeben werden.chdir("/home/bernd/bodenseo/python") >>> os.access” dient zur Überprüfung.chmod("abc. welche Rechte das laufende PythonProgramm für den Pfad „path” hat.getcwd() '/home/data/bodenseo/python' >>> ■ chmod( path.W_OK : Prüft. wird False zurückgegeben.py". ■ chdir(path) Das Arbeitsverzeichnis wird auf durch die Stringvariable „path” bezeichnete Verzeichnis geändert.R_OK : Prüft.

-1) Traceback (most recent call last): File "<stdin>". Das Skript benötigt allerdings Superuser-Rechte.stat("abc.-1) >>> ■ chroot(path) Auch zum Ausführen dieser Funktion benötigt das Skript Superuser-Rechte.py")[0]) >>> permissions '0o100755' >>> ■ chown(path. erhält man folgende Fehlermeldung: >>> os.1001. Oct 19 2012. Das rootVerzeichnis des aktuellen Prozesses wird mit diesem Kommando auf den Pfad „path” gesetzt.2.py". Möchte man einen Wert unverändert lassen. also „. Im folgenden Beispiel setzen wir das root-Verzeichnis auf „/tmp”. line 1. gid) Die Funktion chown ändert den Besitzer und die Gruppen-ID entsprechend der Parameter „uid” und „gid”. "copyright".3 (default.chroot("/tmp") ■ extsep Ein Attribut mit dem Wert des Separators für die Dateikennung4 .' >>> ■ fork( ) siehe 22 (Forks) forkpty( ) siehe 22 (Forks) file extension ■ 4 . >>> import os >>> os.py". uid.chown("abc.” >>> os. 19:53:57) [GCC 4. in <module> OSError: [Errno 1] Operation not permitted: 'abc. Ruft man chown mit ungenügenden Rechten auf. >>> os. "credits" or "license" for more information.7.extsep '.2] on linux2 Type "help".228 21 Systemprogrammierung >>> permissions = oct(os. um diese Änderungen durchführen zu können.1001. setzt man ihn auf -1 beim Aufruf.py' >>> Im folgenden Beispiel starten wir die interaktive Python-Shell mit den entsprechenden Superuser-Rechten: bernd@saturn:~/bodenseo/python$ sudo python3 [sudo] password for bernd: Python 3.chown("abc.

'/usr/local/sbin'. 30. Falls die Durchschnittsbelastung (load average) nicht ermittelt werden konnte. Die Umgebungsvariable PATH wird standardmäßig in os. geteuid( ) Liefert die effektive Benutzer-ID5 zurück.getgroups() [4.environ gesucht. wird ein OSError generiert. getegid( ) Liefert die effektive Gruppen-ID zurück. Diese Verzeichnisse entsprechen den Verzeichnissen der Umgebungsvariablen PATH. '/home/bernd/bin'. 107. '/usr/games'.'] >>> ■ getcwd() Liefert das aktuelle Arbeitsverzeichnis als Unicode-String zurück. '/usr/lib/lightdm/lightdm '. '/usr/sbin'. >>> os. die letzten fünf und die letzten 15 Minuten. Wird für den Parameter „env” ein Dictionary übergeben.getgid() 1000 >>> ■ getgroups( ) Die Funktion getgroups liefert eine Liste der Gruppen des aktuellen Prozesses zurück. '/usr/bin'.3 os-Modul 229 ■ get_exec_path(env=None) Die Funktion get__exec_path liefert die Liste der Verzeichnisse zurück. >>> os. '/bin'. '/home/bernd/bin'. >>> os. getcwdb( ) Liefert das aktuelle Arbeitsverzeichnis als Byte-String zurück. engl. '. '/usr/local/games'. 27. so wird PATH dort gesucht.21. '/ sbin'. user ID ■ 5 . 46. '/home/writing/ etrusker_ag/bin'. Die effektive Benutzer-ID ist im Allgemeinen identisch mit der „normalen” Benutzer-ID.getuid() 1000 ■ ■ ■ ■ getgid( ) Liefert die Gruppen-ID zurück. >>> os. 1000] >>> ■ setgroups(list) Die Gruppen des aktuellen Prozesses werden auf die Liste „list” gesetzt. getloadavg( ) Liefert die Anzahl der Prozesse in der Systemwarteschlange der laufenden Prozesse zurück. Die Zahlen entsprechen den Durchschnittswerten für die letzte Minute. 124. '/usr/local/bin'.get_exec_path() ['/home/bernd/perl5/bin'. 24. die zur Ausführung eines Programms durchsucht werden.

sig) Diese Funktion entspricht dem Linux/UNIX-Kommando „kill”. egid. Dies entspricht den Werten „reale Gruppen-ID” (real group ID). getresgid( ) Liefert ein Dreiertupel (rgid. Der Befehl dient dazu. „effektive Benutzer-ID” (effective user ID) und „gespeicherte Benutzer-ID” (saved user ID). Signale „sig” zu verschicken.21.getresgid() (1000. getpgrp( ) Liefert die Gruppen-ID des aktuellen Prozesses zurück. Allgemein dient kill der Interprozesskommunikation. Im Prinzip ist der Name „kill” irreführend. sich zu beenden. suid) zurück. >>> os. getpid( ) Liefert die Prozess-ID des laufenden Prozesses zurück. 1000.07.getloadavg() (0. >>> os. „effektive Gruppen-ID” (effective groupID) und „gespeicherte Gruppen-ID” (saved group ID). ■ . Standardmäßig wird bei dem UNIX-Kommando kill das Signal SIGTERM versendet. sgid) zurück. >>> os. 1000.22) >>> ■ getlogin( ) Rückgabewert ist der aktuelle Login-Name.getresuid() (1000.getlogin() 'bernd' ■ getpgid(pid ) Die Funktion getpgid() liefert die Prozess-Gruppen-ID des Prozesses mit der Prozess-ID „pid” zurück. liefert getpgid() die Prozessgruppen-ID des aufrufenden Prozesses zurück. da das Beenden („Töten”) von Prozessen nur ein Anwendungsfall von kill ist. 1000) >>> ■ ■ ■ ■ ■ getresuid( ) Liefert ein Dreiertupel (ruid. 0.230 21 Systemprogrammierung >>> os. euid. kill(pid. 1000) >>> ■ getuid( ) Liefert die Benutzer-ID vom aktuellen Prozess zurück. getppid( ) Liefert des Prozess-ID des Elternprozesses zurück. Falls der Wert von „pid” 0 ist. 0. welches den entsprechenden Prozess dazu auffordert. Dies entspricht den Werten „reale Benutzer-ID” (real user ID).

dst ) Diese Funktion erzeugt einen Hardlink „dst” auf die Datei „src”. 'c.3 os-Modul 231 Im folgenden Beispiel wollen wir einen Prozess mit der pid 7036 beenden: >>> import os >>> os.txt" info = os.listdir("/home/bernd/Documents") ['fritz.major(info. 'b.21.listdir() ['a. die häufig vom st_dev oder st_rdev Feld von stat()-Ergebnis stammt.lstat(path) major_no = os.'unterlagen. die häufig vom st_dev oder st_rdev Feld von stat()-Ergebnis stammt.txt'.minor(info. minor_no) ■ ■ Das Ergebnis sieht wie folgt aus: bernd@saturn:~/bodenseo/python/beispiele$ python3 os_major. sig) Eine Prozessgruppe wird mit einem Signal beendet. linesep( ) link(src.txt'] >>> os. listdir( ) >>> import os >>> os.st_dev) minor_no = os.py'. aber symbolischen Links wird nicht gefolgt major(device) Die Funktion major extrahiert die Majornummer eines raw-Devices.cfg'. 'output. 'fritz2. 'test.txt'. Beispiel: import os path = "ulysses.kill(7036. Beispiel: siehe minor-Funktion minor(device) Die Funktion minor extrahiert die Minornummer eines raw-Devices. major_no) print("Minor Device Number :". 'abc'.py Major Device Number : 8 Minor Device Number : 7 bernd@saturn:~/bodenseo/python/beispiele$ .cfg'] >>> ■ ■ ■ ■ lstat(path) Wie stat(path).pdf'.pdf'.9) ■ killpg(pgid.st_dev) print("Major Device Number :".

isdir("x1") True >>> os.232 21 Systemprogrammierung ■ makedev( ) Diese Funktion erzeugt eine Gerätenummer aus Minor.path. Beispiel: import os path = "ulysses. da bereits das Verzeichnis „x2” nicht existiert. wenn sie noch nicht existieren.isdir("x2") False >>> os.mkdir("x2/x22/x33") Traceback (most recent call last): File "<stdin>".txt" info = os. Ein Verzeichnis „path” wird erzeugt. line 1.major(info.B. minor_no) dev_no = os. . 0755) >>> os. Der optionale Parameter „mode” entspricht dem Modus.mkdir("x1". mode] ) Wie der Befehl mkdir.py Major Device Number : 8 Minor Device Number : 7 Device Number : 2055 bernd@saturn:~/bodenseo/python/beispiele$ ■ mkdir(path[. zu einer Fehlermeldung. Im folgenden Beispiel führt der Versuch. aber nur. dev_no) Folgende Ausgaben werden von obigem Skript erzeugt: bernd@saturn:~/bodenseo/python/beispiele$ python3 os_makedev. in <module> OSError: [Errno 2] No such file or directory: 'x2/x22/x33' >>> ■ makedirs(path[. das Verzeichnis „x2/x22/x33” zu erzeugen.und der Majornummer.minor(info. wenn alle oberen Verzeichnisse bereits existieren. „0755”.path.isdir("x1") False >>> os. mode]) Die Funktion mkdir() entspricht der Linux/Unix-Funktion mkdir.lstat(path) major_no = os. minor_no) print("Device Number :".makedev(major_no. Beispiel: >>> import os >>> os.st_dev) print("Major Device Number :".st_dev) minor_no = os. aber makedirs erzeugt auch gegebenenfalls übergeordnete Verzeichnisse.path. major_no) print("Minor Device Number :". also z.

und zwar ohne Limit. os. ist die Pufferung aktiviert.popen eignet sich in besonderer Weise.nice(3) os. Ist der Wert auf 1 gesetzt. „0755”.3 os-Modul 233 Der optionale Parameter „mode” entspricht dem Modus.nice(2) os._wrap_close”.h. dann werden die Ergebnisse nicht an das os.path.nice(1) os. erfolgt keine Pufferung. Damit hat man dann die Möglichkeit. nice(inc) Die Funktion vermindert die Priorität des Prozesses durch „inc” und liefert den Wert der neuen Priorität zurück. entspricht dies der Puffergröße in Bytes. Optional kann der Modus mit dem Parameter „mode” gesetzt werden.isdir("x2") False >>> os._wrap_close-Objekt übergeben. . Beispiel: >>> import os >>> os.isdir("x2/x22/x33") True >>> ■ mkfifo(path[.makedirs("x2/x22/x33") >>> os.nice(5) ■ ■ popen(command[. also schreibend. Beim Modus „r”. sondern an die Standardausgabe des laufenden Programms. lesend. Ein negativer Wert entspricht dem DefaultVerhalten. bufsize]] ) Die Funktion popen öffnet eine Pipe.B.isdir("x2") True >>> os. >>> >>> 2 >>> 5 >>> 6 >>> 11 >>> import os os. Gibt man eine positive Zahl größer 1 an. Ein Kommandostring „command” wird dazu von der Default-Shell des Betriebssystems ausgeführt. im Python-Programm mit diesen Ergebnissen weiterzuarbeiten. mode[. Der Parameter „bufsize” bestimmt die Größe des zu verwendenden Puffers.path.21. d. Wählt man den Modus „w”. ShellBefehle auszuführen. Dieses Objekt dient auch dazu. Der Rückgabewert ist ein Objekt der Klasse „os._wrap_close-Objekt gespeichert. Falls für „bufsize” der Wert 0 gewählt wird. werden die Ergebnisse der Ausführung des Kommandostrings „command” im os. mode]) Funktion zum Erzeugen einer benannten Pipe mit Namen „path”. wie man es von der Kommandozeile des Betriebssystems gewohnt ist. gegebenenfalls die Ergebnisse des Kommandostrings „command” aufzunehmen.path. also z.

erhalten wir folgende Ausgabe: bernd@saturn:~/bodenseo/python/beispiele$ python3 os_popen. ulysses.txt:--You as a good catholic.txt:of their brazen bells: _et unam sanctam catholicam et apostolicam ulysses. aber nun im "r"-Modus: ulysses.txt:the most Roman of catholics call _dio boia_. ulysses.py Kommand "command" wird im Modus "w" gestartet.split(r"\W+". Die Ausgabe geht in die Standardausgabe des laufenden Programms! "command" wird wieder gestartet. line) words = set(words) print("""Wörter im Kontext von "catholic":""") print(words) Starten wir das Programm. Im Folgenden separieren wir alle Wörter._wrap_close”-Objekt zurückgeliefert. Jetzt wird das Ergebnis in einem „os. catholic club. Sun or ulysses."w") print(""" "command" wird wieder gestartet. wir haben mehrfache Vorkommen auf eines reduziert: import os. wird die Shell-Ausgabe unmittelbar in die Ausgabe unseres Skripts weitergeleitet. Zuerst suchen wir mit dem Shell-Kommando „grep catholic *. die das Wort „catholic” enthalten. hangman god."r") list_of_lines = list(res) words = [] for line in list_of_lines: line = line[12:] # Abschneiden des Präfixes "ulysses.""") print("""Die Ausgabe geht in die Standardausgabe des laufenden Programms!""") os.popen(command.txt:who is this used to say he was a queer breedy man great catholic all the ulysses.txt """ print("""Kommand "command" wird im Modus "w" gestartet.txt:practical catholic: useful at mission time. Da wir popen im Modus „w” starten. Why? Some reason. the industrious blind.txt:are liege subjects of the catholic chivalry of Europe that foundered at ulysses. believe . aber nun im "r"-Modus:""") res = os. re command = """ grep catholic *.txt:" words = words + re. he observed. die in diesen Zeilen vorkommen. d. wie man popen sowohl im „w”-Modus als auch im „r”-Modus betreibt.txt:Gill's.popen(command.txt:the holy Roman catholic and apostolic church. talking of body and soul. und geben die Menge dieser Wörter aus. is doubtless ulysses.txt” alle Zeilen.234 21 Systemprogrammierung In einem etwas umfangreicheren Beispiel wollen wir demonstrieren.txt” aus allen Dateien mit der Extension „. Im zweiten popen starten wir den gleichen Befehl im „r”-Modus. das wir in einer Variablen „res” speichern.h.

'to'. 'preferred'. '_dio'. 'prepuce'. 'view'. 'good'. 'catholics'. 'brazen'. 'talking'. He infinitely preferred the sacred music of the catholic ulysses. 'call'. 'carnal'. 'sacred'.21. Handelt es sich um das einzige Unterverzeichnis des Elternprozesses.txt:--That's right. 'mission'. 'he'. 'catholicism'. so wird auch der Elternprozess entfernt.c +-. 'practical'. 'Roman'. The Irish catholic ulysses. 'club'. 'apostolicam'. 'soul'. 'The'.b ■ . removedirs(path) Ein Verzeichnis wird rekursiv entfernt. 'their'. 'all'. 'unam'. 'with'. 'subjects'. 'are'. 'sanctam'. 'that'. 'great'. ' emergency'. 'a'. 'matrimony'.3 os-Modul 235 ulysses. 'catholic'. 'holy'.txt:Roman catholicism at the epoch of and with a view to his matrimony Wörter im Kontext von "catholic": {''. 'cocked'. 'observed'. ' You'. 'useful'. 'god'. 'foundered'.a | |-. 'most'. 'or'. 'time'. ' He'. 'his'.a +-. 'corporation'.y | +-. Dies wird rekursiv solange fortgesetzt. Eine Datei „path” wird entfernt. 'Why'.txt:prepuce. '_et'. bernd@saturn:~/tmp$ tree x x +-. ' corroborated'. 'reason'. 'right'. 'man'. 'dustbuckets'. ' music'. 'Sun'. 'who'. ' chivalry'. 'infinitely'. 'body'.b | +-. 'Some'.z |-. 'this'. 'bridal'. 'Europe'. 'church'. 'doubtless'. 'That'. 'queer'.txt:corporation emergency dustbuckets. 'used'. the carnal bridal ring of the holy Roman catholic apostolic ulysses. ' catholicam'. 'et'. auf den ein symbolischer Link „path” zeigt: >>> import os >>> os. 'breedy'. 'ring'. 'hangman'. 'industrious'. der den kompletten Pfad enthält. bis ein Pfad nicht mehr das einzige Element eines Elternprozesses ist. 'and'. ulysses. ' liege'. 'as'. ' of'. 'say'. 'Irish'. 'at'. 'apostolic'. 'was'. the old tarpaulin corroborated. 's'. 'tarpaulin'. 'epoch'. 'boia_'. 'the'} bernd@saturn:~/bodenseo/python/beispiele$ ■ readlink( ) Die Funktion readlink liefert einen String zurück. 'hat'. the Roman catholic church. 'Gill'.txt:a cocked hat. 'blind'. 'is'. 'bells'. 'old'. ' believe'.readlink("proj") '/home/data/projects/' >>> ■ remove(path ) Entspricht der Funktion unlink.

line 179. new) >>> import os >>> tree = os. line 1.walk("x") >>> list(tree) [('x'.236 21 Systemprogrammierung 7 directories. ['b.removedirs("x/y/a") >>> os. renames(old. 'c']. 'b']. die nicht leer sind. ['a'.renames("x".txt']). line 1. []). Der Aufruf löscht deshalb auch automatisch das Elternverzeichnis „y”. [].removedirs("x/y") Traceback (most recent call last): File "<stdin>". []. ('x/z/a'. 'z']. ('x/z/b'.removedirs("x/y/c") >>> os. []). ('x/y/c'. ['b.removedirs("x/y/c")” ist das Verzeichnis c das einzige Unterverzeichnis und Datei von y. in <module> File "/usr/lib/python3. []. []). [])] >>> os. "x_new") >>> tree2 = os.removedirs("x/y/b") >>> os. >>> import os >>> os. []).py".walk("x_new") >>> list(tree2) ■ . 0 files bernd@saturn:~/tmp$ Aus dem folgendem Beispiel lernen wir. 'b'. dass wir keine Verzeichnisse mit removedirs löschen können. txt']). dst) Mit rename kann eine Datei oder Verzeichnis von „src” nach „dst” umbenannt werden. ['y'. erfolgt eine Fehlermeldung. 0 files bernd@saturn:~/tmp$ ■ rename(src.b 3 directories.z |-. ('x/y/a'. []. ['a'.2/os. line 179. in removedirs rmdir(name) OSError: [Errno 2] No such file or directory: 'x/y' >>> Nach obigen Anweisungen sieht unser Baum wie folgt aus: bernd@saturn:~/tmp$ tree x x +-.txt'. []). []. 'a. ('x/y/b'. in <module> File "/usr/lib/python3. in removedirs rmdir(name) OSError: [Errno 39] Directory not empty: 'x/y' >>> os.py". ('x/y'. Bei der Ausführung von „os.2/os.a +-. Falls der neue Name „dst” bereits existiert.removedirs("x/y") Traceback (most recent call last): File "<stdin>". (' x/z'.

[]. ('x_new/y/b'. sgid) Die effektive.txt'. (' x_new/y/c'. 'b']. []. []). 'a. setregid(rgid. ['b. setsid( ) Der Systemaufruf setsid() wird aufgerufen. setgid(gid) Die Gruppen-ID des aktuellen Prozesses wird auf „gid” gesetzt. in <module> OSError: [Errno 39] Directory not empty: 'x_new' >>> Will man ein nichtleeres Verzeichnis löschen. []).21. 'z']. []). reale und gespeicherte User-ID des Prozesses wird gesetzt. suid) Die effektive. >>> import os >>> os. seteuid(uid) Die effektive User-ID des aktuellen Prozesses wird auf „uid” gesetzt. ('x_new/y/a'. empfiehlt es sich die Funktion rmtree des Moduls shutil zu benutzen. euid) Die effektive und reale User-ID des Prozesses wird gesetzt. egid. stat() Ein stat-Systemaufruf wird durchgeführt. ['a'.txt']). ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ . setuid( ) Die User-ID des aktuellen Prozesses wird auf „uid” gesetzt. []). ['a'. aber nur. wenn es leer ist. []. setreuid(ruid. line 1. egid) Die effektive und reale Gruppen-ID des Prozesses wird gesetzt.rmdir("x_new") Traceback (most recent call last): File "<stdin>".rmtree("x_new") >>> ■ setegid(gid) Die effektive Gruppen-ID des aktuellen Prozesses wird auf „gid” gesetzt. setresuid(ruid. reale und gespeicherte Gruppen-ID des Prozesses wird gesetzt. ['b. wird die Ausnahme „OSError: [Errno 39] Directory not empty: ’x_new’” generiert.txt']).3 os-Modul 237 [('x_new'. ['y'. setpgid( ) Der Systemaufruf setpged() wird ausgeführt. ('x_new/z'. ('x_new ■ rmdir(path) Das Verzeichnis „path” wird entfernt. ('x_new/y'. Falls es nicht leer ist. setpgrp( ) Der aktuelle Prozess wird zum Gruppenleader. 'c ']. 'b'. euid. >>> import shutil >>> shutil. setresgid(rgid.

werden zukünftige Aufrufe Integers zurückliefern. Wenn „newval” False ist..stat("b.strerror(i)) . st_mtime=1361693338. st_gid=1000. Ruft man die Funktion ohne Parameter auf. st_nlink =1. liefern zukünftige Aufrufe von stat() (bzw.11): .[lf]stat zu beeinflussen: Falls „newval” True ist. 1 Operation not permitted 2 No such file or directory 3 No such process 4 Interrupted system call 5 Input/output error 6 No such device or address 7 Argument list too long 8 Exec format error 9 Bad file descriptor 10 No child processes >>> ■ . st_ctime=1361693475) >>> ■ stat_float_times([newval]) Diese Funktion dient dazu. fstat) float-Werte zurück.. os. – st_ino – Inode-Nummer – st_dev – Gerätenummer (device) – st_nlink – Anzahl der Hardlinks – st_uid – User-ID des Besitzers – st_gid – Gruppen-ID des Besitzers – st_size – Dateigröße – st_atime – letzte Zugriffszeit auf die Datei – st_mtime – letzte Modifikationszeit der Datei – st_ctime – plattformabhängig: Zeit der letzten Änderung der Metadaten unter Unix/Linux und die Entstehungszeit der Datei unter Windows >>> import os >>> os. st_dev=2055. Im folgenden Beispiel lassen wir uns die ersten 10 von 132 Fehlermeldungen anzeigen: >>> import os >>> for i in range(1. print(i.stat_result(st_mode=33204. st_atime=1361693338.238 21 Systemprogrammierung Die Ergebniswerte sind: – st_mode – protection bits..txt") posix. wird die aktuelle Einstellung zurückgeliefert. das Ausgabeverhalten von os.. st_ino=16781124. lstat. strerror(code) Zu einer gegebenen Fehlernummer „code” wird der entsprechende Fehlerstring zurückgeliefert. st_size=0. st_uid=1000.

"link2abc.5. cstime. die für kryptografische Anwendungen benutzt werden können.uname() ('Linux'.urandom(10) b'9\xc3\xe9\x02\xe8\xa2z\xea\xfcQ' >>> os.symlink("abc. 0. version.islink("link2abc.py") >>> os.py".py” auf die Datei „abc.0-23-generic'. release. Im folgenden Beispiel erzeugen wir zunächst einen symbolischen Link namens „link2abc.py") True >>> ■ sysconf( ) system( command ) Eine Kommandostring „command” wird als in einer Untershell ausgeführt.14. ■ ■ times( ) times liefert ein Tupel mit den verschiedenen Prozesszeiten zurück: (utime. Man sollte stattdessen das Modul subprocesses benutzen. der auf „src” zeigt. welches die folgenden Informationen über das Betriebssystem enthält: (sysname.65) >>> ■ umask( ) uname( ) Die Funktion uname liefert ein Tupel zurück.21.04.path. '3. 'i686') >>> ■ ■ unlink(path) Eine Datei wird entfernt. urandom(n) Die Funktion urandom liefert n Zufallsbytes zurück.urandom(10) b'\xdd\x06\x9fK\x17{H{>\xa6' >>> os. Entspricht der Funktion remove(path).path.urandom(10) b'^)\xdb\x9c\x8b\x99\x82\x96\x89\xc4' >>> ■ .islink("abc. 17210084.py” mit der Funktion symlink: >>> os.py") False >>> os.04. 0.times() (0. 0. elapsed_time) >>> os. nodename. '#35-Ubuntu SMP Thu Jan 24 13:05:29 UTC 2013'. stime.01. 'saturn'. >>> os. dst) symlink erzeugt einen Link „dst”. machine) >>> import os >>> os.3 os-Modul 239 ■ symlink(src. cutime. Diese Funktionalität ist veraltet.

in dem sich das Unterverzeichnis abc befindet: >>> import os >>> os.txt'.txt']) ('abc/b'. Werden keine Zeiten angegeben.txt']) ('abc/c'.3. 'c'].. print(path) . 'b3. ['a'.6 os. []) ('abc/a'. „rusage” bezeichnet die „resource”-Benutzungsinformation. status). ['a1. aber mit den Parametern „pid” und „status”. 21.txt'. das die PID und den exit-Status enthält.. also das Tupel (pid. dass ein Kind-Prozess terminiert. wait() Wartet darauf.. ('abc'. mtime) ) Die letzte Zugriffszeit (access time) und die Modifikationszeit (modification time) einer Datei werden auf die Werte des Tupels „(atime. um einen Dateibaum rekursiv zu durchwandern.path .txt']) >>> Die Funktion eignet sich also ideal. 'b'. und liefert ein Tupel zurück. walk( ) Betrachten wir folgenden Teilbaum eines Dateisystems: ■ ■ ■ ■ Nun wenden wir walk auf diesen Teilbaum an. waitpid(pid. Wir starten Python in dem Verzeichnis.240 21 Systemprogrammierung ■ utime(path. (atime.Arbeiten mit Pfaden Man kann das Modul „path” auf zwei Arten importieren: entweder direkt mit „import os. []. werden die Zeiten der Datei „path” auf die aktuelle Zeit gesetzt. mtime)” gesetzt. rusage) zurückgeliefert. ['c1. 'b1.walk("abc"): . options) Wie wait. []. []. 'a2.walk("abc") <generator object walk at 0xb714ba7c> >>> for path in os.path” oder indirekt über „import os” .txt'.. ['b2. aber es wird ein 3-Tupel (pid. status. wait3( ) Wie wait.

abspath(".basename("/home/bernd/nonsense") 'nonsense' >>> os.") '/home/bernd' >>> os. Beispiel: >>> os.abspath("nonsense") '/home/bernd/nonsense' >>> ■ basename(p) Liefert die letzte Komponente eines Pfadnamens zurück. Beispiel: >>> paths = ["/home/bill/Documents".path. Oct 19 2012.path. "/home/bill/bin". "/home/bill/ Documents/articles/"] >>> os. was „nonsense” heißt: bernd@saturn:~$ python3 Python 3. aber keines.path.py' >>> os.3 (default.7. der sich aus dem aktuellen Arbeitsverzeichnis und dem Wert von Namen zusammensetzt.2.3 os-Modul 241 ■ abspath(name) Liefert einen Pfad zurück. Im folgenden Beispiel befinden wir uns im Homeverzeichnis des Benutzers bernd.21.commonprefix(paths) '/home/bill/' >>> ■ sep Attribut mit dem Trennsymbol in Pfaden. >>> import os >>> os. 19:53:57) [GCC 4. ob der daraus resultierende Pfad wirklich existiert.py") 'hellO\_world. also in Linux „/” und unter Windows „\\”. Dabei spielt es keine Rolle.path. mit dem alle Pfade der Liste „pf” beginnen. "copyright". >>> os.sep '/' >>> ■ dirname(p) Liefert den Anfang des Pfades „p” bis zum letzten Schrägstrich „/” zurück: .basename("/home/bernd/hellO\_world.path. Dort gibt es ein Unterverzeichnis „python”.path. "credits" or "license" for more information.2] on linux2 Type "help".basename("/home/bernd/python/") '' >>> ■ commonprefix(pf ) Liefert den größtmöglichen Pfad zurück.abspath("python") '/home/bernd/python' >>> os.path.

242 21 Systemprogrammierung >>> path = "/home/bill/documents" >>> os.h.path. Falls $HOME nicht gesetzt ist oder im Fall von „~user” der Benutzer „user” nicht existiert.path.2. wird der Wert von „path” nicht verändert. 19:53:57) [GCC 4.exists("/home/bernd/nonsense") False >>> ■ expanduser(path) „~” und „~user” werden durch den vollständigen Pfad ersetzt.dirname(path) '/home/bill' >>> path = "/home/bill/documents/" >>> os. Variablen in Pfaden werden durch ihren Wert ersetzt.expanduser("~homer") '~homer' >>> os. "copyright". bleibt sie unverändert.path. . "credits" or "license" for more information.path. aber keines mit Namen „nonsense”. „~” wird mit dem Wert der Shell-Umgebungsvariablen $HOME ersetzt. aber einer namens „bill”: >>> os.dirname(path) '/home/bill/documents' >>> path = "/home/bill/documents/beispiel. „True” wird zurückgeliefert. mit dem Homeverzeichnis des Benutzers „user”.3 (default.path. ansonsten „False”. Im folgenden Beispiel existiert kein Benutzer mit Namen „homer”.2] on linux2 Type "help".py" >>> os. >>> import os >>> os. Oct 19 2012.h.dirname(path) '/home/bill/documents' >>> ■ exists(path) Mit dieser Funktion kann man testen.7.exists("/home/bernd/python") True >>> os.expanduser("~bill") '/home/bill' >>> ■ expandvars(path) Variablen bzw. Beispiel: Bei der Funktion „abspath” hatten wir vermerkt. wenn ein Pfad existiert. „False” wird auch zurückgeliefert. d. ob ein Pfad existiert. d.path.path. Im Folgenden prüfen wir dies mittels „exists” nach: bernd@saturn:~$ python3 Python 3. bzw.expanduser("~") '/home/bernd' >>> os. Falls eine Variable nicht definiert ist. wenn es sich um einen „broken link” handelt. dass in „/home/bernd/” ein Unterverzeichnis „python” existiert.path.

in getatime return os. also die Zeit der letzten Änderung an der Datei ausgegeben.expandvars("$SHELL") '/bin/bash' >>> os.getatime("buecher.py") ■ 6 Als Metadaten bezeichnet man in diesem Zusammenhang „Zugriffsrechte”.py”. wenn sich die Metadaten einer Datei ändern. Beispiel: >>> import os >>> os.8920438 >>> os.path.path. line 59.getatime("buch. wird ein OSError produziert mit der Meldung: „ No such file or directory:”."w") >>> fh. Der Name kann sowohl durch einen relativen Pfad als auch durch einen absoluten Pfad gegeben sein.path.getmtime("abc.stat(filename).oder Verzeichnisnamen die letzte Zugriffszeit zurück. die atime wird beim Schreiben nicht mehr verändert: >>> fh = open("abc.21.3 os-Modul 243 >>> os.8701274 >>> os.py".path. wenn in eine Datei geschrieben wird. Linux-atime. Wir schauen uns nun getatime.st_atime OSError: [Errno 2] No such file or directory: 'buecher.getatime("/home/bernd/bodenseo/python/buch. „Besitzer” oder Ähnliches. jedoch wird hier die ChangeTime. line 1.path. Zunächst erzeugen wir eine leere Datei names „abc.expandvars("$ABC") '$ABC' >>> os. Die mtime ändert sich aber im Unterschied zur ctime nicht.path.getatime("abc. während atime einen etwas früheren Wert aufweist.py".2/genericpath. Die mtime ändert sich jedes Mal.tex") 1361384210.tex") Traceback (most recent call last): File "<stdin>". dass entweder der Inhalt der Datei selbst oder die Metadaten6 der Datei geändert wurden.expandvars("/home/$USER/") '/home/bernd/' >>> ■ getatime(filename) Liefert für einen existierenden Datei. dass die ctime und die mtime gleich sind. Wir erkennen.8701274 >>> os. in <module> File "/usr/lib/python3.path. Falls ein Name nicht existiert. atime entspricht der Unix.close() >>> os. Änderung bedeutet hier. also auch. getmtime(filename) Diese Funktion ist analog zu getctime und getatime.bzw. also dem letzten lesenden oder schreibenden Zugriff auf die Datei.path. .tex") 1361384210.py") 1361433115. getmtime und getctime im Zusammenspiel an. wenn sie erstellt wird.tex' ■ getctime(filename) Wie getatime.

"a") fh. >>> os.path. wenn wirklich der Inhalt einer Datei verändert wurde. dass nun sowohl getmtime und getctime die gleichen Werte zurückliefern: >>> fh = open("abc. >>> >>> >>> 0 >>> >>> 17 >>> >>> 17 >>> fh = open("abc.write("Do you like spam?") fh.244 21 Systemprogrammierung 1361433693.write("Just some spam!") 15 >>> fh. Dabei spielt es keine Rolle.path.py") fh = open("abc.getctime("abc.path.getmtime("abc.0429058 >>> os. Wie erwartet ändert sich nun nur die ctime.py".path.path.755) >>> os.path. ob es sich bei einem Dateinamen um einen absoluten oder einen relativen Dateinamen handelt.py".0429058 Nun ändern wir die Zugriffsrechte der Datei „abc. Wir erkennen.close() >>> os.py") 1361433115.path. d.isabs("/monty/python") True .close() os. was ja hier nicht der Fall ist: >>> os.py") 1361433115.py".7121885 >>> os.getmtime("abc.7121885 >>> ■ getsize(filename) Liefert die Dateigröße zurück.path.py") 1361433817. die Anzahl der Bytes. da sich die mtime nur ändert.0595207 Jetzt ändern wir wirklich den Inhalt.py".getsize("abc."w") fh.py") 1361433951.8920438 >>> os.py”.chmod("abc.py") 1361433693.8920438 >>> os. indem wir weiteren Text an die Datei anhängen.0429058 >>> os. Es handelt sich um eine reine syntaktische Prüfung.h.getatime("abc."a") >>> fh.py") 1361433693.py") 1361433951. ob ein Pfadname wirklich im Dateisystem existiert.getsize("abc.close() os.py") ■ isabs(s) Die Funktion prüft.getctime("abc.getatime("abc.path.getctime("abc.path.

py") True >>> os. "link2abc.islink("link2abc.islink("abc.path. wenn es sich bei „path” um einen symbolischen Link handelt.path.3 os-Modul 245 >>> os.path.isfile("/home/bernd/bodenseo/python/abc.path.path.21.path.isfile("abc.py") True >>> os.path.exists("/monty/python") False >>> Achtung: Obwohl es sich bei Pfadnamen wie „~/Documents” oder „~monty” um absolute Pfadnamen handelt.isdir("beispiele") True >>> os. wenn der Pfadname „s” ein existierendes Verzeichnis bezeichnet: >>> os. wenn der Pfadname „path” eine existierende Datei bezeichnet: >>> os.path. wird in diesem Fällen jedoch der Wert „False” zurückgeliefert: >>> os.py") False >>> os.py") False >>> os. ansonsten wird False zurückgegeben.py") >>> os.py") True >>> os.path.py") False >>> ■ islink(path) Liefert True zurück.py” auf die Datei „abc.exists("abc.isabs("~monty/python") False >>> ■ isdir(s) Liefert True zurück.symlink("abc.isdir("abc.path.py” mit der Funktion symlink: >>> os.isabs("python") False >>> os.isfile("/home/bernd/bodenseo/python/spam.isdir("monty") False >>> os.path. Im folgenden Beispiel erzeugen wir zunächst einen symbolischen Link namens „link2abc.py") True >>> .path.isabs("~/python") False >>> os.path.exists("/home/bernd/") True >>> ■ isfile(path) Liefert True zurück.py".path.

h.path.lexists("/home/bernd/monty") False >>> os.path.path. dass es in dem existierenden Verzeichnis „/home/bernd/” kein Unterverzeichnis „monty” gibt und dass es sich bei „/home/bernd/bodenseo/python/monty” um einen „broken link” handelt. wird auch True zurückgeliefert. Unter Windows spielt aber Groß. ob es sich bei dem Pfad „path” um einen Mount-Punkt handelt: >>> os. wenn es sich um einen „broken link” handelt.und Kleinschreibung eines Pfades. >>> os.join("abc". „abc. .lexists("/home/bernd/monty") True >>> os.path.join("abc".py” sind alles gültige Schreibweisen für das gleiche Dateiobjekt."xyz"."def".lexists("/home/bernd/bodenseo/python/monty") True >>> ■ normcase(s) Normalisiert Groß.path.246 21 Systemprogrammierung ■ ismount(path) Testet.und Dateinamen keine Rolle.path."xyz") 'abc/def/xyz' >>> os."xyz") '/home/monty/xyz' >>> os. erhält man jeweils den Namen komplett in Kleinschreibung.join("abc"."def".und Kleinschreibung bei Pfad."xyz/") 'abc/home/monty/xyz/' >>> ■ lexists(path) Liefert True zurück. wird ein Schrägstrich angefügt.PY”."xyz") 'abc/home/monty/xyz' >>> os. Zum Verständnis des folgenden Beispiels muss man wissen. Steht als letzte Komponente ein leerer String.ismount("/media/bernd/CDD8-B9BF") True >>> ■ join(a. werden alle vorher stehenden Komponenten weggelassen.ismount("/media/bernd/") False >>> os. "") 'abc/home/monty/xyz/' >>> os."home/monty".path. „ABC. wobei ein Schrägstrich „/” bei Bedarf eingefügt wird.path.join("abc".join("/home/monty".py” oder „Abc. Falls eine der Komponenten ein absoluter Pfadname ist. d.join("abc"."home/monty". falls der Pfad sonst nicht mit einem Schrägstrich geendet hätte. >>> os.path. also nicht unter Linux und Unix."/home/monty"."home/monty".path. *p) Zwei oder mehr Pfadnamekomponenten werden vereinigt. Diese Funktion hat keine Wirkung unter Posix. Wendet man normcase unter Windows auf diese Namen an. wenn der Pfad „path” existiert.path. Falls path ein symbolischer Link ist."xyz") '/home/monty/def/xyz' >>> os.

py/") '/home/bernd/abc.py' ■ realpath(filename) Die Funktion „realpath” liefert den kanonischen Pfad.normcase("abc.normcase("c:/Users/Bernd/") 'c:\\users\\bernd\\ Unter Linux sieht es hingegen wie folgt aus: >>> os.path.py") 'abc.normpath("/home///bernd//abc..path.normcase("ABC.path.realpath("/home/bernd/bodenseo/python/beispiele/intranet") '/home/data/intranet' >>> ■ relpath(path.py") 'Abc. In der folgenden interaktiven Python-Shell befinden wir uns im Verzeichnis „/home/ bernd/bodenseo/python/beispiele/intranet”./..normpath("abc.normcase("abc.py' >>> os. Dort legen wir einen symbolischen Link „intranet” auf „/var/www/intranet” an: >>> os.relpath("/home/bernd/") '.normcase("ABC. "intranet") >>> os.3 os-Modul 247 Beispiel unter Windows: >>> os.path.py' >>> os.path. Symbolische Links werden dabei aufgelöst.getcwd() '/home/data/bodenseo/python/beispiele' >>> os.path. d.path.PY' >>> os./bernd' >>> . eines Pfades „filename” zurück.21.h. wie wir im Beispiel sehen können.py' >>> os.path.py' >>> os.symlink("/var/www/intranet"..realpath("intranet") '/home/data/intranet' >>> os.normcase("Abc. d.py") 'abc.py' >>> os.path.normcase("Abc.py") 'abc.h.path. >>> os./.path.PY") 'abc.py/") 'abc.PY") 'ABC.. start=None) Es wird ein Pfadname relativ zur aktuellen Position für den Pfad „path” generiert: >>> os.path./. mehrfache Schrägstriche und Schrägstriche am Ende eines Pfades werden entfernt. ein Pfad ohne symbolische Links.py' >>> ■ normpath(path) Der Pfad „path” wird normalisiert.

248 21 Systemprogrammierung ■ samefile(f1.split("/abc/xyz/beispiel.py". also alles vor dem letzten Schrägstrich aufgeteilt.py") True >>> import shutil >>> shutil.path. Beide Teile können jeweils leer sein.h.split("/abc/xyz") ('/abc'.py") ('/abc/xyz'.. Beispiel: >>> os.path. d.path.samefile("beispiele/abc.samefile("beispiele/abc.split("/abc/xyz/") ('/abc/xyz'.py") False >>> ■ split(p) Ein Pfadname wird in den Dateinamen bzw. Es wird nicht geprüft.py') ■ splitext(p) Die Dateierweiterung wird von einem Pfad abgesplittet. "beispiele/abc.splitdrive("c:/abc/xyz/beispiel.path. ". ob zwei Dateien den gleichen Inhalt haben. weil es keine Laufwerkskomponente geben kann. ob zwei Pfadnamen die gleiche Datei referenzieren. 'c:/abc/xyz/beispiel.path. "abc.py") >>> os.path. f2) Es wird getestet.path.py". Unter Linux und Unix ist der erste Wert immer der leere String. "monty.py") (''. 'xyz') >>> os.py". Ein Pfadname wird in den Laufwerksnamen (drive) und den Rest des Pfades zerlegt. auch wenn der Pfad keinen Sinn ergibt: >>> os.py') >>> os. alles.path.path. '\\windows\\users') >>> Unter Linux sieht es wie folgt aus.samefile("abc.py") >>> os.py". 'beispiel.py".split("xyz. Das folgende Beispiel wurde unter Windows erstellt: >>> os./python/abc.samefile("abc. was nach dem letzten Punkt folgt: .py") False >>> os.symlink("abc.copyfile("abc. 'xyz. "monty.py") True >>> os.py") (''. das tiefste Verzeichnis und den Basispfad.py') >>> ■ splitdrive(p) Diese Funktion ist im Prinzip auf das Windows-Betriebssystem zugeschnitten.splitdrive("c:\\windows\users") ('c:'. "monty. wie wir im Folgenden auch erkennen können: >>> os.path.py". '') >>> os.

Zielverzeichnis. Bei der Beschreibung der folgenden Funktionen benutzen wir häufig die String-Parameter „src” und „dst”.4 shutil-Modul Im vorigen Abschnitt hatten wir bereits eine Datei unter Benutzung des shutil-Modules kopiert. >>> >>> >>> >>> >>> fh = open("abc.py") ('/abc/xyz/beispiel'.copyfileobj(fh. "w") shutil. wird „dst” überschrieben.4 shutil-Modul 249 >>> os.21. vermuten die Kopierfunktion zunächst im os-Modul.txt". '') >>> os. Dieses Modul stellt eine plattformunabhängige Schnittstelle zur Verfügung. Existiert „dst” bereits. um Dateien und Dateibäume zu kopieren. dst) Wie copy. allerdings werden auch die Zugriffsrechte.txt") fhw = open("spam. fdst. . Dabei muss der Pfad dst schreibbar sein. Ansonsten wird ein IOError geworfen. die shutil noch nicht kennen. was Quelle in Deutsch bedeutet. dst) Kopiert die Datei „src” nach „dst”. das Quellverzeichnis. dst steht dabei als Abkürzung für destination.splitext("/abc/xyz/beispiel") ('/abc/xyz/beispiel'. Entspricht „dst” einem Ordner. was in Deutsch Ziel bedeutet. Wenn die Datei unter dst bereits existiert.path. wie viele Bytes jeweils gelesen und anschließend gespeichert werden. der Eigentümer und der Zeitstempel mitkopiert. Der Befehl entspricht dem Unix/Linux-Befehl: „cp -p src dst” copyfileobj(fsrc. length=16384) Der Inhalt des zum Lesen geöffneten Dateiobjekts „fsrc” wird in das zum Schreiben geöffnete „fdst”-Objekt kopiert.8 ■ copyfile(src. wird innerhalb dieses Ordners eine Datei mit dem Dateinamen von src angelegt oder überschrieben.path.path. wird sie überschrieben.close() fhw.close ■ ■ ■ 7 8 src steht für das englische Wort source. und „dst” steht für die Zieldatei bzw.splitext("/abc/xyz/beispiel. copy(src. copy2(src.py') >>> os.fhw) fh. Viele Python-Nutzer. '') >>> 21. entfernen oder zu archivieren. falls diese Datei bereits in „dst” existiert. Mit dem optionalen Parameter kann gesteuert werden. dst) Kopiert die Datei src nach dst unter Beibehaltung der Zugriffsrechte.splitext("/abc/xyz/beispiel/") ('/abc/xyz/beispiel/'. '. Dabei bezeichnet „src” die Quelldatei7 bzw.

['b2."xyz") ■ ■ Der Baum „dst” darf noch nicht existieren. ['b2.txt'. line 152. ausgeht. []). ['a'. 'a'. []).txt']). ('abc/c'.5 (Weitere Funktionen im Überblick) kennengelernt haben: >>> import shutil >>> shutil.txt']). ['a1. 'b'.copytree("abc". mtime. also ohne Links. ('abc/xyz/a'. line 203. ('abc/xyz/b'. ('abc/a'. [].txt']). atime.walk("abc") <generator object walk at 0xb71d6054> >>> list(os.h. 'b1. 'a2. ['b2. copy_function=<function copy2>. symlinks=False.walk("abc")) [('abc'. wenn man von Pfadnamen in kanonischer Darstellung."abc/xyz") >>> list(os. []. das wir bereits in Beispiel 21. 'b3. d.3. []. []).txt'. 'b3. ['a1. 'b3. wenn es sich bei dem Pfadnamen „dst” um einen Pfad handelt. [].txt']). line 1.txt'.copytree("abc". ['c1.txt'. []. ['xyz'.copytree("abc". ignore_dangling_symlinks=False) Ein Verzeichnisbaum „src” wird rekusiv in einen Verzeichnisbaum „dst” kopiert. ignore=None."xyz") Traceback (most recent call last): File "<stdin>". ('abc/a '. der im Innern des durch „src” bezeichneten Teilbaumes liegt.py". 'c'].txt']). copystat(src. ['c1.txt '])] >>> shutil. 'b'.py". 'c']. Wir kopieren nun den gesamten Teilbaum „abc” in das Verzeichnis „abc” mit dem neuen Namen „xyz”. [].walk("abc")) [('abc'. 'b'. Mithilfe der Funktion walk des Moduls os schauen wir uns die Bäume jeweils an: >>> import shutil >>> import os >>> os. dst) Die Bits für die Zugriffsrechte werden von „src” nach „dst” kopiert. in makedirs mkdir(name.txt']). []. []. 'a2. also parallel zu den Verzeichnissen „a”. in copytree os. txt'.2/os.txt'])] >>> .250 21 Systemprogrammierung ■ copymode(src. Wir betrachten das Beispiel. 'c']. erhalten wir deshalb eine Fehlermeldung: >>> shutil. ' b1. copytree(src.txt'. „b” und „c”.makedirs(dst) File "/usr/lib/python3. ('abc/b'. flags. mode) OSError: [Errno 17] File exists: 'xyz' >>> Interessant ist vor allen Dingen der Fall. dst) Alle Statusinformationen. Wenn wir obigen Befehl wieder anwenden. In anderen Worten „src” ist ein Teilstring von „dst”. 'b1. [].mode bits. ['a'.txt'. ['a1. 'a2.txt']). ['c1. ('abc/xyz'. dst. werden von „src” nach „dst” kopiert.txt'. ('abc/xyz/c'. ('abc/c'. (' abc/b'. in <module> File "/usr/lib/python3.2/shutil.txt'.

zip']. Falls ein symbolischer Link nicht existiert. '. Als Default wird copy2() benutzt. ('gztar'. Die Funktion liefert den vollständigen Pfad und Namen der erzeugten Archivdatei zurück. ('zip'. Man kann auch eine eigene Funktion übergeben. logger=None) Eine Archivdatei wird erzeugt.gz'. die von copytree besucht werden. werden symbolische Links im Quellbaum auch als symbolische Links im Zielbaum realisiert. Der vollständige Name der Archivdatei ergibt sich mit dem Parameter „format”. wie zum Beispiel das zip. ['. 'ZIP file')] >>> ■ ignore_patterns(*patterns) Diese Funktion kann als „ignore”-Parameter bei copytree benutzt werden. verbose=0. ('tar'.oder tar-Format.4 shutil-Modul 251 Falls der optionale Parameter symlinks auf True gesetzt ist. setzt man den optionalen Parameter ignore_dangling_symlinks auf True. Extension. owner=None. werden die Inhalte der Dateien. ■ get_archive_formats() Liefert eine Liste der unterstützten Formate zum Archivieren und Dearchivieren zurück. Das aufrufbare Objekt liefert dann eine Liste „ignored_names” zurück. was per Default der Fall ist. format. als Parameter. 'uncompressed tar file') . Jedes Element dieser Ergebnisliste ist ein Zweiertupel mit dem Namen und einer Beschreibung: >>> shutil. ('tar'. „tar”. Jedes Element der Ergebnisliste entspricht einem Tupel der Form: (Name. Die „patterns” entsprechen glob-Pattern der Linux-Shells. die erzeugt werden soll. ('gztar'. ■ . Um diese Fehlermeldung zu unterdrücken.21. "gzip'ed tar-file"). auf die symbolische Links zeigen. Es erhält den Pfad „src” und eine Liste der Namen „names”. „base_name” ist der Name der Archivdatei. root_dir=None.tgz ']. ('zip'. ohne die übliche Endung. Beschreibung) >>> shutil. wird dies als Fehler ausgegeben.tar. "gzip'ed tar-file"). 'uncompressed tar file'). base_dir=None. „bztar” oder „gztar”. 'ZIP file')] >>> ■ get_unpack_formats() Liefert eine Liste der Dekomprimierformate zurück. wie die Dateien zu kopieren sind.bz2']. "bzip2'ed tar-file"). kopiert. group=None.listdir() erzeugt wird. dry_ run=0. Der optionale „ignore”-Parameter ist ein aufrufbares Objekt wie zum Beispiel eine Funktion. ['.get_archive_formats() [('bztar'.tar']. Ist der Parameter auf False gesetzt. die festlegt. ['. Dazu dient der optionale Parameter copy_function. also „zip”. so wie sie von os. welcher der Extension des Archivformats entspricht. die nicht von copytree kopiert werden sollen. Dafür stehen die gängigen Archivierungsformate zur Verfügung. make_archive(base_name. ['. Also eine Liste der Namen. "bzip2'ed tar-file").get_unpack_formats() [('bztar'.

"bztar". denn „root_dir” ist auf „.h.tar./abc") Traceback (most recent call last): File "<stdin>".py". d.252 21 Systemprogrammierung Der vollständige Name der Archivdatei wird also durch die folgende Konkatenation gebildet: base_name + + ¨+ ¨ format „root_dir” entspricht dem Root-Verzeichnis. line 1937. "bztar".lstat(name) OSError: [Errno 2] No such file or directory: '.py". in unserem Beispiel das Homeverzeichnis des Benutzers „bernd”. „base_dir” ist das Root-Verzeichnis des zu archivierenden Teilbaums. ".py". ". ".tar. Dieser Baum muss sich im aktuellen Unterverzeichnis befinden. Falls der Zielpfad „dst” ein Verzeichnis oder ein symbolischer Link auf ein Verzeichnis ist.2/shutil. in add tarinfo = self.make_archive("my_archive".gettarinfo(name. line 2065. "/home/ bernd/tmp/abc") '/home/bernd/my_archive.bz2' >>> ■ move(src. in <module> File "/usr/lib/python3. base_dir. in _make_tarball tar. "/home/bernd/".make_archive("my_archive". Nun rufen wir obigen Befehl in einem Verzeichnis auf./abc” befindet. eine Datei oder ein Verzeichnis an einen anderen Speicherort zu verschieben.make_archive("my_archive". wird der Teilbaum „abc” unabhängig vom Wert von root_dir gefunden. in gettarinfo statres = os.2/shutil. von dem relative Pfadnamen in base_dir beginnen. filter=_set_uid_gid) File "/usr/lib/python3.bz2' >>> Die erzeugte Archivdatei befindet sich nun im aktuellen Verzeichnis. ". in dem sich kein Unterverzeichnis „. "bztar".2/tarfile.".” gesetzt: >>> import shutil >>> shutil. Wir erhalten dann eine Fehlermeldung: >>> import shutil >>> shutil./abc' >>> Falls wir den Pfad in base_dir nicht relativ.add(base_dir. Die Archivdatei wird jedoch im von root_dir definierten Pfad abgelegt: >>> import shutil >>> shutil./abc” archiviert. also beispielsweise eine Datei oder .py". arcname) File "/usr/lib/python3./abc") '/home/bernd/tmp/my_archive. „move” dient dazu.2/tarfile. line 426. dann wird das durch „src” bezeichnete Objekt.". in make_archive filename = func(base_name. dst) Dieser Befehl ist ähnlich wie der Unix/Linux-Befehl „mv”. **kwargs) File "/usr/lib/python3. Im folgenden Beispiel wird ein Verzeichnisbaum mit dem Namen „. line 585. line 1. sondern absolut angeben.

„path” der Pfad ist. „extract_dir” ist der Name des Zielverzeichnisses. Falls „ignore_errors” gesetzt ist. Falls „onerror” gesetzt ist. „filename” ist der Name des Archivs. ein Zeiger auf ein aufrufbares Objekt. „function” ist eine Funktion. in das Verzeichnis „dst” verschoben. ■ unpack_archive(filename. oder „gztar” oder ein anderes registriertes Format (siehe register_archive_format). extensions. d. extract_dir=None. function. Außerdem wird „description” von der get_unpack_formats()-Funktion zurückgeliefert. d. wird das aktuelle Arbeitsverzeichnis als Zielverzeichnis verwendet. function. Der optionale Parameter „extra_args” ist ein sequentielles Datenobjekt mit (name. value)-Tupels. wobei „func” entweder „os.remove”.21. description=”) Analog zu register_archive_format allerdings für ein Format zum Entpacken. dann wird dieses Objekt mit den Argumenten (func. wird es erzeugt. werden Fehler ignoriert. extra_args=None. erhält man eine Fehlermeldung. ■ rmtree(path.exc_info() zurückgeliefert wurde. ■ register_unpack_format(name. die benutzt wird. „name” ist der Name des Formats. um ein Archiv zu entpacken. wird ein ReadError generiert. sofern die entsprechenden Rechte vorhanden sind. Ist „src” ein Verzeichnis. Wenn das Verzeichnis „dst” noch nicht existiert. Falls . der den Fehler verursacht hat. onerror=None) Ein Verzeichnisbaum „path” wird rekursiv gelöscht. ignore_errors=False.rmdir” ist. description=”) Ein Archivformat registrieren.h. Falls die Funktion mit dem Archiv nicht klarkommt. path. Dies aber nur. value)-Tupels.listdir”. wird diese überschrieben. oder „os. „extensions” ist eine Liste von Extensions für dieses Format. sondern eine Datei ist. die der Funktion „function” übergeben werden. Wenn das Ziel „dst” bereits existiert. ■ register_archive_format(name. Falls sowohl „ignore_errors” auf False gesetzt ist und „onerror” auf None. „description” ist optional und kann die Beschreibung des Formats enthalten. wohin das Archiv entpackt werden soll. also eines der Formate „zip”. dann wird eine Ausnahme generiert. „description” ist optional und kann die Beschreibung des Formats enthalten. „os. Der optionale Parameter „extra_args” ist ein sequentielles Datenobjekt mit (name. extra_args=None. um ein Archiv zu erzeugen.h.4 shutil-Modul 253 ein Verzeichnis. Als Parameter wird ein Archiv übergeben. aber kein Verzeichnis. es nicht entpacken kann. und exc_info ist ein Tupel. „format” ist das verwendete Archivierungsformat. format=None) Entpackt ein Archiv. die der Funktion „function” übergeben werden. Falls dieser optionale Parameter nicht angegeben wird. „tar”. exc_info) aufgerufen. Außerdem wird „description” von get_archive_formats()-Funktion zurückgeliefert. falls es sich bei „src” auch um eine Datei handelt. „function” ist eine Funktion („callable”). was von sys. „name” ist der Name des Formats. die benutzt wird.

254 21 Systemprogrammierung kein Format angegeben wird. wird ein ValueError generiert. Falls keiner gefunden wird. prüft „unpack_archive”. unregister_unpack_format(name) Entfernt das pack-Format aus der Registrierung. ■ unregister_archive_format(name) Ein Format wird deregistriert. ob es für die Dateiendung einen registrierten Entpacker gibt. ■ .

1 Fork Forks Schon lange vor der Biologie hat sich die Informatik mit dem Klonen beschäftigt.2 Fork in Python Falls Sie Python nur unter Windows benutzen. Der Kindprozess übernimmt die Daten und den Code vom Elternprozess und erhält vom Betriebssystem eine eigene Prozessnummer. können Sie den Rest des Kapitels getrost überspringen. Im letzteren Sinn wird es bei Betriebssystemen verwendet.1 Zellteilung Ein vom Betriebssystem bereitgestellter Systemaufruf. Gabelung. Der Kindprozess läuft als . Verzweigung und als Verb gabeln.22 22. Sie laufen aber unter Linux und Unix. welche dann als Kindprozess des erzeugenden Programmes läuft. In der Software-Entwicklung bezeichnet ein Fork eine Abspaltung von einem (Haupt-) Projekt. Beim Systemaufruf os. fork bedeutet in Englisch Gabel.fork erzeugt der aktuelle Prozess eine Kopie von sich selbst. eine sogenannte PID (engl. Die Fähigkeit einiger Dateisysteme zur Unterteilung von Dateien ■ ■ 22. der den bestehenden Prozess aufspaltet – und dabei eine exakte Kopie des Prozesses erzeugt – und dann beide Prozesse gewissermaßen parallel laufen lässt. aufspalten und verzweigen. Aber man nannte es nicht Klonen sondern Forken. Prozesse werden aufgespalten – geklont würde man heute eher sagen – und führen dann ein eigenständiges „Leben”. vor allem bei Unix und Linux. „Process IDentifier”). Aber es bedeutet auch eine Aufspaltung oder als Verb aufspalten. In der Informatik steht der Begriff Fork für die Bezeichnung verschiedener Sachverhalte: ■ BILD 22. da Forks unter Windows nicht unterstützt werden.

time def counter(count): for i in range(count): time. der sich beliebig oft forken kann. erhalten wir folgende Ausgaben: bernd@saturn:~/bodenseo/python/beispiele$ python3 fork. newpid) print("parent: %d. in denen wir jeweils vier printAusgaben im Sekundenabstand absetzen: import os. os.getpid())) . müssen wir das Modul os in Python importieren. Um Prozesse forken zu können. os. da sonst der Kindprozess in den Elternprozess zurückkehren würde.py parent: 5023. Im Elternprozess hat newpid einen von 0 verschiedenen Wert. Im Kindprozess hat newpid den Wert 0.256 22 Forks eigenständige Instanz des Programms.2 veranschaulicht nochmals.getpid(). und zwar zur input-Anweisung. Im Fehlerfall liefert fork() einen Wert kleiner 0 zurück. und kein Kindprozess wird erzeugt. in welchem Prozess man sich befindet.exit(0) in der child-Funktion ist notwendig. child: 5024 A new child 5024 q bernd@saturn:~/bodenseo/python/beispiele$ Das Diagramm 22._exit(0) os. count of [%s]' % (i. child: %d" % pids) if input( ) == 'q': break parent() Starten wir dieses Programm.getpid( )) def parent(): while True: newpid = os. Die exit-Anweisung os.sleep(1) print('%s. sodass die Ausführung im else-Teil der if-Anweisung fortfährt. sodass dort die Funktion child() aufgerufen wird.fork() if newpid == 0: child() else: pids = (os. Am Rückgabewert von fork() erkennt man. Sowohl der Kindprozess als auch der Elternprozess machen nach dem fork mit der if-Anweisung weiter. Das folgende Beispiel-Skript zeigt einen Eltern-Prozess (Parent). was genau beim Forking passiert: Im nächsten Skript erzeugen wir drei Kindprozesse. unabhängig vom Elternprozess. import os def child(): print('A new child '. solange man als Benutzer des Skripts kein „q” bei der Eingabeaufforderung eingibt. 0 kennzeichnet den Kindprozess.

count of [6430] 2. count of [6428] 1. count of [6429] 0.2 Forking for i in range(3): pid = os.py Another process spawned: 6428 Another process spawned: 6429 Another process spawned: 6430 Exit of parent process bernd@saturn:~/bodenseo/python/beispiele$ 0.fork() if pid == 0: counter(4) os._exit(0) else: print('Another process spawned: %d' % pid) print('Exit of parent process') Die Ausgabe sieht wie folgt aus: bernd@saturn:~/bodenseo/python/beispiele$ python3 fork_counter.22.2 Fork in Python 257 BILD 22. count of [6428] 0. count of [6430] 1. count of [6430] . count of [6429] 1. count of [6428] 2. count of [6429] 2.

count of [6430] bernd@saturn:~/bodenseo/python/beispiele$ . count of [6429] 3.258 22 Forks 3. count of [6428] 3.

Er stellt auch den Default-Wert dar. Dieser Modus ist ebenfalls abwärts kompatibel mit früheren Python-Versionen. In die Klemme geraten heißt im Englischen „to get oneself into a pickle”. Dabei handelt es sich um ein für Menschen lesbares Format. Aber was hat nun das Pökeln von sauren Gurken mit Python zu tun? Na ja. Dateien. können nicht mehr in Python 2. dass sie später wieder deserialisiert werden können. *. wurde mit 2. protocol=None. aber bei Python ist das wahrscheinlich – hoffen wir – seltener als in anderen Sprachen der Fall. Das optionale Argument für das Protokollargument „protocol” steuert die Art der Ausgabe: Protokollversion Beschreibung 0 ist die ursprüngliche Ablageart des Pickle-Moduls. ganz einfach: Python hat ein Modul.dump Beim Programmieren kommt es natürlich immer wieder mal vor.B.x empfohlenen Modus.h. vor Python3.x mit dem zugehörigen PickleModul bearbeitet werden. file.23 23. Es handelt sich hierbei um den von Python 3. einlegen) lassen sich Objekte serialisiert abspeichern. benutzt das alte Binärformat. wieder zu benutzen.1 Das Modul „pickle” Daten sichern mit pickle. eingeführt. d. Dieser Modus ist abwärts kompatibel mit früheren Python-Versionen. die in diesem Modus erzeugt werden. 1 2 3 . Aber jetzt wollen wir wieder seriös werden: Mit dem Modul pickle (dt.3. das „pickle” heißt. Aber „to pickle” bedeutet eigentlich einlegen oder pökeln. Dazu dient die Methode dump. die in ihrer allgemeinen Syntax wie folgt aussieht: BILD 23. und mit dem kann man Python-Objekte gewissermaßen einlegen.0 entwickelt. z. um sie später. also in anderen Sitzungen oder anderen Programmläufen. saure Gurken. und zwar so. Es stellt ein effizienteres „Pickling” zur Verfügung. wurde speziell für Python 3. fix_imports=True) -> None dump() schreibt eine „gepickelte” Darstellung des Objekts „obj” in das Dateiobjekt file.1 Daten „eingurken” dump(obj. dass man in die Klemme gerät.

Oct 19 2012. Im folgenden Beispiel schreiben wir eine Liste in eine Pickle-Datei: >>> >>> >>> >>> >>> import pickle cities = ["Bern". wird pickle versuchen. die neuen Python 3. pickle. "Basel". die mit pickle. wie wir die eben geschriebene Liste in einer anderen Sitzung wieder einlesen können: $ python3 Python 3.load Objekte.2] on linux2 Type "help". sodass der Pickle-Datenstrom mit Python 2.pkl"."rb") >>> staedte = pickle.load(f) >>> print(staedte) ['Bern'.fh) fh. Gallen'.pkl".3 (default.x-Namen auf die alten Modulnamen zu setzen. 19:53:57) [GCC 4.dump(cities.7.x lesbar ist.2 pickle.load(file) wieder eingelesen werden.close() 23.dump() in eine Datei geschrieben worden sind. 'Zürich'] . "credits" or "license" for more information. Gallen".2."wb") pickle. in welchem Format eine Datei erstellt worden ist.load erkennt automatisch.260 23 Das Modul „pickle” Wird das Argument „fix_imports” auf True gesetzt und hat „protocol” einen Wert kleiner als 3. 'St. können mit der Pickle-Methode pickle. 'Basel'. "copyright". >>> import pickle >>> f = open("data."St. Im Folgenden zeigen wir. "Zürich"] fh = open("data.

RA finden auch Verwendung. 24. Einen äußerst interessanten Aspekt von regulären Ausdrücken möchten wir nicht unerwähnt lassen: Die Syntax der regulären Ausdrücke ist in allen Programmiersprachen und Skriptsprachen gleich. Als Erfinder der regulären Ausdrücke gilt der amerika. die recht komplex sein können. ob ein Text oder ein String zu einem RA „matcht”. Der Begriff „Regulärer Ausdruck” kommt aus der Automatentheorie und der Theorie der formalen Sprachen. also z. Zu jedem regulären Ausdruck existiert ein endlicher Automat.1 Reguläre Ausdrücke Ursprünge und Verbreitung In diesem Abschnitt präsentieren wir eine detaillierte und anschauliche Einführung in die regulären Ausdrücke ganz allgemein. in Python.h. zutrifft. d. SED oder AWK.24 24. In Programmiersprachen werden reguläre Ausdrücken meist zur Filterung von Texten oder Textstrings genutzt.h. d. Dazu kann man statt regulärer Ausdrücke natürlich auch den .1 Reguläre Ausdrücke nische Mathematiker Stephen Cole Kleene. Perl. die sogenannten regulären Sprachen.2 Stringvergleiche Ein einfacher Sonderfall von regulären Ausdrücken stellt die Suche nach einem String in einem anderen String dar. um Textersetzungen durchzuführen. Außerdem werden sie von vielen Texteditoren wie zum Beispiel dem vi benutzt. Java. übereinstimmt oder passt. aber vor allen Dingen auch unter Python 3. zwei Gebieten der theoretischen Informatik. der die von dem Ausdruck spezifizierte Sprache akzeptiert.B. sie erlauben einem zu prüfen.BILD 24. In der theoretischen Informatik dienen reguläre Ausdrücke zur formalen Definition einer Sprachfamilie mit bestimmten Eigenschaften. der in den 1950er Jahren reguläre Mengen einführte.

Übrigens handelt es sich bei einem Substring bereits um einen regulären Ausdruck. Dazu wird erst geprüft. In dem String s = "xaababcbcd" soll geprüft werden. den wir im Abschnitt über sequentielle Datentypen bereits kennengelernt haben. ob die ersten Positionen übereinstimmen. Zuerst wird geprüft. Dies gilt. wie die Stringvergleiche durchgeführt werden. was wir durch die Farbe Rot kenntlich machen: Nun wird geprüft. aber s[2] ist ungleich sub[1]: Nun vergleichen wir s[2:5] mit sub. also s[0] == sub[0]. Für den nächsten Schritte benötigen wir wohl keine Erklärung mehr: . ob gilt s[1:4] == sub. was wir mit der Farbe Grün kenntlich machen. ob der Substring sub = "abc" vorkommt. Dann wird weiter verglichen. Im Folgenden zeigen wir Schritt für Schritt.262 24 Reguläre Ausdrücke „in”-Operator benutzen. ob sub[0] == s[1] erfüllt ist. ob das Wort„einfach” im String s vorkommt. Dies ist in unserem Beispiel nicht erfüllt. >>> s = "Reguläre Ausdrücke einfach erklärt!" >>> "einfach" in s True >>> Im obigen Beispiel wurde geprüft. wenn auch einen besonders einfachen. In diesem Fall stimmen sogar die ersten beiden Positionen des Substrings überein.

die zahlreiche Funktionen und Methoden zum Arbeiten mit regulären Ausdrücken zur Verfügung stellt. Ein regulärer Ausdruck entspricht einem String in Python. Teilstringsuche: In einem String wird geprüft. Es empfiehlt sich aber. Wortgrenzen zu bezeichnen. sie sind nicht built in. ob der reguläre Ausdruck „pattern” darin vorkommt. Man sieht dies am besten im folgenden Beispiel: Der reguläre Ausdruck „\b(\w+). „\b” wird in regulären Ausdrücken dazu verwendet. flags=0) Mit dieser Funktion wird ein String „string” durchsucht. in einem String festzustellen. 24. d. bevor es einen String an das re-Modul übergibt. der zu einem gegebenen regulären Ausdruck passt. re ist eine Standardbibliothek. denn es gilt s[4:7] == sub 24. Gibt es eine Übereinstimmung. Beginnen wir mit der wohl wichtigsten Funktion: search Syntax: re.3 Überlappungen und Teilstrings Mit regulären Ausdrücken können prinzipiell zwei Aufgaben bewerkstelligt werden: 1. wird None zurückgegeben. Das Problem liegt darin. ob ein Wort mehr als einmal vorkommt. die Gültigkeit von E-Mail-Adressen oder Postleitzahlen zu überprüfen. Um in Python mit regulären Ausdrücken arbeiten zu können. wenn man einen Rückwärtsschrägstrich (Backslash) verwendet.*\b\1\b” wird Ihnen zum jetzigen Zeitpunkt noch wie Hieroglyphen vorkommen. Benutzt man „\b” aber in einem String. dann gibt die Funktion search ein MatchObject zurück. ob es einen Teilstring gibt.3 Überlappungen und Teilstrings 263 Im nächsten Schritt kann eine vollständige Übereinstimmung gefunden werden.search(pattern. am besten immer einen raw-String zu verwenden. string. d. 2.24. ob solch ein String vollständig durch einen regulären Ausdruck überlappen lässt. auf den der reguläre Ausdruck „pattern” passt. Überlappungen: Feststellen.h. Falls „pattern” nicht passt. aber er dient dazu.4 Das re-Modul Reguläre Ausdrücke gehören nicht zum Grundumfang von Python. Zum Beispiel werden in Kontaktformularen im Internet reguläre Ausdrücke dazu verwendet. wird er von Python als Backspace (also Rückwärtsschritt) interpretiert. dass Python Rückwärtsschrägstriche bereits auswertet. also einen Teilstring in „string”. da es sonst häufig zu Problemen kommt. .h. muss man erst das Modul re importieren.

dass Python.B. wollen wir noch auf ein allgemeines Problem bei regulären Ausdrücken zu sprechen kommen. um die Sequenz. Dies gelingt auch. So werden auch alle Zeichen vor einem „\b” aus einem regulären Ausdruck gelöscht. So ist beispielsweise r"cat" ein regulärer Ausdruck. wenn wir einen raw-String verwenden. Unser Beispielausdruck r"cat" matcht beispielsweise die folgende Zeichenkette: „A cat and a rat can’t be friends.search übergeben wird.” Interessanterweise zeigt sich schon in diesem ersten Beispiel ein „beliebter” Fehler. t) >>> print(x) None >>> x = re. Ohne Raw-Strings müsste man jeden Backslash mit einem Backslash versehen.5 Matching-Problem Bevor wir mit der Besprechung der Syntax der regulären Ausdrücke beginnen. vor einer Interpretation durch den Python-Interpreter zu schützen1 : >>> s = "abc\\bde\\bf" >>> print(s) abc\bde\bf 24. diesen interpretiert. funktioniert es nicht: >>> import re >>> t = "Manchmal ist ein Wort doch kein Wort. können Sie diesen Abschnitt momentan überspringen.search("\b(\w+). um ihn später durchzuarbeiten. „\b”. Wenn Sie wollen.search(r"\b(\w+). also z. denn er enthält keinerlei Metazeichen (Funktionszeichen) mit Sonderbedeutungen. bevor es einen String an search übergibt." >>> x = re.*\b\1\b". Escape-Sequenzen werden aufgelöst.*\b\1\b". „\b” steht zum Beispiel für einen Backspace (Rückwärtsschritt): >>> s = "abc\bde\bf" >>> print(s) abdf Die Buchstaben „c” und „e” wurden gewissermaßen aus dem String gelöscht.SRE_Match object at 0x8e89220> Das liegt daran. Er gehört zu den wohl am einfachsten zu verstehenden Ausdrücken. Jeder String – also Strings ohne spezielle Zeichen mit Sonderbedeutungen – ist bereits ein regulärer Ausdruck. Dies geschieht aber nicht.264 24 Reguläre Ausdrücke Benutzt man in search einen normalen String statt eines Raw-Strings. Eigentlich will man Strings matchen. d. t) >>> print(x) <_sre. bevor dieser an re. in denen das Wort cat vorkommt. aber 1 englisch: escape .h.

climbed on the roof. Schlimmer sind jedoch eine ganze Menge zusätzlicher Wörter. aber wir erkennen die BILD 24.h.." aus? Er wird nun als nicht mehr passend eingestuft. wir erhalten positive Ergebnisse. „communicate”. vor und hinter dem Wort cat im regulären Ausdruck ein Leerzeichen einzufügen. die eine Teilmenge unserer gewünschten Menge C ist. called Oscar. Wir könnten auf die Idee kommen. . . Wie sieht es aber mit einem String "The cat.5 Matching-Problem 265 man erhält auch beispielsweise „cats”. Der >>> . In die. die wir gerne erkennen wollen. Wenn wir das Ergebnis ausdrucken.. die nicht gewünscht sind... Mittels search(expr. die folgenden Beispiele direkt in Python nachzuvollziehen."A cat and a rat can't be friends."): print "Der Ausdruck hat gepasst" else: print "Der Ausdruck hat nicht gepasst" Ausdruck hat gepasst if re. Durch diese Änderung würden wir nicht mehr auf Wörter wie „education”."A cat and a rat can't be friends.search("cow". während im negativen Fall ein „None” zurückgegeben wird. Ein Beispiel dafür erhalten wir..„over” matching sem Diagramm erkennt man auch eine Menge U (hellgrüner Kreis). Dann sind wir auch in der Lage. Der erste gefundene Teilstring wird zurückgeliefert.search("cat".s) wird ein String s nach dem Vorkommen eines Teilstrings untersucht. Wir haben dies im nebenstehenden Diagramm mengenmäßig veranschaulicht. >>> import re >>> x = re. wenn wir versuchen. wie man reguläre Ausdrücke in Python überprüfen kann.SRE_Match object at 0x7fd4bf238238> >>> x = re. „falsification”."A cat and a rat can't be friends. Mit diesem Wissen kann man reguläre Ausdrücke bereits in einem Python-Skript nutzen. .. ohne Näheres über die Match-Objekte zu wissen: >>> . unseren regulären Ausdruck zu verbessern. der auf den regulären Ausdruck expr passt. dass im positiven Fall ein sogenanntes Match-Objekt zurückgegeben wird. was möglicherweise noch erwünscht ist.search("cow".24.. „ramifications”. sehen wir. in denen die Buchstabenfolge „cat” als Teilstring vorkommt. Dies ist ein Fall von „under matching”.."A cat and a rat can't be friends. „falsification” und „ramification” hereinfallen..") >>> print x None Im vorigen Beispiel haben wir die Methode search aus dem re-Modul verwendet. also r" cat ". . Der dunkelgrüne Kreis C entspricht der Menge.2 „under” und Menge O (blauer Kreis). Dies ist ein Fall von „over matching”. C ist eine Teilmenge von O. if re.. „cattle” und viele andere.") >>> print x <_sre.. d.search("cat".. Zunächst wollen wir uns jedoch mal anschauen. also auch Wörter wie „education”."): print "Der Ausdruck hat gepasst" else: . Es ist wohl die am wichtigsten und am häufigsten benutzte Methode. Diese Problematik wird im Folgenden noch klarer.

. Den regulären Ausdruck könnte man so formulieren: r" . print("") . die mit „at” enden: Die regulären Ausdrücke bieten einen Metacharacter „.. „bat”. Eine Lösung. matched matched matched matched no match no match >>> 24. print("no match") . „sat” und andere. lernen wir im nun folgenden Unterabschnitt unserer Einführung kennen. wenn im Text ein „@at” oder „3at” stünde? Die matchen dann auch. „eat”.. der als Platzhalter für ein beliebiges Zeichen steht. und wir haben wieder ein over matching.7 Zeichenauswahl Durch eckige Klammern „[” und „]” können wir eine Zeichenauswahl definieren... „cat”.search(r".. Aber was ist.. die mit „at” enden. print "Der Ausdruck hat nicht gepasst" .6.266 24 Reguläre Ausdrücke ... dass wir im vorigen Beispiel nicht daran interessiert waren.1 Syntax der regulären Ausdrücke Beliebiges Zeichen Nehmen wir an. um dies zu umgehen.”... if re..6 24. Betrachten wir den folgenden regulären Ausdruck: r"M[ae][iy]er" . sondern dreibuchstabige Wörter.. i): .at". else: . Der Ausdruck hat nicht gepasst 24. Der Ausdruck in eckigen Klammern steht dann für genau ein Zeichen aus dieser Auswahl.at " Der reguläre Ausdruck matcht nun durch Leerzeichen isolierte dreibuchstabige Wörter. Dieser Ausdruck passt nun auch auf Wörter wie „rat”. das Wort cat zu finden.. Im Folgenden sehen wir obigen regulären Ausdruck in einer Anwendung: >>> import re >>> for i in cat_and_more: .

Das einzige andere Metazeichen innerhalb von eckigen Klammern ist das Caret-Zeichen (auch Textcursor oder Einschaltungszeichen genannt). Wenn es direkt hinter der öffnenden eckigen Klammer positioniert ist. Der Vorteil beim Schreiben wird sofort ersichtlich. aber keine Ziffer”. [^abc] bedeutet alles außer „a”. „b”. Wenn es nicht als erstes Zeichen steht. Sie können ihn also getrost überspringen. [a-e] ist eine abgekürzte Schreibweise für [abcde] oder [0-5] steht für [012345]. dann negiert es die Auswahl. [a^bc] bedeutet entweder ein „a”. den wir benutzt hatten. weil es am Anfang direkt nach der öffnenden Klammer steht. Wen das noch nicht überzeugt: Wie sieht es mit der Zeichenauswahl „ein beliebiger Klein. So bezeichnet der Ausdruck [-az nur die Auswahl zwischen den drei Zeichen „-”.oder Großbuchstabe” aus? [A-Za-z] Die umständliche Alternative überlassen wir der geneigten Leserin oder dem geneigten Leser :-) Aber es gibt noch eine Besonderheit mit dem Bindestrich. Man kann [ABCDEFGHIJKLMNOPQRSTUVWXYZ] oder [A-Z] schreiben. Das Gleiche gilt für [az-]. Dem großen M kann ein kleines „a” oder ein kleines „e” folgen. Frage: Welche Zeichenklasse wird durch [-a-z] beschrieben? Antwort: Das Zeichen „-”.2 Bei einem endlichen Automaten handelt es sich um ein Modell bestehend aus 2 englisch: finite state machine (FSM) . nämlich den Bindestrich „-”. also zum Beispiel eine Ziffer zwischen „0” und „5” oder ein Buchstabe zwischen „a” und „e”. aber keine anderen Zeichen.8 Endliche Automaten Dieser Abschnitt ist nicht zum weiteren Verständnis für die praktische Anwendung von regulären Ausdrücken notwendig. Ein endlicher Automat wird manchmal auch als Zustandsmaschine oder Zustandsautomat bezeichnet. also das ganze Alphabet der kleinen Buchstaben und der Bindestrich. zum Abschluss dann „er”. wenn er nicht unmittelbar nach der öffnenden eckigen Klammer oder vor der schließenden eckigen Klammer positioniert ist. und alle Zeichen zwischen „a” bis „z”. dann muss ein „i” oder „y” folgen. benötigt man sehr häufig die Auswahl zwischen ganzen Zeichenklassen. [^0-9] bezeichnet die Auswahl „irgendein Zeichen. Dafür gibt es bei der Notation für reguläre Ausdrücke ein reserviertes Sonderzeichen innerhalb der Zeichenauswahl.24.8 Endliche Automaten 267 Dieser Ausdruck passt auf vier verschiedene Schreibweisen des häufigen deutschen Familiennamens. dann hat es keine spezielle Bedeutung und bezeichnet nur sich selbst. wenn man die Zeichenauswahl „ein beliebiger Großbuchstabe” notieren will. um den Anfang und das Ende einer Zeichenklasse zu markieren. „a” und „z”. Der Bindestrich hat nur eine Sonderbedeutung. 24. wenn er innerhalb von eckigen Klammern steht. „b” oder „c”. „c” oder ein „^”. Statt einzelner Buchstaben. wie im vorigen Beispiel die Auswahl zwischen „e” oder „a” (in RE-Notation [ea]). und auch dann nur. Die Position des Caret-Zeichen innerhalb der eckigen Klammern ist entscheidend.

wenn ein leerer String zwischen einem \W und einem \w steht oder umgekehrt. Es ist nicht wesentlich für die Anwendung von regulären Ausdrücken. Sie BILD 24. alle Ziffern und der Unterstrich "_". es hängt davon ab. welches Zeichen vor und nach dem leeren String steht. Zustandsübergängen und Aktionen.4 Wortbegrenzer matchen leere Strings in Abhängigkeit von deren Nachbarschaft.). endlich ist. Vereinfachung im Diagramm: Eigentlich müsste es im Startknoten einen Zeiger geben.3 Endlicher Automat auf dem Startknoten. „b”. Wir wollen hier nur ein Beispiel liefern: einen endlichen Automaten zum Akzeptieren der Meyer/Meier/Mayer/MaierVarianten. die von „M” verschieden sind. Das heißt. \b passt zum Beispiel. Dies sind alle Klein. Ein gutes Beispiel hierfür ist sicherlich die Zeichenklasse. kann man das eben über endliche Automaten Gesagte getrost ignorieren. man bleibt solange BILD 24. matchen sie aber keine Zeichen. 24. was auf den ausgehenden Pfeilen vorhanden ist. Das entspricht der folgenden Zeichenklasse r"[a-zA-Z0-9_]" Deshalb gibt es für häufig vorkommende Zeichenklassen vordefinierte Kürzel: Die vordefinierten Zeichenklassen \b und \B der vorigen Übersicht werden häufig nicht richtig oder gar falsch verstanden. bestimmte Zeichenklassen auf die bisherige Art und Weise zu konstruieren.und Großbuchstaben.9 Vordefinierte Zeichenklassen Im Prinzip kann es sehr mühsam werden. „m”. Diesen Sachverhalt haben wir im nebenstehenden Diagramm veranschaulicht. das bedeutet. Wie bereits eingangs gesagt. es werden leere Strings zwischen \W und \W und leere Strings zwischen \w und \w gematcht. „3” usw. Man bezeichnet ihn als endlich. . der wieder auf den Startknoten zurückzeigt. die er annehmen kann. Während die anderen Klassen einzelne Zeichen matchen (so matcht beispielsweise \w unter anderem „a”. \B bezeichnet wie üblich das Komplement.268 24 Reguläre Ausdrücke Zuständen. weil die Zahl der Zustände. d. die einen gültigen Wortbuchstaben definiert. Von allen anderen Knoten müsste es auch einen Pfeil zum Startknoten zurück geben. wenn man kein Zeichen liest.h. wenn er zwischen \w und \W steht. wie man Zeichen liest. wenn man es nicht versteht.

Das Komplement von \s. print("I found one!") . verschiedene Schreibweisen des Namen Meyer zu matchen.24. im Inneren oder am Ende des Strings befindet. d. \W \b \B \\ 24. ist der Ausdruck r"M[ae][iy]er" in der Lage. Die andere Funktion hat unserer Meinung nach einen irreführenden Namen. die Funktion search().search(r"M[ae][iy]er". Also alle Zeichen außer den Ziffern. entspricht der Klassennotation [^0-9]. dass der String unmittelbar mit dem „M” des Namens beginnt? Das re-Modul von Python stellt zwei Funktionen zum Matchen von regulären Ausdrücken zur Verfügung. Aber egal wie. Dabei spielt es keine Rolle.h. entspricht [^ \t \n \r \f \v ]. entspricht [0-9]. Irreführend deshalb.. Passt wie \b auf den leeren String...line): . I found one! >>> Aber wie sieht es aus. Newlines usw. die Umlaute.. wenn wir nur Vorkommen des Namens direkt am Anfang eines Strings suchen. also [a-zA-Z0-9_]. match() ist eine Lösung auf unsere Fragestellung. aber nur. wenn dieser nicht am Anfang oder Ende eines Strings ist.h. ob sich der Name am Anfang. >>> import re >>> line = "He is a German called Mayer." >>> if re. entspricht der Klasse [ \t \n \r \f \v ]. d. Tabs. s) nur prüft. also z. aber nur. also Leerzeichen. s1)) . das Komplement von \d.. wenn dieser am Anfang oder Ende eines Strings ist. wie wir im folgenden Beispiel sehen: >>> >>> >>> >>> import re s1 = "Mayer is a very common Name" s2 = "He is called Meyer but he isn't German. denn sie heißt match(). Also alles außer Whitespace. Wenn die LOCALE gesetzt ist. ob eine Übereinstimmung am Anfang des Strings vorliegt.10 Anfang und Ende eines Strings Wie wir bereits ausgeführt hatten. Das Komplement von \w.search(r"M[ae][iy]er".1 Vordefinierte Zeichenklassen Kürzel \d \D \s \S \w Bedeutung Eine Ziffer. Alphanumerisches Zeichen plus Unterstrich." print(re. Passt auf den leeren String.B. matcht es auch noch die speziellen Zeichen der LOCALE. Ein Backslash. Eine der beiden haben wir bereits kennengelernt. Ein Whitespace.10 Anfang und Ende eines Strings 269 TABELLE 24. weil match(re_str.

s.270 24 Reguläre Ausdrücke <_sre. egal in welcher Schreibweise. dass der Multiline-Modus keinen Einfluss auf die matchMethode hat. s2)) None >>> Auf diese Art können wir zwar den Anfang eines Strings matchen. Außer im MULTILINE-Modus. aber diese Methode funktioniert nur in Python.search(r"M[ae][iy]er". re.match(r"M[ae][iy]er". re. s1) <_sre.search(r"^M[ae][iy]er".search(r"^M[ae][iy]er". s1)) <_sre.SRE_Match object at 0xb724a0c8> >>> print(re.SRE_Match object at 0xb724a0c8> >>> print(re.SRE_Match object at 0xb724a100> >>> print(re. re. s2)) <_sre.SRE_Match object at 0xb724a0c8> >>> print(re. >>> s = s2 + "\n" + s1 >>> print re.SRE_Match object at 0xb724a100> >>> print(re. .M)) <_sre. ob man sich im Multiline-Modus befindet oder nicht. der reguläre Ausdruck mit einem führenden „^” muss also auf den Anfang des Strings passen.search(r"^M[ae][iy]er". wenn wir die beiden Strings s1 und s2 auf nachfolgende Art zusammenfügen? s = s2 + "\n" + s1 Der String beginnt nicht mit einem Maier. s) None >>> Der Ausdruck konnte nicht matchen. s. Einfügezeichen) stellt sicher." >>> print re. wenn wir den MULTILINE-Modus zuschalten: >>> s = s2 + "\n" + s1 >>> print(re.MULTILINE)) <_sre. >>> import re >>> s1 = "Mayer is a very common Name" >>> s2 = "He is called Meyer but he isn't German. dann kann der Ausdruck immer auf ein Newline-Zeichen folgen. Deshalb ändert sich das Ergebnis.search(r"^M[ae][iy]er".SRE_Match object at 0x7fc59c5f26b0> >>> print re.match(r"^M[ae][iy]er". Das Zeichen „^” (Textcursor. d. s.match(r"M[ae][iy]er".h.search(r"^M[ae][iy]er". Aber die Syntax der regulären Ausdrücke stellt eine andere Möglichkeit zur Verfügung. match() prüft nie etwas anderes als den Anfang des Strings unabhängig davon. s2) None Aber was passiert.M)) None >>> Das vorige Beispiel zeigt auch. Aber der Name kommt nach einem Newline-Zeichen vor. dass der nachfolgende reguläre Ausdruck nur direkt auf den Anfang des Strings angewendet wird.

SRE_Match object at 0xb724a138> >>> Python. dann irren Sie sich. sieht ähnlich aus.")) Python. Wenn wir nun versuchen.")) Python and Perl.11 Optionale Teile 271 Damit haben wir die Prüfung für den Anfang eines Strings erledigt.\nSome prefer Java or 24. Unser finaler Mayer-Erkenner sieht nun wie folgt aus: r"M[ae][iy]e?r" Ein Fragezeichen kann auch hinter einer runden Klammer stehen. dass uns noch etwas fehlt: Wie können wir sagen: „e kann. "Meier". es darf kein weiteres Zeichen zwischen dem regulären Ausdruck und dem Newline des Strings stehen.$".$".$". aber muss nicht vorkommen”? Dafür hat man in der Syntax der regulären Ausdrücke dem Fragezeichen eine Sonderbedeutung verpasst.search(r"Python\. aber nicht vorkommen muss. "Meyer".search(r"Python\. in der das „e” vor dem „r” „verloren” gegangen ist. einen passenden regulären Ausdruck zu konstruieren.\nSome prefer Java or Python."I like Perl. also „der Buchstabe e kann. dann muss der Ausdruck auf das Ende des Strings passen."I like None >>> print(re. So gibt es insbesondere in Bayern die Variante. fällt uns auf.")) None >>> print(re. ob ein regulärer Ausdruck auf das Ende eines Strings passt. Dann bedeutet das. Der Ausdruck „e?” bedeutet gerade. d.$". Es gibt noch weitere Varianten in vielen anderen Schreibweisen. was wir wollen. dass wir bereits alle Schreibweisen der Namen Mayer und Co. erfasst hätten. dass der komplette Unterausdruck innerhalb der Klammern vorkommen kann. re.search(r"Python\.".11 Optionale Teile Falls Sie denken. "Maier"]. "Mair"] zusätzlich zu unserer alten Liste ["Mayer". Dazu erhält das „$”-Zeichen eine Sonderbedeutung.M)) <_sre. Wird ein regulärer Ausdruck von einem „$”-Zeichen gefolgt."I like <_sre.h. Dadurch erhalten also noch vier weitere Schreibweisen: ["Mayr". aber muss nicht vorkommen”.24. Wir demonstrieren dies im folgenden Beispiel: >>> print(re. Die Prüfung."I like Perl.SRE_Match object at 0xb724a138> >>> print(re.search(r"Python\. "Meir". "Meyr". Mit dem folgenden Ausdruck können wir Teilstrings mit „Feb 2011” oder „February 2011” erkennen: r"Feb(ruary)? 2011" .

indem Sie weitergelesen haben. Also die Zeile. nur dass der Plus-Operator wenigstens ein Vorkommen des Zeichens oder Teilausdrucks verlangt. Folgt ein Stern „*” einem Zeichen oder einem Teilausdruck. dass dieses Zeichen oder der Teilausdruck keinmal oder beliebig oft vorkommen oder wiederholt werden darf. * sind zu unspezifisch für diesen Fall. lassen sich bestimmte Eigenschaften nicht in regulären Ausdrücken abbilden. und die folgende Lösung ist sicherlich zu umständlich: r"^[0-9][0-9][0-9][0-9] [A-Za-z]+" . in der die Postleitzahl und der Ortsname steht. das Fragezeichen. r". Ein Zeichen oder ein in runden Klammern eingeschlossener Teilausdruck wird entweder einmal oder keinmal „wiederholt”. dass wir Adresszeilen von Briefumschlägen in der Schweiz lesen wollen. Sie haben also das Plus-Zeichen verwendet? Das ist super. Außerdem hatten wir zu Beginn dieser Einführung einen anderen Quantor kennengelernt. Lösung: r"[0-9][0-9] . + bzw. was wir bisher in unserem Kurs behandelt haben Also dann. oder Sie wissen bereits mehr über reguläre Ausdrücke als das. gefolgt von einem Leerzeichen und dem Ortsnamen. aber auch auf den leeren String.*" passt auf eine beliebige Folge von Zeichen und auf den leeren String. Beispielsweise benötigt man immer wieder Möglichkeiten darzustellen.272 24 Reguläre Ausdrücke 24. was wir bisher an syntaktischen Mitteln kennengelernt haben. Lösung unserer Aufgabe mit dem "+Operator: r"[0-9]+ . r"[0-9]. Nehmen wir an. dass man bestimmte Teilausdrücke wiederholen will. wenn wir bereits beim Plus-Operator sind: Mit dem Plus-Operator kann man auf angenehme Art und Weise die vorige Übung lösen. Es handelte sich um den Stern-Operator.*" Der obige Ausdruck passt auf eine beliebige Folge von Ziffern.h.*" Aber auch mit Plus. die mit einer Folge von Ziffern – wenigstens einer – beginnen und von einem Leerzeichen gefolgt werden.12 Quantoren Mit dem. der Strings matched. d. Eine Form von Wiederholung hatten wir gerade eben kennengelernt.und Sternchen-Operator fehlt noch etwas Wichtiges: Wir wollen in bestimmten Situation die exakte Anzahl der Wiederholungen oder eine minimale oder maximale Anzahl von Wiederholungen angeben können. aber in diesem Fall haben Sie wohl gemogelt.*" So. Übung: Schreiben Sie einen regulären Ausdruck. Im Prinzip funktioniert der PlusOperator wie der Sternchen-Operator. dann heißt dies. ohne dass wir in besonderer Weise auf ihn eingegangen sind. eine vierstellige Postleitzahl.

5} [A-Z][a-z]{2. Nick Riviera 555-NICK Earn Cash For Your Teeth 555-6312 Family Therapy Center 555-HUGS Homer Jay Simpson (Plow King episode) 555-3223 Homer Jay Simpson (work) 555-7334 Jack Neu 555-7666 Jeb Neu 555-5543 Jennifer Neu 555-3652 Ken Neu 555-8752 Lionel Putz 555-5299 In dieser Liste befinden sich Leute. die den Namen Neu führen und deren Vorname mit einem „J” beginnt. aber keine Beschränkung nach oben”. [0-9]{4.}" Allgemein gilt: {min. {. Genau. die nach Deutschland gehen. und {min.to}.} ist eine Abkürzung für „höchstens min-Mal. Ein praktisches Beispiel in Python Bevor wir fortfahren. Montgomery Burns 555-0113 Canine College 555-7201 Canine Therapy Institute 555-2849 Cathy Neu 555-2362 City of New York Parking Violation Bureau 555-BOOT Dr. Die selbst auferlegte Aufgabe besteht nun darin. Dazu schreiben wir ein Python-Skript. Montgomery Burns 555-0001 C. das diese Zeile einliest und Zeile für Zeile bearbeitet: import re 3 Das gesamte Telefonbuch finden Sie in unserem Programm. DIE SIMPSONS.} beschreiben. die aus der berühmten amerikanischen Serie. die mit Nachnamen „Neu” heißen. max} ist eine abgekürzte Schreibweise für {0. deren Name aus weniger als drei Buchstaben besteht. Allison Neu 555-8396 Bob Newhall 555-4344 C. . Nun wollen wir auch noch Briefe mit erfassen.und Beispielverzeichnis. Julius Hibbert 555-3642 Dr. Diesen Umstand können wir mit [A-Za-z][3. diejenigen Leute zu finden. möchten wir eine kleine praktische Übung mit regulären Ausdrücken in Python einschieben. Postleitzahlen haben bekanntlich eine Stelle mehr in Deutschland.12 Quantoren 273 Glücklicherweise bietet die Syntax der regulären Ausdrücke eine optimale Lösung: r"^[0-9]{4} [A-Za-z]*" Nun wollen wir unseren regulären Ausdruck noch weiter verbessern. max}: mindestens min-Mal und höchsten max-Mal. dass wir mindestens 4 Ziffern. dass es keine Stadt oder keinen Ort in der Schweiz gibt.24. Nehmen wir an. aber höchstens 5 erwarten: r"^[0-9]{4. Dazu haben wir ein Telefonbuch3 der Simpsons.5} bedeutet.

die man im folgenden Beispiel im selbsterklärenden Einsatz sieht: >>> import re >>> mo = re. wenn der reguläre Ausdruck gepasst hat.und die Endposition. und ansonsten nur ein None. Bevor wir jedoch mit Rückwärtsreferenzen weitermachen.close() Startet man das Programm.search("[0-9]+".end() 23 . 2013") >>> mo. also welcher Teilstring. \n (n = 1.py Jack Neu 555-7666 Jeb Neu 555-5543 Jennifer Neu 555-3652 24.. 24.line): print line. . wollen wir noch einen Paragraphen über Match-Objekte einfügen.search(r"J. dass Python oder genauer die Methode re. back references).1 Match-Objekte Bisher waren wir immer nur daran interessiert. Uns interessierte bisher nicht. span(). ob ein Ausdruck gepasst hatte oder nicht. erhält man folgende Ausgabe: $ python3 phone_numbers.group() '232454' >>> mo.13 Gruppierungen und Rückwärtsreferenzen Ausdrücke lassen sich. wie bereits erklärt.span() (17.search() ein MatchObjekt zurückliefert.274 24 Reguläre Ausdrücke fh = open("simpsons_phone_book. was gepasst hatte. Date: February 12..13. die wir im Folgenden benötigen. mit runden Klammern „(” und „)” zusammenfassen.txt") for line in fh: if re. wo der Match im String stattfand.*Neu". Eine andere Information wäre. ) bezeichnet die n-te Gruppierung. also die Start.rstrip() fh. Dies bezeichnet man als Rückwärtsreferenzen (engl. 23) >>> mo. Die gefundenen Übereinstimmungen der Gruppierungen werden von Python abgespeichert. Dadurch wird deren Wiederverwendung im gleichen regulären Ausdruck an späterer Stelle ermöglicht. "Customer number: 232454. Ein match-Objekt enthält unter allem die Methoden group(). Wir nutzten die Tatsache.start() 17 >>> mo. 2. start() und end(). 3.

Ruft man group mit einem Integer-Argument n auf. Date: February 12.m): >>> import re >>> mo = re. In einer Datei (z. auf den der reguläre Ausdruck passt. Dann wird kein String zurückgeliefert.group(1.txt”) steht folgender Inhalt: <composer>Wolfgang Amadeus Mozart</composer> <author>Samuel Beckett</author> <city>London</city> Wir möchten diesen Text automatisch in folgendes Format umschreiben: composer: Wolfgang Amadeus Mozart author: Samuel Beckett city: London Dies lässt sich mittels Python und regulären Ausdrücken mit folgendem Skript realisieren. 2013' >>> mo. 2013') Ein sehr intuitives Beispiel stellt das Lesen von korrespondierenden schließenden Tags von XML oder HTML dar.*: (.B. sondern ein Tupel mit den Werten von group(n) und group(m). group(n. 2013' >>> mo.search("([0-9]+). auf den die n-te Gruppe gepasst hatte.group(1) '232454' >>> mo.und Endwert gibt es noch zwei Funktionen start() und end(). 2013") >>> mo. Für den Anfangs. wird der reguläre Ausdruck so weiter ausgeführt. Date: February 12.group(m)) ist gleich group(n. als hätte er von Anfang an „<composer>(.13 Gruppierungen und Rückwärtsreferenzen 275 >>> mo. "Customer number: 232454. Zuerst enthält \1 den Wert „composer”: Nachdem der Ausdruck das erste „>” erreicht hat.2) ('232454'.*)</composer>” gelautet. z. Alles.B. Wird group() ohne Argumente aufgerufen. was zwischen „<” und „>” steht. Man kann group() auch mit mehr als einem Integer-Wert aufrufen. Der reguläre Ausdruck funktioniert wie folgt: Er versucht erst das Symbol „<” zu finden. der auf den RE gepasst hat. bis er auf das Größerzeichen „>” stößt.group(2) 'February 12. das den Anfangs.und Endwert des Substrings enthält.m). Danach liest er eine Gruppe von Kleinbuchstaben. dass span()[0] dem Wert von start() und span()[1] dem Wert von end() entspricht. „tags. wird in einer Rückwärtsreferenz (back reference) gespeichert.24. liefert es den Substring zurück. Also es gilt (group(n). und zwar unter \1.span()[1] 23 >>> Diese Methoden sind nicht schwierig zu verstehen: span() liefert ein 2er-Tupel zurück.group() '232454. 'February 12.*)". liefert es den Substring zurück. Das zugehörige Python-Skript: .span()[0] 17 >>> mo. wobei gilt.

000 Zeilen mit Postleitzahlen mit den zugehörigen Städtenamen sowie weiteren Informationen. \3. Dateien.9.14 Umfangreiche Übung In dieser Übung geht es darum. d. Gegeben ist eine Telefonliste der Simpsons. getrennt durch ein Leerzeichen.9."Bayern" .group(2)) Wenn es mehr als ein Klammerpaar (runde Klammern) innerhalb eines regulären Ausdrucks gibt. \2. zuerst der vollständige Name und dann die Telefonnummer: $ python3 simpsons_phone_book. aber wenn eine Telefonnummer existiert.txt") for i in fh: res = re."München". Montgomery".. "555-7334 Simpson..276 24 Reguläre Ausdrücke import re fh = open("tags.group(1) + ": " + res.*)</\1>"."Nürnberg"."Bayern" 80331.group(2) + " " + res.group(1)) 24. Allison"."München".i) print(res. Nicht jeder Eintrag enthält eine Telefonnummer.\s+(.group(3) + " " + res.search(r"<([a-z]+)>(. "Burns. Montgomery Burns Lionel Putz 555-5299 Homer Jay Simpson 555-7334 Das folgende Python-Programm löst die Aufgabe: import re l = ["555-8396 Neu. Die erste Datei beinhaltet nahezu 15. unter Benutzung von regulären Ausdrücken zusammenbringen. Stadt". dann steht sie am Anfang des Strings. "555-5299 Putz. Die Liste soll in der folgenden Form ausgegeben werden. der Nachname.py Allison Neu 555-8396 C."Nürnberg. die Informationen aus zwei Listen.h.*)". Dann folgt. entry) print(res. dann sind die Rückwärtsreferenzen in der Reihenfolge der Klammern durchnummeriert: \1. Durch ein Komma getrennt folgen dann Nachnamen. d. Es folgen ein paar willkürlich ausgewählte Zeilen zur Verdeutlichung und zur Findung von regulären Ausdrücken: 90402.9564. Homer Jay"] for entry in l: res = re. C.h.search(r"([0-9-]*)\s*([A-Za-z]+). Übung: Im nächsten Beispiel werden drei Rückwärtsreferenzen benutzt.9184. Lionel". .

729 Baden-Württemberg Die Aufgabe besteht nun darin.10041. Stadt".8335.8111. Stadt".8."Bodenseekreis".7314. Stadt".8."Friedrichshafen".884 Nordrhein-Westfalen Frankfurt am Main 646.550 Hessen Essen 595.715."Nordrhein-Westfalen" Die andere Datei enthält eine Liste der 19 größten deutschen Städte."Baden-Württemberg" 88045. 11.223 Bayern Köln 962.10.169 Berlin Hamburg 1. den Namen der Stadt. 6.8.10."Saarland" 78048.8435. 4."Baden-Württemberg" 68159."Augsburg."Böblingen"."Saarlouis"."Ulm".24. 15.400 Bayern Dresden 477."Böblingen". Jede Zeile enthält die Position der Stadt.8421."Ludwigshafen am Rhein.807 Sachsen Bochum 391. 13."Ulm"."Baden-Württemberg" 67059.6412.8222. 17."Schwarzwald-Baar-Kreis". 9.9.915 Nordrhein-Westfalen Leipzig 493."Augsburg"."Stuttgart"."Saarlouis"." Rheinland-Pfalz" 66740.8."Hessen" 50667. import re import codecs ."Baden-Württemberg" 88662.243 Nordrhein-Westfalen Dortmund 588.8.8.147 Nordrhein-Westfalen Wuppertal 366."Saarland" 66111. 16.8327.5315.5.8.994 Nordrhein-Westfalen Stuttgart 583."Villingen-Schwenningen"."Mannheim".14 Umfangreiche Übung 277 86150."Ludwigshafen am Rhein". Was jedoch fehlt. Stadt". 5. 12.8.txt und post_codes_germany. 10."Baden-Württemberg" 79098."Baden-Wü rttemberg" 78532."Konstanz"."Tuttlingen"."Köln". die 19 größten Städte zusammen mit ihren Postleitzahlen auszugeben."Baden-Wü rttemberg" 76131.403 Bremen Hannover 515.8311."Bayern" 89073. 14.758 Nordrhein-Westfalen Mannheim 306."Köln.7.001 Niedersachsen Duisburg 514."Baden-Württemberg" 60311.8326. Die Dateien befinden sich in unserem Beispielverzeichnis unter den Namen largest_cities_germany. 19."Stuttgart". 8.874 Baden-Württemberg Düsseldorf 569.364 Nordrhein-Westfalen Bremen 539. 2."Stadtverband Saarbrücken".392 Hamburg München 1.8."Tuttlingen".382.9761.8435."Bodenseekreis"."Überlingen"."Frankfurt am Main."Frankfurt am Main". 3."Freiburg im Breisgau". 7. die Einwohnerzahl und das Bundesland."Baden-Württemberg" 78462.434 Nordrhein-Westfalen Bielefeld 321.6."Mannheim"."Freiburg im Breisgau".10044.210.8115. 18.208 Sachsen Nürnberg 488.txt."Konstanz".8212. ist die zugehörige Postleitzahl: 1."Karlsruhe".8."Baden-Württemberg" 71032. Berlin 3.8."Saarbrücken"."Baden-Württemberg" 70173."Karlsruhe".

". die sich Perl.strip("\"")] = post_code fh_largest_cities = codecs.open("largest_cities_germany. PLZ[city]) Die Ausgabe für obiges Programm sieht wie folgt aus: $ python3 largest_cities_postcode.und Java-Programmierer vergeblich wünschen: re.txt". encoding="iso -8859-1") PLZ = {} for line in fh_post_codes: (post_code.search(r"^[0-9]{1.open("post_codes_germany.group(1) print(city.split(".line ) city = re_obj.15 findall Python oder besser das Modul re stellt noch eine weitere großartige Methode zur Verfügung. city. rest) = line.\s+([\wÄÖÜäöüß\s]+\w)\s+[0-9]".278 24 Reguläre Ausdrücke fh_post_codes = codecs. flags]) findall liefert alle Übereinstimmungen des regulären Ausdrucks „pattern” im String „str” als Liste zurück. str[. (Zur Erinnerung: search() und match() liefern nur die erste Übereinstimmung .py 14199 Berlin 22769 Hamburg 81929 München 51149 Köln 65936 Frankfurt am Main 45359 Essen 44388 Dortmund 70629 Stuttgart 40629 Düsseldorf 28779 Bremen 30669 Hannover 47279 Duisburg 4357 Leipzig 90491 Nürnberg 1478 Dresden 44894 Bochum 42399 Wuppertal 33739 Bielefeld 68309 Mannheim 24.2) PLZ[city.txt".findall(pattern.2}\. encoding=" utf-8") for line in fh_largest_cities: re_obj = re.

"Customer number: 232454. Also die Wahl zwischen verschiedenen Ausdrücken. wir wollen unsere E-Mails filtern. 'cat'. wird eine Liste mit Tupels der einzelnen Gruppenergebnisse zurückgeliefert: >>> import re >>> items = re.*". destination is London >>> Wer das letzte Beispiel für zu künstlich und nicht praxisnah genug hält. für den oder die haben wir hier ein weiteres Beispiel. Dazu verwendet man das Symbol „|”.. Date: January 22. und die Einträge der Liste entsprechen diesem Arbeitsablauf.*(London|Paris|Zurich|Strasbourg)". Manchmal benötigt man etwas Analoges für verschiedene Teilausdrücke. Zeichenklassen bieten eine Auswahl aus einer Menge von Zeichen. 'January 22.findall("[force]at". 'rat'. 'eat'] >>> Falls eine oder mehrere Gruppen in dem regulären Ausdruck vorkommen. 'oat'. Date: January 22.*: (. Nehmen wir an.24. und zwar nach einem vorausgegangenen Wort „destination”: >>> import re >>> str = "The destination is London!" >>> mo = re. 2013") >>> print(items) [('232454'. 'eat'. 2013')] >>> 24.*: . Zürich oder Strasbourg vorkommen.*)".16 Alternativen 279 zurück. da es sich um ein logisches „Oder” handelt. Wir möchten die gesamte Korrespondenz mit Guido van Rossum. Der folgende reguläre Ausdruck dürfte dann recht hilfreich sein: r"(^To:|^From:) (Guido|van Rossum)" . t) >>> print(mo) ['fat'. "Customer number: 232454.findall("[0-9]+.. Date : January 22.findall("([0-9]+). Paris. dem Schöpfer und Designer von Python.str) >>> if mo: print mo. 2013'] >>> items = re.search(r"destination." >>> mo = re. 2013") >>> print(items) ['232454. Im folgenden Beispiel prüfen wir. ob in einem String die Städte London.group() .) Der String „str” wird von links nach rechts gescannt.16 Alternativen Zu Beginn unseres Kapitels hatten wir Zeichenklassen eingeführt. finden. >>> import re >>> t="A fat cat doesn't eat oat but a rat eats bats.

17 Kompilierung von regulären Ausdrücken Falls man denselben regulären Ausdruck mehrmals in seinem Skript verwenden will. das zuvor kompilierte Pattern zu matchen: >>> x = ce.span() (17. Die allgemeine Syntax der compile()Funktion: re. das man später zum Suchen und Ersetzen verwenden kann. ist es eine gute Idee. split sub und andere .compile(r"01+") >>> ce <_sre. in <module> AttributeError: '_sre.SRE_Pattern object at 0xb72ac440> >>> Auf dem SRE_Pattern-Objekt ce kann man nun die Methode search anwenden. 24. den Ausdruck zu kompilieren.SRE_Match object at 0xb71af0c8> >>> x. Das Verhalten des Ausdrucks kann man mit Flag-Werten modifizieren.compile(r"01+") >>> x = ce. die entweder mit „To:” oder mit „From:” beginnen und von einem Leerzeichen gefolgt werden.search("Eine Binärzahl: 00111 und noch eine 01011") >>> x. Schauen wir uns dies in einem Beispiel an: >>> import re >>> ce = re.SRE_Match' object has no attribute 'findall' 4 ebenso wie match.search("Eine Binärzahl: 00111") >>> x <_sre. flags]) compile lieferte ein regex-Objekt zurück. 21) >>> x. die nur einen String braucht. wie wir im folgenden Beispiel sehen: >>> import re >>> ce = re. denen dann entweder der Vorname „Guido” oder der Nachname „van Rossum” folgt. line 1.compile(patter[.group() '0111' >>> Das SRE_Pattern-Objekt kennt auch eine Methode findall4 . auf dem versucht wird.findall() Traceback (most recent call last): File "<stdin>".280 24 Reguläre Ausdrücke Dieser Ausdruck passt auf alle Zeilen.

die Definition und die Benutzung von regulären Ausdrücken zu trennen.\s . re. \B . '011'] >>> Kompilierte reguläre Ausdrücke sparen in der Regel nicht viel Rechenzeit. Mit diesem Flag passen sie auch im Innern eines Strings vor und nach einem Newline „\n”.UNICODE re. dass Leerzeichen.LOCALE Beschreibung Groß. Tabs. \w . .DOTALL re.h. muss man es mittels Backslash schützen (escape) oder es in eine Zeichenklasse packen.24. Das Verhalten von bestimmten Zeichenklassen wie z.” passt dann auf alle Zeichen plus dem Newline „\n”. auch wenn man sie mit re. \s .M. \d . Ermöglicht „wortreiche” (verbose) reguläre Ausdrücke. \W . Alles hinter einem „#” wird bis zum Ende einer Zeile als Kommentar ignoriert.IGNORECASE re. \b .MULTILINE re.und Kleinschreibung wird nicht mehr unterschieden. \w .search() oder re. Leerzeichen werden ignoriert.2 Flags für compile Flag re. ^ und $ passen defaultmäßig nur auf den Anfang und das Ende eines Strings. Wenn man ein Leerzeichen im Verbose-Modus matchen will. re. \S werden re. nicht als solche gematcht werden.findall("Eine Binärzahl: 00111 und noch eine 01011") >>> x ['0111'. '01'.17 Kompilierung von regulären Ausdrücken 281 TABELLE 24. außer wenn dieses Zeichen in einer Zeichenklasse oder hinter einem Backslash steht. d. >>> x = ce. Das bedeutet. \W . re. Ein guter Grund dafür. sie zu verwenden.VERBOSE von Unicode-Einstellungen abhängig. „. \D . # wird auch ignoriert.B.I.match() aufruft. re.U. besteht darin.L. weil Python sowieso automatisch reguläre Ausdrücke kompiliert und zwischenspeichert. re. \b .S. \S wird von der eingestellten Sprachumgebung (locale) abhängig gemacht. re.X. Wagenrücklauf „\c” usw.

'it'. proclaimed in legislative halls. 'the'. 'Let'. ' pulpit. 'be'. 'legislative'. 'halls. 'let'. Let it be preached from the pulpit. 'Let'. 'political'.") ['James'.18 24." >>> law_courses. And. 'and'. ' schools. dass standardmäßig Leerräume (Whitespaces) als Separatoren genommen werden.'. als Separatoren benutzt. mit deren Hilfe man einen String in Teilstrings aufspalten kann. 'of'. 'that'. 'teacher'. ' in'. der von seinem Aufbau von Excel oder von Calc (OpenOffice) kommen könnte.'.Perl" >>> line. ' enforced'. 'and'. and in colleges.'. 'And. Dazu müssen wir lediglich „. 'American'. 'her'.” als Argument beim Aufruf übergeben: >>> line = "James. 'and'. 'taught'. Im folgenden kleinen Beispiel wollen wir das Semikolon als Separator nehmen. 'every '. 'babe'. Let it be taught in schools.teacher. 'of'. 'seminaries. Wir demonstrieren dieses Verhalten mit einem Zitat von Abraham Lincoln: BILD 24. 'in'.5 Splitting Strings >>> law_courses = "Let reverence for the laws be breathed by every American mother to the lisping babe that prattles on her lap. 'become'.282 24 Reguläre Ausdrücke 24. 'to'. 'Miller'. 'Perl'] . 'from'. 'reverence'. 'the'. and enforced in the courts of justice. Let it be written in primers. and in almanacs. spelling books. 'the'. 'religion'. 'mother'. 'for'. 'in'. 'justice.'. 'in'. str. 'the'. In unserem vorigen Beispiel hatten wir gesehen. 'it '. 'courts'. 'almanacs. 'colleges. Den zweiten Parameter werden wir später besprechen. 'the'. 'proclaimed'. 'Let'.'.'. 'breathed'. in short.Miller.'.'.'. ' short. ' prattles'.1 Aufspalten eines Strings mit oder ohne regulären Ausdruck split-Methode der String-Klasse Es gibt eine String-Methode split(). 'in'. 'preached'. 'lap. 'primers. 'on'. 'it'.'] >>> Wir schauen uns nun einen String an. 'spelling'.split() ['Let'. 'lisping'. 'it'. 'in'. in seminaries. 'be'. 'books. 'laws'. werden alle Teilstrings. die aus Leerräumen (Whitespaces) bestehen. 'in'. 'nation. let it become the political religion of the nation. maxsplit]]) Wenn das optionale Argument von split fehlt oder None ist.'. 'written'.18. 'in'. 'the'.'. 'be'. 'by'.split([sep[.split(". 'be'.'.

die ebenfalls split() heißt. The chief temple is in the holy city of New York. The chief temple is in the holy city of New York." >>> mammon. was nicht Buchstaben entspricht. 'leading religion.3) ['The'. The chief temple is in the holy city of New York. The chief temple is in the holy city of New York.'] 24. 'god'. also für den Separator. wenn man nur die reinen Wörter eines Texts herausfiltern will? Wenn man also alles herausfiltern will. from whom these miracles did spring."] >>> Die leeren Strings können wir verhindern. In diesem Fall wird split() nach jedem Leerzeichen den String aufsplitten. 'of'. d.2 split-Methode des re-Moduls In den meisten Fällen genügt die split-Methode aus dem str-Modul voll und ganz. indem wir None als erstes Argument. Dann arbeitet split() mit der Standardeinstellung. Falls maxsplit angegeben wird. und dadurch erhalten wir in unserer Ergebnisliste leere Strings und Strings. benutzen.split(" "." .18. die nur ein „\t” enthalten: >>> mammon = "The god \t of the world's leading religion. 'god'. also so. 'the'. also auch Tabs) hintereinander stehen.split() in einem kurzen Text. Inspire my numbers with coelestial heat." >>> mammon. 'of'."] Wir benutzten im vorigen Beispiel ein Leerzeichen als Separator. was ein Problem darstellen kann. The chief temple is in the holy city of New York. die Ergebnisliste besteht aus höchstens „maxsplit + 1” Elementen.split(None. ''. 'of'. Dann benötigen wir eine Split-Funktion. I sing: Ye Gods. dann wird der String an maximal „maxsplit” Separatoren zerlegt. Das Modul re bietet eine solche Methode. wenn mehrere Leerzeichen (irgendwelche Leerzeichen.h. "world's". "the world's leading religion. "the world's leading religion. Wir demonstrieren die Wirkungsweise von maxsplit mit einer Definition des Begriffs Mammon aus dem „Devil’s Dictionary” von Ambrose Bierce: >>> mammon = "The god of the world's leading religion. '\t'. als wenn man keinen Trennstring angegeben hat: >>> mammon.5) ['The'. dem Beginn der Metamorphosen von Ovid: >>> import re >>> metamorphoses = "OF bodies chang'd to various forms.split(" ". Wir erläutern die Arbeitsweise mit re. Aber wie sieht es beispielsweise aus. 'god'. die die Angabe von regulären Ausdrücken zur Definition von Separatoren zulässt.24.18 Aufspalten eines Strings mit oder ohne regulären Ausdruck 283 Wie bereits erwähnt hat die Methode split() noch einen weiteren optionalen Parameter: maxsplit.5) ['The'.

Untersatz: Ein Mann kann ein Pfostenloch in sechzig Sekunden graben.metamorphoses) ['OF'.somit: Obersatz: Sechzig Männer können eine Arbeit sechzig mal so schnell machen wie einer. dem Autor von „The Devil’s Dictionary”. 'did'. sieht man. 'my'. einem Untersatz und einer Konklusion (Schlussfolgerung) besteht . . 'to'.5 Wir haben auf re. eingeleitet werden.split("\w+: ". ''] Seine volle Wirkungskraft entfaltet split im nachfolgenden Beispiel. 'spring'. 'I'. 'whom'.""" definitions = re. ' Inspire'. 'numbers'.split("\w+: ". Übersetzung stammt von der Webseite „Logik wider alle Vernunft” (http://www. dass jede Definition bzw. der aus einem Obersatz. 'forms'.de/logik/) von Bernd Klein. 'heat'. 'Ye '. 'sing'. denn vor dem ersten Separator „Logik:” steht kein Zeichen. 'Gods'. 'd'. der aus einem Obersatz. logik) ein leerer String ist. 'various'. die Beispiele für den Obersatz und den Untersatz sowie die Konklusion durch den jeweiligen Begriff. logik) den Slice-Operator [1:] angewendet.split("\W+".split("\w+: ". weil der erste Eintrag der Ergebnisliste von re. 'these'. Die Ausgabe des obigen Skripts sieht wie folgt aus: $ python3 split_logics. Als Beispieltext verwenden wir eine ironische Definition von Logik. logik)[1:] print("Definition von Logik: \n" + definitions[0]) print("Beispiel für einen Obersatz: \n" + definitions[1]) print("Beispiel für einen Untersatz: \n" + definitions[2]) print("Konklusion: \n" + definitions[3]) Wenn man sich den String logik anschaut. 'chang'.klein-singen. deswegen: Konklusion: Sechzig Männer können ein Pfostenloch in einer Sekunde graben . gefolgt von einem Doppelpunkt. einem Untersatz und einer Konklusion (Schlussfolgerung) besteht . 'miracles'. 'from'. Die Grundlage der Logik ist der Syllogismus (logische Schluss). Wir können also als Separator den regulären Ausdruck "\w+:"verwenden. 'bodies'. wie sie Ambrose Bierce in seinem berühmten „Devil’s Dictionary” vorschlägt: import re logik = """Logik: Die Kunst des Denkens und Schlussfolgerns in strenger Ü bereinstimmung mit den Beschränkungen und Unfähigkeiten des menschlichen Missverständnisses.284 24 Reguläre Ausdrücke >>> re.somit: 5 Die Definitionen stammen von Ambrose Bierce. Die Grundlage der Logik ist der Syllogismus (logische Schluss). 'with'.py Definition von Logik: Die Kunst des Denkens und Schlussfolgerns in strenger Übereinstimmung mit den Beschränkungen und Unfähigkeiten des menschlichen Missverstä ndnisses. 'coelestial'.

.. 'like'.. 'my '. 'your'... take him for all in all.. 'father'. . HAMLET He was a man.. . 'not'. 'I'. 24. 'was'. 'once'. 'the'. 'father'. The king my father!""" Mithilfe von re. .split(r"\W+".3 Wörter filtern Wir wollen nun die Wörter eines Texts herausfiltern.t) ['HORATIO'.split(r"\W+". 'HORATIO'. 'lord'. 'shall'. 'again'. 'Where'. 'man'.. 'HAMLET'. he was a goodly king. 'In'. 'goodly'. 'upon'... 'The'. .. import re t = """HORATIO HAMLET HORATIO Where. I shall not look upon his like again. 'HORATIO'.. 'look'. 'Saw'. Horatio. 'king'.24. .lower() for x in re..18 Aufspalten eines Strings mit oder ohne regulären Ausdruck 285 Beispiel für einen Obersatz: Sechzig Männer können eine Arbeit sechzig mal so schnell machen wie einer. . deswegen: Konklusion: Sechzig Männer können ein Pfostenloch in einer Sekunde graben. 'king'. 'He'. 'him'.. 'lord'. 'all'. . Beispiel für einen Untersatz: Ein Mann kann ein Pfostenlock in sechzig Sekunden graben. 'king'. ' a'. 'for'.t)} >>> len(words) .. 'I'. 'him'. . ''] Wir können uns auch sehr leicht die Menge der Wörter... 'HORATIO'. 'My'.. 'HAMLET'. 'all'. the king your father. 'I'. Betrachten wir folgenden String aus Shakespeares Hamlet: >>> >>> . also ohne mehrfache Vorkommen erzeugen: >>> words = { x. 'HAMLET'. ' his'.18. 'take'... 'him '. .. 'yesternight'. 'mind'. 'I'. 'my'. I think I saw him yesternight. 'a'. I saw him once. 'think'. . 'my'. 'saw'. 'Horatio'. HORATIO HAMLET HORATIO HAMLET My lord.. 'was'. 'he'. 'in'. 's'. 'who'.. 'HAMLET'. also ohne Satzzeichen und Sonderzeichen. 'My'. ' saw'. Saw? who? My lord...... . . 'lord'... my lord? In my mind's eye. . ' eye'. .split() können wir eine Liste aller Wörter erzeugen: >>> re.

2}b+.286 24 Reguläre Ausdrücke 36 >>> words {''. Aufgabe: Aufgaben Welche der folgenden regulären Ausdrücke (a). 'him'. 'think'. 24. 'like'.sub(regex. (g) passen auf welche Strings von (1). Beispiel:6 >>> import re >>> str = "yes I said yes I will Yes. . 'look'. 'he'. 'father'. 'a'.20 1. 'eye'. str) >>> print res no I said no I will no. 'king'. 'who'. 'yesternight'.sub("[yY]es". . subject) Jede Übereinstimmung (match) des regulären Ausdrucks „regex” wird durch den String „replacement” ersetzt. 'upon'. . 'i'. . 'man'. Seite 405 6 Der im Beispiel verwendete String entspricht den letzten Worten des Romans „Finnegans Wake” von James Joyce. 'my'. 'where'.}c? ^a{1. replacement. 'his'. 'hamlet'. 'all'. . 'in'. (6): (1) (2) (3) (4) (5) (6) abc ac abbb bbc aabcd b (a) (b) (c) (d) (e) (f) (g) ab+c? a?b*c b+c* ^b+c*$ a. 'once '} >>> 24. 'take'. 'mind'. 'saw'. 'for'. 'again'." >>> res = re.+b?c b{2. 'the'. 's'. 'lord'. 'was'.?d* Lösung: Lösungen zu Kapitel 24 (Reguläre Ausdrücke). . 'goodly'.19 Suchen und Ersetzen mit sub re. ' shall'."no". 'not'. 'your'. 'horatio'. .

B. z. 20500-0001 (president).und Kleinschreibung. Aufgabe: Was matcht x(xy)*x? (1) (2) (3) (4) (5) xx xyxyxyx xxyxy xyxx xxyxyx Lösung: Lösungen zu Kapitel 24 (Reguläre Ausdrücke).24. Aufgabe: Finden Sie heraus. Aufgabe: Schreiben Sie einen Ausdruck. dass ein Zip-Code nur aus 5 Ziffern besteht. 20500-0002 (first lady). Seite 406 3. Berechnen Sie die Häufigkeitsverteilungen von Wortlängen in einem Text ohne Berücksichtigung von Groß. Ein Zip-Code besteht entweder aus 9 Zeichen. Lösung: Lösungen zu Kapitel 24 (Reguläre Ausdrücke). also z. gefolgt von 4 Ziffern. z. 205000001 oder 5 Ziffern gefolgt von einem Strichpunkt. die aus zwei gleichen Teilwörtern bestehen. Lösung: Lösungen zu Kapitel 24 (Reguläre Ausdrücke). .txt”. Seite 406 4. 20500 (Washington DC) Lösung: Lösungen zu Kapitel 24 (Reguläre Ausdrücke). Außerdem ist es auch zulässig. Seite 407 6.20 Aufgaben 287 2. der US-Zip-Codes prüft. wie viele verschiedene Wörter in dem Roman „Ulysses” von James Joyce mit „ship” enden. Sie finden den Roman in unserem Beispielverzeichnis unter dem Namen „ulysses.B. Seite 407 5. Das längste Wort in „Ulysses” ist übrigens das Wort „Nationalgymnasiummuseumsanatoriumandsuspensoriumsordinaryprivatdocent”.B. wie beispielsweise „dumdum” oder „poohpooh”. Aufgabe: Auch in dieser Aufgabe bleiben wir bei der Weltliteratur. Aufgabe: Finden Sie in „Ulysses” alle Wörter. Damit hat dieses Wort noch zwei Buchstaben mehr als das Wort „Grundstücksverkehrsgenehmigungszuständigkeitsübertragungsverordnung”.

„nur”. dann haben wir folgende Verteilung: 4 Wörter der Länge 3 2 Wörter der Länge 4 Man könnte eine Häufigkeitsverteilung auch auf die verschiedenen Wörter anwenden.”. „ist” Lösung: Lösungen zu Kapitel 24 (Reguläre Ausdrücke). Seite 408 . dann sieht die Verteilung so aus: 1 Wort der Länge 4: „Wort” 3 Wörter der Länge 3: „ein”.288 24 Reguläre Ausdrücke Zur Erläuterung: Besteht der Text nur aus dem String „Ein Wort ist nur ein Wort.

und reduceFunktionen besonders vorteilhaft. Schauen wir uns ein einfaches Beispiel einer lambda-Funktion an. lambda x: x + 42 . map und reduce. nachdem er eine Codeerweiterung mit diesen Funktionalitäten von einem. filter und reduce Wenn es nach Guido van Rossum. Der lambda-Operator bietet eine Möglichkeit. Sie können eine beliebige Anzahl von Parametern haben. führen einen Ausdruck aus und liefern den Wert dieses Ausdrucks als Rückgabewert zurück. Die Listen-Abstraktion ist klarer und leichter verständlich. Dazu kann man die folgenden Gründe angeben: Es gibt eine gleich mächtige Alternative zu lambda. Guido van Rossum hatte lambda. Lisp-Hacker erhalten hatte. um ein Problem zu lösen” („There should be one obvious way to solve a problem”). zu schreiben und zu benutzen. BILD 25. In Python 3 sollten sie nach seinem Willen verschwinden. reduce(). nämlich die Listen-Abstraktion (englisch: list comprehension). dann verletzt dies das Python-Motto „Es soll (genau) einen offensichtlichen Weg geben. die nicht über einen Namen verfügt. wie er glaubt. filter. anonyme Funktionen. map.25 ■ ■ lambda. dem Autor von Python. Hat man sowohl die Listen-Abstraktion also auch „Lambda und Co.1 Dateien Anonyme Funktionen sind insbesondere bei der Anwendung der map-. gegangen wäre. filter. also Funktionen ohne Namen. filter() and map() noch nie gemocht und sie bereits 1993 widerwillig in Python aufgenommnen. ■ 25. Eine solche Funktion kann deshalb nur über Verweise angesprochen werden.”. würde dieses Kapitel in unserem Buch wahrscheinlich fehlen.1 lambda Eine anonyme Funktion oder Lambda-Funktion ist eine Funktion. Lambda-Funktionen kommen aus der funktionalen Programmierung und wurden insbesondere durch die Programmiersprache Lisp besonders bekannt.

Die allgemeine Syntax einer Lambda-Funktion sieht wie folgt aus: lambda Argumentenliste: Ausdruck Die Argumentenliste besteht aus einer durch Kommata getrennten Liste von Argumenten... . print(42 + i) .100 print(y) for i in range(10): (lambda x: x + 42)(i) Natürlich kann man mit obigem Code viele beeindrucken...290 25 lambda. die die Summe von x und 42 zurückgibt. und der nach dem Doppelpunkt stehende Ausdruck ist ein beliebiger Ausdruck. filter und reduce Bei dem obigen Beispiel handelt es sich um eine Funktion mit einem Argument „x”... map. 42 43 44 45 46 47 48 49 50 51 (lambda x: x + 42)(3) y = (lambda x: x + 42)(3) . der diese Argumente benutzt. 42 43 44 45 46 47 48 49 50 51 . aber man hätte es natürlich auch viel einfacher hinschreiben können: >>> for i in range(10): . Doch kommen wir zurück zu unserem einführenden Beispiel.. Wie können wir unsere Funktion lambda x: x + 42 benutzen? >>> 45 >>> >>> -55 >>> ..

f44 usw.. anwenden(lambda x: x + i. 43. 50. >>> f42(4) 46 Nun kommen wir endlich zu einer sinnvollen Anwendung der lambda-Notation. 47.range(10)) [42. die eine Funktion als erstes Argument und eine Liste als zweites Argument erwartet. den lambda-Ausdruck einer Variablen zuzuweisen.append(f(element)) . 48.1 lambda 291 Eine andere Möglichkeit besteht darin. return x + 42 . 22. 43. Mit diesem Namen können wir unsere Funktion jetzt wie eine „gewöhnliche” Funktion f benutzen: >>> f42 = lambda x: x + 42 >>> f42(4) 46 Aber dazu brauchten wir nicht die lambda-Notation. Wir schreiben eine Funktion mit dem Namen „anwenden”. die wir nur einmal bei dem Funktionsaufruf von „anwenden” benötigen. wenn wir diese Funktionen direkt an unsere Funktion „anwenden” übergeben könnten. 44..42]: . Dies ist mit der lambda-Notation möglich: >>> anwenden(lambda x: x + 42. . Um diese Funktion zu benutzen..liste): . 45. return ergebnis Wir können nun die Funktion „anwenden” mit unserer f42-Funktion und der Liste der Zahlen von 0 bis 9 aufrufen: >>> anwenden(f42. hatten wir zuerst eine Funktion mit dem – hässlichen – Namen f42 einführen müssen. 49. ergebnis = [] . Sie können sich leicht vorstellen. 51] Wir haben oben den Funktionsnamen als Referenz auf unsere Funktion übergeben... 44. benötigen könnten... range(10)) .. 49.. also ohne den Umweg mit der Namensgebung... 46.range(10)) [42.. for element in liste: . 48. Wir hätten dies auch mit einer normalen Funktionsdefinition bewerkstelligen können: >>> def f42(x): . Die Funktion f42 ist eine „Wegwerffunktion”. ergebnis. dass wir gegebenenfalls auch ähnliche Funktionen wie f43.. 50. 47.. 46. 51] Auch solche Anwendungen sind jetzt möglich: >>> for i in [17.25. Die Funktion „anwenden” wendet auf jedes Element der übergebenen Liste die als erstes Argument übergebene Funktion an: >>> def anwenden(f. Aus diesem Grund wäre es natürlich bedeutend eleganter.. 45..

filter und reduce [17. 43. seq) Das erste Argument func ist eine Funktion und das zweite eine Sequenz (z. Für das folgende Beispiel „vergessen” wir nun „lambda” und „map” und beschränken uns auf eine „konventionelle” Programmierung: . 25. 29. 20. 31] [42. eine Liste oder ein Tupel) seq. 24. 49. 25. 18. + 42.B. 43. 19. 47. also ein Iterator. 23. Nehmen wir an. 48. Rufen wir map(lambda x: x + 42. Eine Temperatur C in Grad Celsius lässt sich mittels der Formel 9 ∗ C + 32 5 in Grad Fahrenheit wandeln. 45. 45. range(10)) 48. 46. 21. 47. 44.292 25 lambda. 46. 44. 22. Im Prinzip entspricht „map” unserer Funktion „anwenden”. 50. 51] + 42. 47. und eine Temperatur F in Grad Fahrenheit lässt sich mittels der Formel 5 ∗ (F − 32) 9 in Grad Celsius wandeln. map wendet die Funktion func auf alle Elemente von seq an und schreibt die Ergebnisse in ein map object. range(10))) 48. 26. dass wir Listen mit Temperaturwerten in Grad Celsius und Grad Fahrenheit haben. 45. welchen großen Vorteil diese Kombination aus lambda und map-Funktion mit sich bringt. range(10)) auf. range(10)) Damit es ist völlig gleich ist. 30. Wir möchten diese wechselseitig in die jeweils andere Temperaturskala wandeln. 49. 43. 27.2 map Nachdem wir uns im vorigen Kapitel intensiv mit der Funktion „anwenden” beschäftigt hatten. 44. 24. 49. 25. stellt die von Python zur Verfügung gestellte Funktion „map” kein Problem dar. 51] In obigem Beispiel haben wir mit Hilfe des Schleifenparameters i drei verschiedene Funktionen kreiert. >>> anwenden(lambda x: x [42. 26] [22. entspricht dies fast unserem Aufruf anwenden(lambda x: x + 42. müssen wir lediglich das map-Objekt noch in eine Liste wandeln: >>> list(map(lambda x: x [42. map ist eine Funktion mit zwei Argumenten: r = map(func. 28. map. 23. 51] In einem weiteren Beispiel wollen wir nun zeigen. 50. 46. 50.

F_liste) print(list(C_liste)) map kann auch gleichzeitig auf mehrere Listen angewendet werden. der Parameter y seine Werte aus der Liste b und der Parameter z seine Werte aus der Liste c beziehen. dass der Parameter x seine Werte aus der Liste a. 37.5.y.z : 2.39) def Fahrenheit2Celsius(F_liste): erg = [] for F in F_liste: erg.y. 37.39) F_liste = list(map(lambda C: (5.append(fahrenheit(C)) return erg F_liste = Celsius2Fahrenheit(temp) print(F_liste) C_liste = Fahrenheit2Celsius(F_liste) print(C_liste) Unter Benutzung von lambda und map schrumpft unser obiges Codebeispiel in beachtlicher Weise: temp = (36. Dann werden die Argumente entsprechend ihrer Position und der Reihenfolge der Listenargumente entsprechend mit den Werten aus den Listen versorgt.9] >>> list(map(lambda x.c)) [37.5*x + 2*y .b.z:x+y+z.2 map 293 def fahrenheit(T): return ((9.11.4] >>> b = [17. 24. a. 37.10] >>> c = [-1. temp)) print(F_liste) C_liste = map(lambda F: (9.-4.z.32 ) temp = (36.32 ). 33.5.b)) [18.12.2.0] >>> Wir sehen in dem obigen Beispiel.append(celsius(F)) return erg def Celsius2Fahrenheit(C_liste): erg = [] for C in C_liste: erg.0 / 5) * F + 32.5.5. 14.5. . 37. >>> a = [1.y:x+y.5. 19. 23] >>> list(map(lambda x.5. a. 14] >>> list(map(lambda x. 14.0 / 5) * T + 32) def celsius(T): return (5.3. 10. a.0 / 9) * ( C .25.0.0 / 9) * ( T . 21.b.c)) [17.

Die Funktion filter(f.13.55] odd_numbers = list(filter(lambda x: x % 2.8. >>> >>> [0. 3. 5. 21. fibonacci)) print(odd_numbers) 1. die er am wenigsten mag.. Diese Funktion wird dann auf jedes Argument des Objekts „iter” angewendet. „iter” ist entweder ein sequentieller Datentyp wie beispielsweise eine Liste oder ein Tupel. fibonacci)) print(even_numbers) 2. >>> >>> >>> . map.5. Liefert f True für ein x. reduce wurde in das Modul „functools” verbannt und gehört damit nicht mehr in den Kern der Sprache.iter) benötigt als erstes Argument eine Funktion f. This is actually the one I’ve always hated most.3 Die Funktion Filtern mit „filter” filter(funktion. >>> >>> [0.1 Mit reduce war er erfolgreich. 8. Die Funktion reduce(func. filter und reduce 25. liste) bietet eine elegante Möglichkeit. oder es ist ein iterierbares Objekt. dass Guido van Rossum lambda. für die die Funktion „funktion” True liefert.1. 55] even_numbers = list(filter(lambda x: x % 2 == 0. apart from a few examples involving + or *. I need to grab pen and paper to diagram what’s actually being fed into that function before I understand what the reduce() is supposed to do. almost every time I see a reduce() call with a non-trivial function argument.1. 13.21.4 reduce Eingangs des Kapitels erwähnten wir bereits. >>> >>> >>> [1.” . 8.. because.34.294 25 lambda. dann wird x in der Ergebnisliste übernommen. map. diejenigen Elemente aus der Liste liste herauszufiltern.3. fibonacci)) print(even_numbers) 2. 34] 25. reduce ist diejenige Funktion. seq) 1 „So now reduce(). 34] # or alternatively: even_numbers = list(filter(lambda x: x % 2 -1. filter und reduce nicht mehr in Python 3 wollte. >>> fibonacci = [0. ansonsten wird x nicht übernommen.2. die Wahrheitswerte liefert.

sn ]. bis nur noch ein Element übrig bleibt.y: x+y. . s2) und s3 angewendet. s3.13]) 113 >>> Im folgenden Beispiel veranschaulichen wir die Arbeitsweise von reduce an einem konkreten Beispiel: >>> reduce(lambda x.42. Die Funktion „func” ist eine Funktion. Um mit reduce zu arbeiten.. Das ist der wesentliche Unterschied zu früheren Python-Versionen wie zum Beispiel Python 2.4 reduce 295 wendet die Funktion func() fortlaufend auf eine Sequenz seq an und liefert einen einzelnen Wert zurück.. d. . Das Ergebnis ersetzt die beiden Elemente s1 und s2. Dies wird solange fortgesetzt.s3).42. [47. s2. die zwei Argumente erwartet.11. s3.y: x+y. Die Liste sieht damit wie folgt aus: [ func(s1.h. müssen wir in Python 3 das Modul functools importieren. Falls seq = [ s1.11. funktioniert der Aufruf reduce(func.13]) 113 Im folgenden Diagram sind die Ergebniswerte dargestellt: .7: >>> import functools >>> functools. [47. . sn ]. . Die Liste sieht damit wie folgt aus: [ func(func(s1. seq) wie folgt: ■ zuerst wird func auf die beiden ersten Argumente s1 und s2 angewendet.. s2).25.reduce(lambda x. s2). ■ ■ ■ ■ Für den Fall n = 4 können wir die vorige Erklärung auch wie folgt illustrieren: Das folgende Beispiel zeigt die Arbeitsweise von reduce() an einem einfachen Beispiel.. man hat die Liste auf ein Element reduziert. sn ] ist.. . Im nächsten Schritt wird func auf func(s1. ..

map. filter und reduce). Seite 410 . Einzelpreis) ] Schreiben Sie wieder ein Programm.95 56.80 32.00 € liegt. Aufgabe: In einer Buchhandlung findet sich in einem Abrechnungsprogramm in Python eine Liste mit Unterlisten mit folgendem Aufbau: Bestellnummer Buchtitel und Autor Anzahl Einzelpreis 34587 98762 77226 Learning Python. Aufgabe: Situation wie in voriger Aufgabe.€ erhöht werden. Einzelpreis). map. filter und reduce). Seite 410 2. Jedes Tupel besteht aus der Bestellnummer und dem Produkt aus der Anzahl und dem Einzelpreis. . das als Ergebnis eine Liste mit Zweier-Tupeln liefert. Paul Barry 4 5 3 40. Mark Lutz Programming Python.296 25 lambda. (Artikel-Nr. aber jetzt sehen die Unterlisten wie folgt aus: [Bestellnummer.95 Schreiben Sie ein Programm unter Benutzung von lambda und map. filter und reduce 25.. Das Produkt soll jedoch um 10.. wenn der Bestellwert unter 100. Gesamtpreis) liefert.5 Aufgaben 1. Lösung: Lösungen zu Kapitel 25 (lambda. Anzahl. Lösung: Lösungen zu Kapitel 25 (lambda.. Anzahl. map. was eine Liste mit 2-Tupel (Bestellnummer. (Artikel-Nr. Mark Lutz Head First Python.

26.h. filter und reduce ansehen. und man kann sie als vollständigen Ersatz für den Lambda-Operator sowie die Funktionen map. dass Guido van Rossum diese Funktionen nicht mag und sie am liebsten mit der Einführung von Python 3 entfernt hätte. Stattdessen bevorzugt er die Listen-Abstraktion.2 Einführung in die Listen-Abstraktion Die Listen-Abstraktion ist eine einfache Methode. Die List Comprehension für Lambda und Co.26 26. ist eine elegante Methode. y )|x ∈ Z ∧ y ∈ Z}. solche Aufgaben zu lösen. es werden nur Elemente aus einer anderen Liste.0 in Python eingeführt. die bestimmte Bedingungen erfüllen. d. um Listen zu erzeugen. Die Listen-Abstraktion. Allgemein verwendet man sie. die meist auch im Deutschen als „List Comprehension” bezeichnet wird. Im vorigen Kapitel über lambda. Schauen wir uns zunächst einmal an. Mengen in Durchfahrt verboten Python zu definieren oder zu erzeugen. um neue Listen zu erzeugen. In der Mathematik definiert man die Quadratzahlen der natürlichen Zahlen beispielsweise als {x 2 |x ∈ N} oder die Menge der komplexen ganzen Zahlen {(x .1 Comprehension” bekannt. eigentlich auch im Deutschen besser als „List BILD 26. Die Syntax der List Comprehension ist im Allgemeinen leichter verständlich. bei denen jedes Element durch Anwendung verschiedener Operationen aus einem Element einer anderen Liste oder eines Iterators erzeugt wird. Im Folgenden erzeugen wir die Liste der Quadratzahlen für die Zahlen von 1 bis 9: . mit welchem Aufwand es verbunden ist. reduce and map haben wir erfahren. filter.1 Listen-Abstraktion/ List Comprehension Die Alternative zu Lambda und Co. auf traditionellem Wege. um Unterlisten zu erzeugen. kommt der mathematischen Notation von Mengen sehr nahe. Ebenso nutzt man es. einem Tupel oder allgemein eines sequentiellen Datentyps übernommen. also ohne Listen-Abstraktion. Die ListenAbstraktion wurde mit der Version 2.

. >>> t [(1. 3)... 36. 36.7) for y in range(1. (2. 81] Viel einfacher – das heißt in nur einer Codezeile – lässt sich dies unter Benutzung der Listen-Abstraktion bewerkstelligen: squares = [i**2 for i in range(1.10): squares. 16. 9.y) for x in range(1. 81] map liefert einen Iterator auf ein list-Objekt zurück. 16.. (4. (4. Dies könnte beispielsweise den Ergebnissen von zwei Würfeln entsprechen: >>> [ (x. 49. 64. (5. Im folgenden Beispiel erzeugen wir alle 2-Tupel mit Zahlen von 1 bis 6. 1)] . 6). t. 26.. 49. range(1. während die Listen-Abstraktion eine Liste zurückgibt.7): ..3 Syntax Die Listen-Abstraktion ist von eckigen Klammern umrahmt. 3). 2). (6..10))) >>> squares [1. (3. 2). der keine Listen-Abstraktion nutzt: >>> t = [] >>> for x in range(1. (6..10)] Nur zur Erinnerung: Unter Benutzung von map und lambda sieht es wie folgt aus: >>> squares = list(map(lambda x: x**2. 25. deren Summe gleich 7 ist.. 6). (5... 64.7): . . squares = [] for i in range(1. >>> [1. 5). 25. 5).append( (x. 9. if x + y == 7: . (2.append(i**2) squares 4.298 26 Listen-Abstraktion/List Comprehension >>> >>> . 4). 4. for y in range(1. (3.. der von einem oder mehreren for-Ausdrücken und gegebenenfalls von einer if-Bedingung gefolgt wird.y) ) .7) if x + y == 7] [(1. 4). 1)] Dies ist äquivalent mit dem folgenden „konventionellen” Code. Nach der öffnenden Klammer steht ein Ausdruck.

5). 4. 100.4 Weitere Beispiele Im Abschnitt über die map-Funktion hatten wir die Wandlung einer Liste mit Werten in Grad Celsius in Fahrenheit-Werte mit der map-Funktion gelöst. 29)] >>> Im folgenden Beispiel berechnen wir das Kreuzprodukt aus zwei Mengen: >>> colours = [ "red". (5. 15). 37. 24. 20). ('red'. Ein solches Tripel wird üblicherweise mit (a. 21.y. die durch 4 teilbar sind: {x |x ∈ Z ∧ x teilbar durch 4} oder ein anderes Beispiel: {x |10 <= x <= 100 ∧ x teilbar durch 4} . 36. 'house'). 'car'). 5). "green". "tree" ] >>> coloured_things = [ (x. wie das folgende Beispiel zeigt: >>> [(x.5.z) for x in range(1.y) for x in colours for y in things ] >>> print(coloured_things) [('red'. 99. (12. 25). 12. 'car').30) for z in range(y . ist angelehnt an die mathematische Notation von Mengen. (9. 13).7. 'car'). 25).56. "car". Mit der List Comprehension lässt sich dies sehr einfach lösen: >>> Celsius = [39. 12. 24.26. 26). ('blue'. 'house'). c) notiert.14. 4 und 5 dar. ('yellow'. (6. 37. (8. 16. ('green'. 'tree').4 Weitere Beispiele 299 26.30) for y in range(x. "blue" ] >>> things = [ "house". 4.03999999999999] >>> Ein pythagoreisches Tripel oder pythagoreisches Zahlentripel besteht aus drei positiven ganzen Zahlen mit der Eigenschaft a 2 + b 2 = c 2 . ('yellow'. 97. ('blue'. 'tree')] >>> 26. 20. ('red'. 'tree'). ('green'. Die pythagoreischen Tripel lassen sich leicht mittels List Comprehension berechnen. (7. 8. Beispiel: Die Menge aller ganzen Zahlen. 17). eine Liste quasi algorithmisch zu beschreiben. (20. (' blue'. 'car'). ('yellow'. also das Tripel (3. b.5 Die zugrunde liegende Idee Die Idee. 'house'). 'house'). 10).3. 15.8] >>> Fahrenheit = [ ((float(9)/5)*x + 32) for x in Celsius ] >>> print(Fahrenheit) [102. (15.30) if x**2 + y**2 == z**2] [(3. ('green'. 'tree'). Ein Beispiel stellen die Zahlen 3. (10.2. "yellow".

84. 42. 72. 40. 28. 75. 88. 43. 100) if x not in noprimes] print(primes) 3. 64. 21. 30. 48. 72. 18. 99] >>> Am besten wäre es. 68. 74. 52. 60. 7. 32. 90. 53. also „|”. 36. i)] primes = [x for x in range(2. 96. 89. 56. 66. 63. 36. 90. 6. 24. 94. 32. 45. 8. 52. 81. 14. 42. 16. 40. 64. 41. 86. 65. 55. 80. 99. dass es bei der Konstruktion dieser Liste ein Problem gibt. 40. 60. 9. 11. 16. 47. 16. 78. 98. 54. 8. 17. 12. 35. 59. 30. 30. 48. diese Doppeleinträge bereits gar nicht zu erzeugen. 100] Der senkrechte Strich. 80. 75. 51.300 26 Listen-Abstraktion/List Comprehension Das letzte Beispiel lässt sich wie folgt in Python schreiben: >>> [ x for x in range(10. 84. 90. 14. 97] Das vorige Beispiel wollen wir nun in einer etwas allgemeineren Form schreiben. 67. 96. 77. 80. 15. 71. 18. 19. 91. 66. 48. 84. 58. 50. 66. 72. 18. 92. 24. ” 26. 100. 16. 32. 80. 30. was die Berechnung der Liste der Primzahlen ineffizient werden lässt. also im obigen Beispiel „All x for which 10 is . 36. 57. 42. 79. 56. damit es die Primzahlen für eine beliebige Zahl n berechnet: >>> >>> >>> >>> from math import sqrt n = 100 sqrt_n = int(sqrt(n)) no_primes = [j for i in range(2. 13. 96. 24. 10. 80. n. erkennen wir. 6. 38. 22. 5. 70. 63. 12. 69. 48. 26. in der mathematischen Notation. 56. 27. 87. 36. 29. 54. 24. 37. 64. 42. 88. >>> Anspruchsvolleres Beispiel Berechnung der Primzahlen bis 100 nach dem Sieb des Eratosthenes: noprimes = [j for i in range(2. 85. 76. . 27. wird übrigens im Englischen bei der Mengenschreibweise meist als „for” gelesen. 44. 54. 84. Diese Liste beinhaltet Doppeleinträge. 64. 84. 20. 73. 82. 95. 20. 76. 93. 60. 18. 68. 36. 44. 28. 63. 72. 32. . 88. 44. 70. 15. 72. 35. 88. 12. 62. 68. 92. 45. 23. 72. 83. 21. 60. 12. 8) for j in range(i*2. 61. 24. 49. . 31.101) if not x % 4] [12. da auch alle Doppeleinträge jeweils betrachtet werden müssen: >>> no_primes [4. 40.sqrt_n) for j in range(i*2. 50. 76. 98. 48. 10. 20. 45. 25. 34. 24.6 >>> >>> >>> [2. 96. 84. 28. 36. 20. 92. 96. 90. 54. 78. 70. 96. 39. 52. 40. i)] Wenn wir uns no_primes ausgeben lassen. 90. 60. 28. 81. 33. 46. 60. 78. 48. 56. 56. 72.

79. 67. 64. 66. 29. 81. 72. 53. 96. 41. 87. 11. 84. 7. 77. 5. 27. 16. i)} no_primes 6. 46. 38. 97} >>> 26. 75. 90. 60. 83. 99} >>> primes = {i for i in range(n) if i not in no_primes} >>> print(primes) {0.sqrt_n) for j in range(i*2. 8. 50. n. 73. 85. 56. 23. 15. 35. 91. 43. 54. 37. 82. 31. 59. 32. 62. 42. 65. 92. Wir berücksichtigen darin. 74. 34. 88. 10. aber sie liefert – wie der Name andeutet – eine Menge und nicht eine Liste zurück. 49. 51. n. 69. 2. 28. 70. also die Nicht-Primzahl ohne Doppelte zu kreieren: >>> >>> >>> >>> >>> {4. 40. 93. 48. 13. Mit der Mengen-Abstraktion sind wir nun in der Lage. 14. 26. from math import sqrt n = 100 sqrt_n = int(sqrt(n)) no_primes = {j for i in range(2. 17. 45. 78. 86. 18. 63. 58. 3. 33. 98. 36. 39. also „richtige Mengenklammern”. 61. 25. 94. 47. 20.7 Mengen-Abstraktion 301 26. 19.7 Mengen-Abstraktion Die Mengen-Abstraktion (Set Comprehension) ist analog zur Listen-Abstraktion (List Comprehension). 44. dass man sich nur die Vielfachen der Primzahlen von 1 bis zur Quadratwurzel von n anschauen muss: from math import sqrt def primes(n): if n == 0: return [] elif n == 1: return [1] else: p = primes(int(sqrt(n))) no_p = {j for i in p for j in range(i*2. 55. 68. n) if x not in no_p} return p print(primes(40)) .8 Rekursive Funktion zur Berechnung der Primzahlen Eine effizientere Berechnung der Primzahlen bis zu einer natürlichen Zahl n stellen wir in der folgenden rekursiven Implementierung in Python vor. 71. 22. 80. 21. i)} p = {x for x in range(2. 30. Zur syntaktischen Unterscheidung zur Listen-Abstraktion benutzen wir geschweifte Klammern. 52.26. das vorige Problem zu lösen. 12. 9. 95. 76. 1. 24. 57. 89.

dass eigentlich im vorigen Ausdruck ein Klammerpaar fehlte.11)) <generator object <genexpr> at 0x960e2ac> >>> x**2 for x in range(1. um diese Quadratzahlen zu summieren: >>> sum([x**2 for x in range(1. weil häufig keine Liste benötigt wird. außer dass sie in runde Klammern statt in eckige Klammern eingebettet sind.11))) 385 Bei Reduktionsfunktionen. line 1 x**2 for x in range(1. die ein sequentielles Datenobjekt auf einen Wert reduzieren. Sonst ist es aber notwendig: >>> (x**2 for x in range(1. Im folgenden Summationsausdruck wird zunächst mittels der Listen-Abstraktion die Liste der Quadratzahlen von 1 bis 10 gebildet. über die iteriert wird. Speicherplatzschonend kann man obige Summe also auch so berechnen: >>> sum(x**2 for x in range(1. min und max.11)]) 385 Für die Funktion sum hätte aber auch ein Generator-Objekt statt einer Liste genügt.11) ^ SyntaxError: invalid syntax .11)) 385 Sicherlich haben Sie bemerkt. Danach wird die Funktion sum darauf angewendet. Die Syntax ist nahezu identisch mit der Listen-Abstraktionen. Man hat sie eingeführt.11) File "<stdin>". Im Prinzip hätten wir den Ausdruck so schreiben müssen: >>> sum((x**2 for x in range(1. Erzeugt wird ein Iterator statt einer Liste. sondern nur die einzelnen Elemente. brauchen wir also kein separates Klammernpaar.302 26 Listen-Abstraktion/List Comprehension 26.9 Generator Comprehension/ Generatoren-Abstraktion Die Generatoren-Abstraktion (Generator Comprehension) wurde mit Python 2.6 eingeführt. so wie sum.

Seite 412 .10 Aufgaben 303 26. dass die erste der Zahlen ohne Rest durch die zweite teilbar ist und die beiden Zahlen nicht identisch sind. Lösung: Lösungen zu Kapitel 26 (Listen-Abstraktion/List Comprehension). Seite 411 3.10 1. die obige Wahrscheinlichkeit für eine beliebige Summe als Argument berechnet. Lösung: Lösungen zu Kapitel 26 (Listen-Abstraktion/List Comprehension). Seite 411 2. Aufgabe: Aufgaben Mittels einer Listen-Abstraktion soll die Menge aller Paare von natürlichen Zahlen kleiner als ein gegebenes n gebildet werden unter den Bedingungen. dass beim Wurf zweier Würfel die Summe der Augenzahlen 7 entspricht? Anmerkung: Wir erwarten natürlich. Aufgabe: Schreiben Sie eine Funktion. Lösung: Lösungen zu Kapitel 26 (Listen-Abstraktion/List Comprehension).26. Aufgabe: Wie groß ist die Wahrscheinlichkeit. dass Sie die Aufgabe unter Benutzung von ListenAbstraktionen lösen.

Ein Generator ist also im Prinzip eine Funktion.1 Generatoren le: Zum einen spart man Speicherplatz. der dazu benutzt wird. Falls Letzteres überhaupt möglich ist. Auch wenn man denken könnte. Deshalb werden Generatoren.. Man kann sich ihn wie eine Funktion vorstellen. also zum Beispiel ein Array oder eine Liste. city: Paris . Generatoren können auch potentiell unendliche Folgen von Werten liefern. Im folgenden Beispiel durchlaufen wir die Elemente der Liste „cities”.. Dies hat zwei Vortei. weil die Schleife schneller ihre ersten Werte erhält.BILD 27.."London". dass es sich bei Generatoren um neue und moderne Software-Technik handelt. weil nie eine solche Liste mit all ihren Werten erzeugt werden muss.27 27. sondern einen Wert nach dem anderen. ohne im Besonderen darauf einzugehen. die sich wie ein Iterator verhält."Vienna"] >>> for city in cities: . und zum anderen. print("city: " + city) . wurden sie bereits 1975 in CLU und 1977 in Icon verwendet. 27.1 Generatoren und Iteratoren Einführung In der Informatik versteht man unter einem Generator Programmcode (meist eine Routine oder Funktion)."Berlin". meistens in Schleifen verwendet.2 Iteration in for-Schleifen Iteratoren haben wir bereits in for-Schleifen kennengelernt und häufig benutzt. wie wir schon eingangs erwähnt haben. das Iterationsverhalten einer Schleife zu kontrollieren. die Parameter hat und bei einem Aufruf eine Folge von Werten zurückliefert. dass diese Folge von Werten nicht auf einmal zurückgeliefert wird.. Allerdings mit dem Unterschied. bis die gesamte Folge von Werten berechnet worden ist. denn man muss nicht warten. >>> cities = ["Paris".

Der Rückgabewert von iter() ist ein Element der Klasse „list_iterator”. The capital city of Switzerland is Bern The capital city of Netherlands is Amsterdam The capital city of Germany is Berlin The capital city of France is Paris >>> 1 Häufig wird hierfür der englische Begriff „built-in” benutzt! . "Germany":" Berlin".. dass das Resultat von iter() an eine Variable iter_i gebunden wird. die von der Funktion iter() aufgerufen wird.306 27 Generatoren und Iteratoren city: Berlin city: London city: Vienna >>> Schauen wir uns einmal an. "Netherlands":"Amsterdam".. Man kann diese Iteration auch „manuell” nachvollziehen: >>> l = [23. um die for-Schleife auszuführen: Bevor die Schleife gestartet wird. mit dem es möglich ist. bis next(iter_x) die Ausnahme StopIteration erzeugt. line 1. Auch der Datentyp Dictionary (dict) unterstützt die Iteration. die Elemente der Liste zu durchlaufen. Um das weitere Vorgehen bei der for-Schleife zu verstehen. Die Schleife wird solange wiederholt. ruft Python die eingebaute1 Funktion iter mit der Liste „cities” als Argument auf.34. was Python genau macht. Die eigentliche „Arbeit” erledigt die Methode __iter__ der list-Klasse. also ein Iterator. in <module> StopIteration >>> Die sequentiellen Basistypen sowie ein Großteil der Klassen der Standardbibliothek von Python unterstützen Iterationen. Also in unserem Fall iter_i = iter(cities). nehmen wir an.56. Nach jedem Schleifendurchlauf wird die next-Funktion mit iter_x als Argument aufgerufen und das Ergebnis der Variablen iter_x zugewiesen.. Die Funktion iter liefert nun ein Objekt zurück. print("The capital city of " + country + " is " + capitals[ country]) . "Switzerland":"Bern" } >>> for country in capitals: .. In diesem Fall läuft die Iteration über die Schlüssel des Dictionarys: >>> capitals = { "France":"Paris".78] >>> iter_x = iter(l) >>> next(iter_x) 23 >>> next(iter_x) 34 >>> next(iter_x) 56 >>> next(iter_x) 78 >>> next(iter_x) Traceback (most recent call last): File "<stdin>".

und gleichzeitig werden auch alle Zustände."Berlin". sobald alle Städte im Generator durchlaufen sind. wo der Generator verlassen wird."Berlin".py Paris Berlin London Vienna Die for-Schleife endet also. also die lokalen Variablen. Zur Erinnerung: Bei Funktionen werden alle lokalen Variablen beim Verlassen gelöscht und bei einem neuen Aufruf wieder neu angelegt. Wir können allerdings auch eine Endlosschleife im Generator verwenden.py”."Vienna"] for city in cities: yield city for city in city_generator(): print(city) Trifft der Programmfluss auf die yield-Anweisung."Vienna"] while True: city = cities.3 Generatoren Doch kommen wir zurück zu unserem ersten Beispiel über Städtenamen.3 Generatoren 307 27.27. für einen weiteren Aufruf erhalten. Wir können daraus ein erstes Beispiel für einen Generator bilden: def city_generator(): cities = ["Paris". werden die Städtenamen ausgegeben: $ python3 city_generator.append(city) Speichern wir obige Definition in einer Datei „cities_forever."London". def city_generator(): cities = ["Paris". aber Python „merkt” sich. können wir sie interaktiv in der Python-Shell testen: >>> from cities_forever import city_generator >>> x = city_generator() >>> y = city_generator() >>> next(x) 'Paris' >>> next(x) 'Berlin' >>> next(y) 'Paris' >>> next(x) 'London' >>> next(x) ."London".pop(0) yield city cities. wird der Generator wie bei einer returnAnweisung verlassen. Ruft man dieses Programm auf.

London. London. könnten wir unsere for-Schleife mit einem Zähler und einem break versehen.. London. Vienna. Berlin. Paris. end=".. Paris. Paris. Vienna. Vienna. Paris. Berlin. London. Paris. London .append(city) if __name__ == "__main__": count = 0 for city in city_generator(): if count == 10: print() break print(city. Wir dürfen ihn lediglich nicht in einer Endlosschleife aufrufen. Paris. end=". Paris. Vienna. Berlin. Paris. London. London. London. Paris. Berlin. Vienna. Paris."London". Berlin. Um eine solche Endlosschleife zu vermeiden. Paris. Vienna. Berlin. Paris. Vienna. ") . London.308 27 Generatoren und Iteratoren 'Vienna' >>> next(x) 'Paris' >>> next(y) 'Berlin' >>> Wir sehen also. Dies könnte beispielsweise so aussehen: def city_generator(): cities = ["Paris". Berlin. welchen nach einer bestimmten Anzahl von Iterationen ausgeführt wird. London. London."Vienna"] while True: city = cities. ") count += 1 . Vienna. Berlin. Berlin. Berlin . London. Berlin. Vienna.. Vienna. Paris. Berlin. Vienna. Berlin. Paris. durchaus sinnvoll benutzen können.pop(0) yield city cities. Berlin. print(city. London. Paris. Berlin. wie es im folgenden interaktiven Skript geschieht. Wir müssen dann die Schleife mit „Ctrl-C”’ abbrechen: >>> from cities_forever import city_generator >>> for city in city_generator(): . Vienna. London. Paris. dass wir einen Generator. Vienna. Vienna."Berlin". London. Paris.. Berlin. Berlin. Vienna. London. der eine Endlosschleife beinhaltet. Vienna. London. Vienna.

Berlin. ansonsten spricht man von einer Permutation ohne Wiederholung. Paris. Regal. wie erwartet. kennt man Permutationen aus dem täglichen Leben: ■ Das Mischen der Karten eines Kartenspiels: Der Kartenstapel entspricht einer Permutation aller Karten. folgende Ausgabe: $ python3 cities_forever. BILD 27. einer Liste oder einem Tupel.'e'. der alle Permutationen eines sequentiellen Datenobjekts erzeugt. Paris.'d']): .4 Beispiele 309 Ein Aufruf liefert dann. Berlin. London. $ 27.1 Beispiele Permutationen Unter einer Permutation (von lateinisch permutare. Wenn Objekte mehrfach auftreten dürfen.py Paris. London. Berlin. . . Ein Anagramm ist eine Permutation der Buchstaben eines Wortes: Lager. 2 · 1 Auch wenn das hier sehr abstrakt klingt. Im Folgenden wollen wir uns nur mit Permutationen ohne Wiederholung beschäftigen und einen Generator schreiben. Vienna. von einem String. Vienna. spricht man von einer Permutation mit Wiederholung.2 Permutationen von vier Farben auf vier Plätzen Die Anzahl der Permutationen von n Objekten berechnet sich durch die Fakultät: n ! = n · (n − 1) .4.4 27.27.B.'d']""") for p in permutations(['r'. erlag def permutations(items): n = len(items) if n==0: yield [] else: for i in range(len(items)): for cc in permutations(items[:i]+items[i+1:]): yield [items[i]]+cc ■ print("""permutations for (['r'. vertauschen) versteht man in der Kombinatorik eine Anordnung von Objekten in einer bestimmten Reihenfolge. also z.'e'.

'd'] red rde erd edr dre der permutations of the letters of the string "bin" bin bni ibn inb nbi nib 27.(n − k + 1) (n − k )! Spielt die Reihenfolge dabei keine Rolle.310 27 Generatoren und Iteratoren print(''. Formal heißt dies: Aus n Objekten werden k ohne Zurücklegen und ohne Beachtung der Reihenfolge ausgewählt.. n): if n==0: yield [] else: for i in range(len(items)): for ss in selections(items. Die Anzahl berechnet sich wie folgt: n n n! n · (n − 1) · (n − 2). Bei der Lotterie 6 aus 49 handelt es sich beispielsweise um eine Kombination bzw. n-1): if (not items[i] in ss): . Die Anzahl der Variationen lässt sich wie folgt berechnen: n! = n · (n − 1) · (n − 2). dann spricht man von einer Variation statt von einer Permutation.join(p)) Obiges Programm liefert folgende Ausgabe: $ python3 permutations_generator.2 Variationen und Kombinationen Werden bei einer Anordnung nicht alle Objekte für die Anordnung ausgewählt.. so bezeichnet man dies als eine Kombination.4.(n − k + 1) = = = k n −k k ! · (n − k )! k! Wir können die Kombinationen mit folgendem Generator erzeugen: def selections(items..'e'.. Selektion.py permutations for (['r'.join(p)) print("""permutations of the letters of the string "bin" """) for p in permutations(list("bin")): print(''.

4. 5. 10] [1. 4. 5. 4. Liste) aus der k Elemente ausgewählt und in einer neuen Liste zurückgegeben werden. 2. 2. 2. 3. 5. 5. 3. 18] [1. 4. 3. können Sie auch die Funktion sample aus dem Modul random benützen. k) population ist eine Sequenz (z. 10. 3. >>> import random >>> print(random. 4. 5. 3. 3. 16] [1.50) for s in selections(l. 4. 3.sample(population. 2. Dabei wird „population” aber nicht verändert. 4. 17] [1. 5. 3. 4. 4. 4.4 Beispiele 311 yield [items[i]]+ss print("6 aus 49") i = 0 l = range(1. 41] 2 Achtung: Es dauert ziemlich lange. 21] [1. 4. 4.27. 2. 2. 3. 3. 5. 5. 5. 2. 4. 30. 19] [1. 4. 2. 3. 5. 5. 4. 20] [1. 27] Falls Sie allerdings nur an einem Lottogewinn interessiert sind. 4. 25] [1.B. 5. 2. 2.py 6 aus 49 [1. 5. 3. 4. 4. 5. 9] [1. 11] [1. 5. 3. 4. 24] [1. 3. 5. 2. 13] [1. 14] [1. 3. 2. 2. 3. 2. 8] [1. 4. 2. 5. random. 2. 5.50). 4. 12] [1. 26] [1. 2. 3. 3. 3. 23] [1. 2.6)) [19. 2. 5.sample(range(1. 2. 22] [1. 5. 5. 5. 6] [1. 2. 4. 14. 3. 7] [1. 3. 2. 3.6): print(s) if i > 20: break else: i = i+1 Obiges Programm liefert folgende Ausgabe:2 $ python selections. bis die ersten Ergebnisse nach der Ausgabe „6 aus 49” kommen! Es handelt sich nicht um eine Endlosschleife! . 2. 15] [1.

'Paris'] 27. Vergessen Sie bitte nicht den Autor dieses Buches. Man findet sie in dem Modul itertools.islice(city_generator(). einen Generator zu verwenden. Im nächsten Beispiel die ersten fünf Elemente.islice(city_generator(). ") Aber Python wäre nicht Python. sodass man nun Werte an sie „senden” . der die ersten n Elemente eines anderen Generators ausgibt.append(city) if __name__ == "__main__": for city in firstn(city_generator(). n): for i in range(n): yield next(g) def city_generator(): cities = ["Paris". 10): print(city. Die yield-Anweisung wurde verändert. 'Vienna'."Vienna"] while True: city = cities. Als Parameter erhält er einen Generator g und eine Anzahl n: def firstn(g. Wir schreiben einen solchen Generator. end="."London"."Berlin". sollten Sie einen Sechser haben 27.0.0. Mit der Methode islice kann man sich die Elemente von einer Start.6 send-Methode Seit Python 2.pop(0) yield city cities.5) <itertools.bis zu einer Endposition angeben lassen.islice object at 0xb713f4b4> >>> cities = itertools. die von von city_generator() generiert werden: >>> import itertools >>> from cities_forever import city_generator >>> itertools. den wir firstn nennen.5) >>> list(cities) ['Paris'.5 Generatoren zähmen Eine deutlich elegantere Methode besteht jedoch darin.5 ist es mit Generatoren auch möglich. Werte zu empfangen und nicht nur auszugeben. 'London'. wenn es nicht eine noch elegantere Methode gäbe.312 27 Generatoren und Iteratoren Obige Zahlen können Sie gerne als Tipp für Ihren Lottoschein verwenden. 'Berlin'.

7 Generator-Ausdrücke 313 kann. 16. 81] squares2 = (i**2 for i in range(1.py a b e f a 27. 9.send(4)) print(next(x)) print(next(x)) Wir erhalten folgende Ausgabe: $ python3 abc_generator_with_send. in unserem Beispiel auf 4 gesetzt. wenn er an den Generator gesendet wird. in der Variablen i gespeichert: i = (yield s[count % 6]) Dadurch wird der Wert der Laufvariablen auf einen neuen Wert gesetzt.27. 36. 49. sondern Generatoren. Den Zusammenhang zwischen Listen-Abstraktion und Generator-Ausdrücken zeigt das nächste Beispiel: >>> >>> [1. die ihre Elemente wie Generatoren eines nach dem anderen zurückliefern.10)) type(squares2) . def abc(): s = "abcdef" count = 0 while True: i = (yield s[count % 6]) if i: count = i else: count += 1 if __name__ == "__main__": x = abc() print(next(x)) print(next(x)) print(x. Statt eckigen Klammern werden runde Klammern verwendet. 64.10)] squares1 4. Anders als Listen-Abstraktionen werden keine vollständigen Listen erzeugt. Dies geschieht mittels der send-Methode. Im folgenden Beispiel wird ein Wert. >>> >>> squares1 = [i**2 for i in range(1.7 Generator-Ausdrücke Generator-Ausdrücke sind Listen-Abstraktionen (List Comprehensions) sehr ähnlich. 25.

dann generiert round_robin die Elemente 1. nachdem das letzte Element von g produziert worden ist.8 Aufgaben 1. Zur Erinnerung: Die n-te Fibonacci-Zahl errechnet sich F(n) = F(n-1) + F(n-2). 9. line 1.3. 64. 2 und 3 generiert.3 .1. dass list(squares2) und squares1 identisch sind.3. in <module> StopIteration Der obigen Listenausdruck ist identisch mit dem folgenden Generator: def squares(): for i in range(1. Beispiel: Falls g die Elemente 1.5)) >>> next(squares) 1 >>> next(squares) 4 >>> next(squares) 9 >>> next(squares) 16 >>> next(squares) Traceback (most recent call last): File "<stdin>". >>> squares = (i**2 for i in range(1. . .2. der die Fibonacci-Zahlen generiert. 81] Man sieht.5): yield i ** 2 27.2. 25. Aufgabe: Schreiben Sie einen Generator. beginnt „round_robin” wieder von vorne mit g. der zunächst die Elemente von g auch generiert. 16.314 27 Generatoren und Iteratoren <class 'generator'> >>> list(squares2) [1. .2. 49. Falls g endlich ist.1. 4. mit F(0)=0 und F(1)=1 2. Aufgabe: Schreiben Sie einen Generator „round_robin” mit einem Generator g als Argument. 36.

2 und 3 generiert.1 . 4.3. Wird dann wieder das erste Element erreicht. Nehmen wir an. .27.3. Beispiel: Falls g die Elemente 1.1.8 Aufgaben 315 3.2. . gibt „pendulum” die Elemente von g in umgekehrter Reihenfolge aus.3. . Aufgabe: Schreiben Sie einen Generator „pair_sum” mit einem Generator g als Argument. g 2 . .2.1. „pair_sum” generiert dann die Werte g 1 + g 2 . g n −1 + g n . . g 1 + g 2 . Aufgabe: Schreiben Sie einen Generator „pendulum” mit einem Generator g als Argument. . . g n generiert.2. . der als Erstes die Elemente von g generiert.2. beginnt „pendulum” wieder von vorne. g 2 + g 3 .3. Falls g endlich ist. g n + g 1 . . . . dass g die Werte g 1 . . dann generiert „pendulum” die Folge 1. nachdem das letzte Element von g produziert worden ist.

Im Englischen kommt der Begriff in den Schreibweisen Memoisation und Memoization vor. da es keinen deutschen Begriff gibt. statt die Werte neu zu berechnen. Wird eine Funktion mit den gleichen Parametern aufgerufen wie bei einem vorigen Aufruf. Memoisation ist eine Technik. aber es sind auch kompliziertere Strukturen möglich. So können beispielsweise assoziative Arrays verwendet werden. die in Perl Hashes und in Python Dictionaries genannt werden. welche die Implementierung der Memoisation erleichtern. die in der Programmierung benutzt wird. um den Programmablauf zu beschleunigen. aber einige Programmiersprachen wie auch Python stellen Mechanismen zur Verfügung. Die Memoisation kann explizit vom Programmierer programmiert werden.28 28. was „das zu Erinnernde” bedeutet. Der Ausdruck basiert auf dem lateinischen Wort „memorandum”.1 Memoisation Bedeutung und Herkunft des Begriffes Der Ausdruck „Memoisation”1 wurde im Jahre 1968 von Donald Michie geprägt. 1 Wir haben den englischen Fachbegriff eingedeutscht.1 Gehirn auf die gespeicherten Ergebnisse zugegriffen. wie zum Beispiel die Ergebnisse von Funktionsaufrufen. indem Berechnungsergebnisse gespeichert werden. In vielen Fällen wird ein einfaches Array für die Ergebnisspeicherung benutzt. Dies wird erreicht. . wird BILD 28.

um ein Beispiel. wird auch als Closure oder Funktionsabschluss bezeichnet. d. Dabei handelte es sich bereits. Wir hatten ein Dictionary dazu verwendet. dass wir den Code der rekursiven fib-Funktion ändern bzw. die im Ein.318 28 Memoisation 28.h.h. Ein Aufruf der Funktion memoize(fib) liefert eine Funktion zurück.und Ausgabeverhalten identisch mit fib() ist. wie man das Laufzeitverhalten der rekursiven Version verbessern kann. Diese Technik. Dadurch wird eine Neuberechnung verhindert. was im Deutschen „eingefangen” oder „gefangen genommen” bedeutet. Schönheit und Lesbarkeit nicht tangiert. das Bewahren von „lokalen” Werten oder Funktionen über ihren lokalen Geltungsbereich hinaus. was fib() tut. Dadurch wird ihre Klarheit. ohne dass wir es so genannt hatten. Im folgenden Code präsentieren wir eine Lösung. werden ihre Werte durch die helper-Funktion bewahrt. Das „Problem” besteht darin. Wir hatten gezeigt. memoize() benötigt zwei Argumente. Zusätzlich speichert sie jedoch die Ergebnisse im memo-Dictionary. Die Methode hatte jedoch einen entscheidenden Nachteil: Die Klarheit und die Schönheit der ursprünglichen rekursiven Methode ging dabei verloren. memoize() liefert als Funktionswert eine Referenz auf die helper-Funktion zurück. d. sie tut. Obwohl sowohl die Variable „memo” (unser Dictionary zum Speichern der Werte) als auch die Funktion „f” lokal innerhalb der Funktion memoize sind. also eine Funktion wie die folgende: def fib(n): if n == 0: return 0 elif n == 1: return 1 else: return fib(n-1) + fib(n-2) In unserem Kapitel über Rekursion hatten wir auch einen Weg dargestellt. die ohne Änderungen der fib-Funktion auskommt. Auch die Funktion memoize benutzt ein Dictionary. def memoize(f): memo = {} def helper(x): if x not in memo: memo[x] = f(x) return memo[x] return helper . Zu diesem Zweck definieren wir eine Funktion. dass die direkte Umsetzung der mathematischen Definition der Fibonacci-Zahlen ein exponentielles Laufzeitverhalten aufzeigt. erweitern mussten. um bereits durch die Funktion berechnete Werte für spätere Aufrufe zu speichern. die wir memoize nennen.2 Memoisation mit Dekorateur-Funktionen In unserem Kapitel über rekursive Funktionen hatten wir eine iterative und eine rekursive Funktionsversion zur Berechnung der Fibonacci-Zahlen programmiert. wie man explizit die Technik der Memoisation nutzen kann. Im Englischen benutzt man statt „bewahrt” das Wort „captured”. um die Funktionswerte zu speichern.

*args): if args not in self.fn = fn self. eine Methode oder eine Klassendefinition zu modifizieren. um eine Funktion. Das ursprüngliche 2 3 englisch: mutable englisch: immutable . 28. Tupel.3 Memoize in einer Class Wir können das Zwischenspeichern der Ergebnisse auch in einer Klasse statt einer Funktion einkapseln.memo[args] Da wir ein Dictionary verwenden. was als „Dekorateur” (englisch decorator: Raumgestalter.memo = {} def __call__(self. können wir keine veränderlichen2 Argumente verwenden. Wir demonstrieren dies im folgenden kleinen Beispiel: class Memoize: def __init__(self.memo[args] = self.B.4 Dekorateure in Python Ein Dekorateur in Python ist ein aufrufbares Python-Objekt. also z.28. Dekorateur) bezeichnet wird. dass die fib-Funktion durch die memoize-Funktion dekoriert wird. Anders ausgedrückt: Die Argumente dürfen nur unveränderlich 3 .3 Memoize in einer Class 319 def fib(n): if n == 0: return 0 elif n == 1: return 1 else: return fib(n-1) + fib(n-2) fib = memoize(fib) print(fib(40)) Als nächsten Punkt kommen wir zu einem Konzept.fn(*args) return self. sein. Schauen wir uns die folgende Codezeile an: fib = memoize(fib) In diesem Fall spricht man davon. das benutzt wird. fn): self. 28.memo: self.

handelt es sich um einen Dekorateur. im Beispiel am Anfang dieses Kapitels unseres Tutorials. Allerdings hatten wir in diesem Beispiel nicht die spezielle Syntax von Dekorateuren benutzt. also beispielsweise eine modifizierte Funktion. Statt der Anweisung fib = memoize(fib) können wir vereinfachend folgende Anweisung benutzen: @memoize Allerdings muss diese Zeile unmittelbar vor der dekorierten Funktion stehen. ohne es so zu nennen. Der Dekorateur liefert ein modifiziertes Objekt zurück. Bei der memoizeFunktion. Python-Dekorateure haben eine ähnliche Syntax wie in Java.320 28 Memoisation (als das zu modifizierende) Objekt wird dem Dekorateur als Argument zugeführt. Mit Dekorateur sieht unsere Fibonacci-Funktion wie folgt aus: def memoize(f): memo = {} def helper(x): if x not in memo: memo[x] = f(x) return memo[x] return helper @memoize def fib(n): if n == 0: return 0 elif n == 1: return 1 else: return fib(n-1) + fib(n-2) #fib = memoize(fib) print(fib(40)) . Nun können wir unsere fib-Funktion dekorieren. der modifiziert wird. also das „@”-Zeichen. Dieses modifizierte Objekt wird an den Namen gebunden. Beispiel: Dekorateur für die Memoisation Wir hatten bereits einen Dekorateur benutzt.

28.5 Überprüfung von Argumenten durch Dekorateure Im Abschnitt über rekursive Funktionen hatten wir die Fakultätsfunktion eingeführt. aufgerufen werden. Hätten wir die Argumente der Fakultätsfunktion auf Plausibilität geprüft. und der Kern des Algorithmus wäre nicht mehr so erkennbar gewesen. Dabei wollten wir die Funktion so einfach wie möglich halten. faculty(i)) print(faculty(-1)) .5 Überprüfung von Argumenten durch Dekorateure 321 28. also float-Werten. um sicherzustellen. die allerdings glücklicherweise durch den endlichen Rekursionsstack von Python mit einem RuntimeError abgebrochen wird: RuntimeError: maximum recursion depth exceeded in comparison Das folgende Programm benutzt eine Dekorateur-Funktion. So darf die Funktion keinesfalls mit negativen Werten oder Fließkommazahlen. In beiden Fällen kommt es zu einer endlosen Rekursion. dass es sich bei dem verwendeten Argument um eine positive ganze Zahl handelt: def argument_test_natural_number(f): def helper(x): if type(x) == int and x > 0: return f(x) else: raise Exception("Argument is not an integer") return helper @argument_test_natural_number def faculty(n): if n == 1: return 1 else: return n * faculty(n-1) for i in range(1.10): print(i. dann hätten wir die zugrunde liegende Idee verschleiert.

Diese Werte werden in einem speziellen NumPy-Datentyp ndarray abgespeichert: . Fourier-Transformation und vielen anderen. Zuvor gehen wir noch kurz auf die Funktion arange von numpy ein.1 NumPy Übersicht NumPy und SciPy sind OpenSource-Erweiterungsmodule für Python. Anmerkung zum Bild oben rechts: Das Diagramm in dem Bild entspricht der grafischen Veranschaulichung einer Matrix mit 14 Zeilen und 20 Spalten. die schnelle vorkompilierte Funktionen für mathematische und numerische Routinen bereitstellen.1 Visualisierte Matrix Sowohl NumPy als auch SciPy sind nicht standardmäßig installiert. Die Farbe bestimmt. SciPy („Scientific Python”) erweitert die Funktionalität von NumPy mit nützlichen Funktionen wie Minimierung.29 29. Die Größe eines Quadrats entspricht der Größe eines Wertes in der Matrix. Bei der Installation sollte man jedoch beachten. ob ein Wert positiv oder negativ ist. Regression. besteht der große Vorteil von NumPy und SciPy darin. dass man NumPy vor SciPy installieren muss. dass sie auf Python aufbauen und Python eine modernere und allgemeinere Programmiersprache als MATLAB ist. Wir wollen dies im Folgenden demonstrieren. Auch wenn MATLAB über eine große Anzahl von zusätzlichen Tools verfügt. NumPy („Numeric Python”) dient zur Bearbeitung von großen Arrays und Matrizen mit numerischen Daten. NumPy basiert auf dem Python-Modul Numarray. NumPy und SciPy stellen eine kostenlose und freie Alternative zu MATLAB dar. Wie range erzeugt arange gleichmäßig verteilte Werte. welches seinerseits eine komplette Neuüberarbeitung eines noch älteren Moduls Numeric ist. Es handelt sich dabei um ein sogenanntes „Hinton-Diagramm”. NumPy bietet einen großen Zeitvorteil gegenüber Standard-Python. BILD 29. Also zum Beispiel entspricht die Farbe Rot den negativen Werten und die Farbe Grün in unserem Beispiel den positiven Werten.

.time() X = np.time() . Als Vektoren benutzen wir eindimensionale Arrays der numpy-Klasse ndarray-Array. import time import numpy as np def trad_version(): t1 = time.10.ndarray'> >>> # mit Schrittweite: . Diese erzeugen wir mit der Funktion arange. In der Funktion numpy_version benutzen wir das NumPy-Modul.arange(10000000) Z = X + Y return time.time() . Im folgenden Programm befinden sich zwei Funktionen. wie eingangs gesagt.t1 def numpy_version(): t1 = time..arange(1. den NumPy bietet. den Zeitvorteil demonstrieren.t1 t_trad = trad_version() t_numpy = numpy_version() print("Benötigte Zeit für traditionelle Lösung:") print(t_trad) print("Benötigte Zeit für Lösung mit NumPy:") print(t_numpy) print("Lösung mit NumPy " + str(t_trad * 100 / t_numpy) + " % schneller") Ruft man dieses Programm auf. die wir mit der range-Funktion erzeugen.arange(1.324 29 NumPy >>> import numpy as np >>> x = np. erhält man folgendes beeindruckende Ergebnis: .10) >>> print(x) [1 2 3 4 5 6 7 8 9] >>> type(x) <class 'numpy. >>> x = np.3) >>> print(x) [1 4 7] >>> Nun wollen wir.arange(10000000) Y = np. Wir berechnen dazu die komponentenweise Addition von zwei Vektoren.time() X = range(10000000) Y = range(10000000) Z = [] for i in range(len(X)): Z.append(X[i] + Y[i]) return time. In der Funktion trad_version stellen wir die Vektoren als Listen dar.

2 Arrays in NumPy Arrays sind der zentrale Bestandteil von NumPy.array( ((11.112).12. Der wesentliche Unterschied zu Listen in Python besteht darin.py Benötigte Zeit für traditionelle Lösung: 6. Erzeugung eines Arrays aus einer Liste: >>> import numpy as np >>> x = np. 11]) >>> Die Methode array wandelt eine Sequenz von Sequenzen – im Beispiel Tupel – in ein zweidimensionales Array: >>> x = np.23). d.33)) ) >>> print(x) [[11 12 13] [21 22 23] [31 32 33]] >>> Entsprechend wandelt sie Folgen von Folgen von Folgen in ein 3-dimensionales Array: >>> x = np.32. Arrays sind bedeutend effizienter und schneller als Listen in Python. ((211.212). Ein Array kann später nicht mehr verändert werden.122) ). d. int) >>> x array([42.h.949158840005 % schneller 29. Integer. dass die Elemente eines Arrays alle vom gleichen Typ sein müssen.11806702613830566 Lösung mit NumPy 5552. (21.22.29.array([42. Sie können beliebig dimensional sein.(221.222)) ) ) >>> print(x) [[[111 112] [121 122]] [[211 212] .11].47. Die Anzahl der Elemente muss a priori bekannt sein. 47. (121.556201934814453 Benötigte Zeit für Lösung mit NumPy: 0.array( ( ((111. ■ Selbstverständlich sind Arrays in NumPy nicht auf eine Dimension beschränkt. normalerweise float oder int. Float (Real) oder Komplexe Zahlen. (31.2 Arrays in NumPy 325 $ python3 numpy_comparison.h. wenn das Array erzeugt wird. allerdings mit den folgenden Unterschieden: ■ Alle Elemente haben den gleichen Typ. Prinzipiell können Arrays wie Listen angesehen werden.13).

11]) >>> x[0] 42 >>> x[:2] array([42.47.shape (4.3 Achsen . Die Achsen (axis) eines Arrays beschreiben die Reihenfolge der Indizierungen (axis=0 steht für den ersten Index.array( ((7. 9]. 11.array([42. wir haben sechs Zeilen und drei Spalten. [ 7. 3.3. Dazu steht der shape-Parameter zur Verfügung. 7]. Die Methode shape() liefert ein Tupel mit den Array-Dimensionen zurück: >>> x = np.8))) >>> x. 8]]) >>> BILD 29. 49.7). Im Fall der obersten Abbildung gilt shape = (6. axis=1 für den zweiten und so weiter.0). (15.(12.3). Die Ausprägung („shape”) eines Arrays bezeichnet ein Tupel mit der Anzahl der Elemente pro Achse (Dimension). 47]) >>> x[1] = 49 >>> x array([42. d. Wie die Achsen eines ndimensionalen Vektorraums auf den shape-Parameter verteilt sind. [12.3.9).ndim 2 >>> x.4.11.2 Achsen Ein Besonderheit von NumPy besteht darin.11]) >>> x[:2] array([42. 3. 3) >>> x array([[ 7. Die Bearbeitung von Arrays erfolgt ähnlich wie bei Listen: >>> x = np. 11]) >>> BILD 29. dass man die Verteilung der Elemente auf die Dimensionen auch im Nachhinein wieder verändern kann. [15. 47]) >>> x = np.array([42. 0]. 4. zeigen die beiden Abbildungen.h.47.326 29 NumPy [221 222]]] >>> print(x[1][0][1]) 212 >>> print(x[1][1][1]) 222 >>> Das Attribut ndim gibt Auskunft über die Anzahl der Dimensionen eines Arrays. (7.

5 . [ 6.314 . 0. 7]]..314.67. besteht ein NumPy-Array im Gegensatz zu normalen Listen in Python nur aus Daten des gleichen numerischen Typs. ]) >>> x[0.0.3 ■ Arrays flach machen Es gibt zwei Methoden.4142]) >>> x[:.314.0 >>> Auch bei 2-dimensionalen Arrays kann man Slices einsetzen: >>> x[:. 0. 1].array([ [[ 0. 5].67 .1] array([ 0. um ein mehrdimensionales Array flach zu machen1 : flatten() ravel()2 ■ Die Arbeitsweise können wir im folgenden Beispiel an einem dreidimensionalen Array beobachten: import numpy as np x = np.3 Arrays flach machen 327 Im Folgenden zeigen wir ein Beispiel eines zweidimensionalen Arrays: >>> x = np. 29. 7]].29.2] array([ 17. [ 4. verwickeln. 0. der die Zahlen in doppelter Präzision abspeichert. 0. ]) >>> x[1] array([ 1.array([[0. 7.4142. also Integer oder Float.[1. [ 2.5. float) >>> x[0] array([ 0. verheddern”. englisch: flatten Dies Wahl des Begriffes ist „verwirrend” (ravelling): Das Wort „ravel” bedeutet im Englischen „verwirren.2] 17. Sie tut das Gegenteil.4142. was aber Englisch dem Verb „ravel out” entsprechen würde.67]) >>> x[:. >>> x.]) >>> Wir wir bereits erfahren haben. ähnlich zu dem Typ float in Python. 17. Mit dem Attribut dtype kann man den Typ der Werte eines Arrays ermitteln. was die Methode ravel aber nicht tut.dtype dtype('float64') float64 ist ein numerischer Typ von NumPy. . 1. 7.0] array([ 0.5 .17]. 1 2 3].

ravel()) print("x:") print(x) Sowohl flatten als auch ravel liefern ein Objekt <class ’numpy.flatten():") print(x. flatten und ravel liefern die gleichen Ergebnisse zurück. aber es gibt Unterschiede in der Implementierung. 9]. wenn möglich eine View zurückzuliefern. es wird versucht. 23]]]) print("Aufruf von x.flatten(): [ 0 1 2 3 4 5 6 7 8 Aufruf von x. $ python3 numpy_arrays. [12. 15]]. 21]. 11].3 Wir sehen bei der Ausgabe des Skripts. dessen Dimension 3 Verwirrend? ravel hat also seinen Namen zu Recht erhalten – siehe vorige Fußnote.4 Arrays umdimensionieren Arrays lassen sich in NumPy beliebig umdimensionieren. flatten erzeugt immer eine komplette Kopie der Daten. dass das ursprüngliche Array x unverändert geblieben ist.h. 13].ndarray’> zurück. wie notwendig ist. Dazu wird die Methode reshape(t) zur Verfügung gestellt. d.py Aufruf von x. 19]. Das Argument von reshape ist ein Tupel. [[16. [14. [20.flatten()) print("Aufruf von x. verändern aber nicht ihr Objekt.flatten():") print(x. [22. [10. 17]. während im Falle von ravel opportunistisch nur so viel kopiert wird.flatten(): [ 0 1 2 3 4 5 6 7 8 x: [[[ 0 1] [ 2 3] [ 4 5] [ 6 7]] [[ 8 9] [10 11] [12 13] [14 15]] [[16 [18 [20 [22 17] 19] 21] 23]]] 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23] 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23] 29. [18.328 29 NumPy [[ 8. .

34. 94. Die Methode reshape() liefert ein Array mit geänderten Dimensionen zurück. 26. [ 2. 22. 19]. [18.1:-1] array([[11. 15]]. 16. 3]. [60. 9. 9]. [30. 89]. 69]. 2. 47. 91. 24. 79]. 21. [70. 32. während die Werte dieses Tupels die Verteilung der Elemente über die Dimensionen widerspiegelt. 71. 75. 62. [41. 27. 13. 48]. . 21. 31. 11]. 22. 17. 92. 13]. 1. [[16.2)) >>> y array([[[ 0. 7. [40. 12. [21. 36. 6. 7. 48. 1. 17. [ 4. [ 6. 42. 52. 23. 93. [[ 8. 14. 23. 12. 49]. 11. 28. 19]. 5]. >>> y[1:-1.array(range(100)) >>> y = x. 32. 57. 21].4. [20. 85. 68. 67. die letzte Zeile. 7]]. 4. 26. 25. ohne dass die Daten des als Parameter übergebenen Arrays verändert werden. 86. 28]. 12. 99]]) 18]. 78. 83. die erste Spalte und die letzte Spalte entfernt: >>> x = np. 5. 45.array(range(24)) >>> y = x. 24. wie wir mit Slices geschickt den Rand eines Arrays wegschneiden können. [90. 98. 18. 44. 36. 6. 51. 23]) >>> Im folgenden Beispiel zeigen wir. 59]. [10. 33. [31. 42. 66. 46. 20. Beispiel: >>> import numpy as np >>> x = np. 55. [50. 43. 3. [14. 25. 88. 72. 73. >>> x array([ 0. 64.4 Arrays umdimensionieren 329 die Dimension des veränderten Arrays darstellt. 43. 38]. 33. 84. 10. 81. 9]. 17. 4. 54. 15. 14. Es werden also die erste Zeile. 77. 18. 47. [20.29. 44. 23]]]) 8. 74. 63. 13. 37. 17]. 95. 61. 38. [12. 27. 37.reshape(10. 16. 46. 3. 1]. [22. 22. 53. 5. [80. 35.reshape((3. 29]. 8. 15. 96. 65. 11. 35. 2. 56. 41. [10. 39]. 82. 97. 14. 16. 13. 34. 19. 87.10) >>> y array([[ 0. 76. 45. 58. 15.

1. . >>> 52. 63. [71. Anschließend werden die Elemente des dritten Arrays daran angehängt: >>> import numpy as np >>> x = np. 85. [[ 8.2)) >>> z = np.124)) >>> y = y. [81. 1]. 67. 13]. >>> 3. 57. 5].3. [ 4. Man kann allerdings auch den optionalen Parameter axis explizit setzen: >>> x = np. 72. 19]. 7]]. [[ [ [ [ 16. 53. [ 6. 83. 58].concatenate((x.reshape((3. 54.2)) >>> y = np.array(range(100. 87. 68].z)) array([11. 7. 18. 74. 18. 56. 15]]. 84. 65. 22.reshape((3. 17].concatenate((x. 22. [61. 73.330 29 NumPy [51. 55. 6. 86. 21]. 76.array([18.4. [ 12. Die Elemente des zweiten Arrays werden an das erste Array angehängt. wird default-mäßig nach der ersten Achse (axis = 0) verknüpft. 66. 88]]) 29. 23]].y. 82. [ 2. 62.5]) >>> np. 20. [ 14. 77. 64.array([1.6]) >>> z = np.7.array(range(24)) >>> x = x.5 Arrays konkatenieren Im folgenden Beispiel konkatenieren4 wir drei eindimensionale Arrays. 5]) Wenn wir mehrdimensionale Arrays konkatenieren. 4 Konkatenieren stammt vom lateinischen catena. 11]. Unter Konkatenieren versteht man also „verketten” oder „verknüpfen”.22]) >>> y = np. 9]. 78].y)) >>> z array([[[ 0. [ 10. was Kette bedeutet.4.array([11. 75. 3].

113]. 101]. [ 6. 101]. [104. [118. [ 6. 3]. [[ 8. 105]. [ 2. 119]. [ 22. [114. [110.axis = 2) >>> z array([[[ 0. [108. 123]]]) >>> >>> z = np. 23].29. 103]. [116. 107]]. 102. [[116. .concatenate((x. 9].5 Arrays konkatenieren 331 [[100. 5]. 1]. [ 10. 115]]. [ 14. 109]. [ 20. 1. 7]. 123]]]) >>> >>> z = np. [102. 103]. 107]]. 100. [104. 119]. [112. 106. 117]. 103].y). 17]. 121]. 105]. 111]. [106. 19]. [112. [114. [120. 13]. 117]. 108. [110. 15].concatenate((x. [[ 16. [118. [ 4.y). 104. 111]. 115]]. 3. [122. 11]. [102. 7. 5.axis = 1) >>> z array([[[ 0. 107]]. [122. [100. 101]. [[ 8. [[108. 105]. 109]. [ 4. [120. 113]. 109]. [106. 21]. 9. [ 2. [ 18. 121]. [ 12.

111].. 1. 117].18. 114. [ 5]. Arrays mit Nullen oder Einsen zu initialisieren. 18. 1.7 Array mit Nullen und Einsen initialisieren Es gibt zwei Möglichkeiten. neue Dimension hinzufügen Neue Dimensionen können einem Array mittels Slicing und np. 11. [ 1. 1]. [[ [ [ [ >>> 16. 118. 1.. np. Bei Default wird das Array mit Einsen vom Typ float gefüllt.ones((3.3)) array([[ 1. 1. 14.].. [18].14. 1.array([2. 1.newaxis] >>> y array([[ 2]. 121]. 13. 4]) >>> y = x[:. 1]]) >>> . [ 12. kann man den optionalen Parameter dtype auf int setzen: >>> np. 22.dtype=int) array([[1. [1.4]) >>> x array([ 2. Wir demonstrieren diese Technik im folgenden Beispiel: >>> x = np. 1].6 Array. 113].5. 122. Wenn man Einsen vom Typ Integer braucht. 20. [14]. 116..ones((2. 1.]]) >>> np. 5.newaxis hinzugefügt werden. 123]]]) 29. 1. 110.332 29 NumPy [ 10. 115]]. 18. [ 14. [ 4]]) >>> 29. 17.4). 21. 19. 119]. 15. 23. 120. Die Methode ones(t) benötigt ein Tupel t mit der „shape” des zu schaffenden Arrays und füllt das Array entsprechend mit Einsen. 112. 1. [1. 1.

. wie wir in Python mittels NumPy ohne Aufwand und effizient Matrizenarithmetik betreiben können...zeros_like(x) array([0. also ■ Matrizenaddition Matrizensubtraktion Matrizenmultiplikation Skalarprodukt Kreuzprodukt und weitere arithmetische Funktionen auf Matrizen ■ ■ ■ ■ ■ Die arithmetischen Standardoperationen +. 1.1]) >>> x + y array([8. 1]. In diesem Abschnitt wollen wir zeigen.ones_like(x) array([1.array([1.y array([-6. 0.]]) Es gibt noch eine weitere interessante Möglichkeit. 0.29.14285714. 0. >>> x = np. dtype=int32) >>> x / y array([ 0. /. 2]. damit man diese Operatoren anwenden kann. 0]) >>> 29. 9.14.4.. 20.. 0. d. >>> import numpy as np >>> x = np.8 Matrizenarithmetik Bisher haben wir gesehen. [ 0.4]) >>> np. 1.h.]. *. 0.4)) array([[ 0.18. wie man Arrays erzeugen und ändern kann. wenn das Array die „shape” eines anderen existierenden Arrays „a” haben soll.5. ]) . ** und % werden elementweise angewendet. 0. wie wir im folgenden Beispiel sehen: >>> np. 1. 3].5. -. 1..8 Matrizenarithmetik 333 Was wir über die Methode ones() gesagt haben. 0.2]) >>> y = np. eine Matrix mit Einsen oder Nullen zu füllen. 1. dtype=int32) >>> x * y array([ 7. die Arrays müssen die gleichen Größen haben.25 . gilt analog für die Methode zeros(). dtype=int32) >>> x . 0. 2. Für diesen Zweck stellt NumPy die Methoden ones_like(a) und zeros_like(a) zur Verfügung. >>> 0.array([2. dtype=int32) >>> np. 1].zeros((2.array([7.

9 Vektoraddition und Vektorsubtraktion Vielen dürfte die Vektoraddition aus dem Physikunterricht der Schule bekannt sein.334 29 NumPy >>> x % y array([1. um die Gesamtkraft zu berechnen. platzieren wir die End.y = x + (-y). Grafisch wird eine Vektoraddition realisiert. indem man die jeweiligen Komponenten miteinander addiert. siehe Bild auf der rechten Seite. ist das Gleiche.1]) >>> z = x + y >>> z array([8. >>> import numpy as np >>> x = np. Man benutzt die Vektoraddition.array([3. als wenn man das Negative von y zu dem Vektor x addiert. 3]. wenn verschiedene Einzelkräfte mit unterschiedlichen Ausrichtungen auf einen als punktförmig angenommenen Körper einwirken. 1. Mathematisch gesehen wird die Vektorsubtraktion durch eine komponentenweise Subtraktion der einzelnen Komponenten durchgeführt. dtype=int32) >>> 29. >>> x = np. welche Kraft insgesamt BILD 29.array([5.5 Achsen punkte von x und y auf den gleichen Punkt. Rechnerisch kann man mit der Vektoraddition die Gesamtverschiebung der Vektoren ermitteln.BILD 29. Dieser „Pfeil” ist ein Repräsentant des Vektors x . den Anfang des zweiten Vektors ansetzt.array([5.2]) >>> y = np. Wenn man wissen will. Geometrisch kann man die Subtraktion eines Vektors wie folgt durchführen: Um y von x zu subtrahieren. Es gilt also: x . dtype=int32) >>> Einen Vektor y von einem Vektor x zu subtrahieren. muss man eine sogenannte Vektoraddition durchführen.2]) >>> y = np. Dann zeichnen wir einen Pfeil von der Spitze von y zu der Spitze von x.1]) .4 Achsen auf den Körper ausgeübt wird.array([3. indem man durch Parallelverschiebung an die Spitze des ersten Vektors. an der sich der Pfeil befindet.y. also die Stelle. 0].

y >>> z array([-2.dot(x.29.” häufig als Operatorzeichen für diese Operation genutzt wird. dass der „. um den Winkel zwischen zwei Vektoren zu ermitteln: Berechnung des Skalarprodukts: ⃗ a ·⃗ b = a1 · b1 + a2 · b2 + a3 · b3 Es ist leicht einzusehen. 1]. Mathematisch stellt das Skalarprodukt eine algebraische Operation dar. Der Name Punktprodukt (oder englisch „dot product”) stammt übrigens davon. dass das Ergebnis der Operation ein Skalar ist. dtype=int32) >>> Das Skalarprodukt wird häufig auch als inneres Produkt oder Punktprodukt bezeichnet.x)) Der Winkel zwischen ⃗ x und ⃗ y berechnet sich als: cos ∠(⃗ x.⃗ y) = ⃗ x ·⃗ y ⃗ | x |·|⃗ y| .9 Vektoraddition und Vektorsubtraktion 335 >>> z = x . die zwei Koordinationvektoren gleicher Größe als Argument nimmt und eine einfache Zahl zurückliefert. Der Name Skalarprodukt stellt mehr den Aspekt in den Vordergrund. auch über das Skalarprodukt definieren bzw. indem die Komponenten mit gleichem Index multipliziert und die so erhaltenen Produkte anschließend addiert werden. Definition des Skalarprodukts: ⃗ a ·⃗ b =| ⃗ a |·|⃗ a | cos ∠(⃗ a . dass man den Betrag.⃗ b) Aus der Definition des Skalarprodukts können wir ersehen. Das Ergebnis wird berechnet.sqrt(np. also die Länge eines Vektors. dass es benutzt werden kann. berechnen kann: |⃗ a |= ⃗ a ·⃗ a= a1 · a1 + a2 · a2 + a3 · a3 = 2 2 2 a1 + a2 + a3 Wir wollen nun mit konkreten Vektoren mit dem Skalarprodukt in NumPy „herumspielen”: Wir benutzen zwei Beispielvektoren ⃗ x und ⃗ y:    2 −2 ⃗ x =  7  und ⃗ y = 3  −3 4  Der Absolutbetrag von ⃗ x berechnet sich wie folgt:    2 −2  7 · 3  −3 4  |⃗ x |= ⃗ a ·⃗ a= Dies entspricht in NumPy-Notation: numpy.

2).-3]) >>> x_abs = np.arccos(cos_xy) >>> angle_xy # Winkel in Bodenmaß 1. dass sie eine komfortable Notation für verschiedene Matrizenoperationen wie z.dot(x.array([2. die Matrix-Multiplikation zur Verfügung stellen. (3. [28. >>> x = np. -5]]) >>> x = np. während NumPy-Arrays von beliebiger Dimension sein können.x)) >>> x_abs 7.10 Matrix-Klasse Die Matrix-Klasse ist eine Unterklasse der NumPy-Arrays (ndarray).sqrt(np. Der größte Vorteil von Matrizen liegt darin.7.2).y) / ( x_abs * y_abs) In der folgenden interaktiven Python-Shell wenden wir die obigen Überlegungen an: >>> import numpy as np >>> x = np.y) / ( x_abs * y_abs) >>> cos_xy 0.3).y)) >>> y_abs 5. 5)) ) >>> y = np. 1]]) .228117822203146 >>> 29. Wenn X und Y zwei Matrizen sind. 5)) ) >>> y = np. [15. dann definiert X * Y eine komponentenweise Multiplikation.sqrt(np. also n-dimensional. dass die NumPyMatrizen streng 2-dimensional sind.4]) >>> y_abs = np. (5.8740078740118111 >>> y = np.array([-2.pi # Winkel in Gradmaß 83. Ein Unterschied besteht darin. (3.11791665765914455 >>> angle_xy = np. Wenn allerdings X und Y zwei ndarrays sind.array( ((1. Ein Matrix-Objekt erbt alle Attribute und Methoden von ndarry. -1)) ) >>> x * y array([[ 2.dot(x.336 29 NumPy Im unten stehenden Skript wird dies wie folgt berechnet: cos_xy = np.matrix( ((1. -1)) ) >>> x * y matrix([[17.dot(x.4526046862352173 >>> angle_xy * 360 / 2 / np. dann definiert X * Y die Matrix-Multiplikation. 6].B.3.array( ((2.3). 1].matrix( ((2.dot(y.3851648071345037 >>> cos_xy = np. (5.

1]. wodurch eine Matrizenmultiplikation durchführt wird: >>> import numpy as np >>> x = np. die wie folgt berechnet wird: m ci j = k =1 ai k · bk j Die folgende Grafik verdeutlicht dieses Verfahren..mat("1 2. j =1.mat(y) matrix([[17.l ..mat("2 3. 5)) ) >>> y = np.. (5..array( ((1. [28.. 1]]) >>> . (3. 1]]) ■ Wie eben.array( ((2. (5.m und einer (m x n)-Matrix B = (b i j )i =1.3).. -1)) ) >>> np. eine Matrizenmultiplikation durchzuführen: ■ Wir definieren zwei Matrizen x und y als zweidimensionale Arrays und bilden das Kreuzprodukt.n .m .. (3.29.2)... aber statt des Kreuzprodukts casten wir x und y in Matrix-Objekte: >>> import numpy as np >>> x = np.y) array([[17. 5)) ) >>> y = np.dot(x.mat(x) * np.3). 5 -1") >>> np. [28.10 Matrix-Klasse 337 29.array( ((1.10. 1].1 Matrix-Produkt Das Produkt einer (l x m)-Matrix A = (a i j )i =1. 1]. -1)) ) >>> np.array( ((2.l . j =1.n ist eine Matrix C = (c i j )i =1.2). j =1.mat(x) * np.mat(y) matrix([[17. [28. 1]]) >>> x = np. 3 5") >>> y = np. Es gibt mehrere Möglichkeiten.

können wir NumPy und die Matrizenmultiplikation nutzen: .matrix("1 2. 175 g der Marke B und 210 von C. Außerdem kaufte sie noch 120 g der Marke A.matrix("2 3. B und C gekauft.90 und C nur 1. [28. wir haben vier Personen. B kostet 3.mat("2 3.10. 1]. A kostet 2. Dafür scheint sie ein echter Fan der Sorte C zu sein. Jeder von ihnen hat Pralinen der Marken A. wie viel die einzelnen Sorten kosten: ■ ■ ■ Wenn wir nun berechnen wollen. Mia wählte 90 g von A. Leon und Hannah taufen. Hannah mag allem Anschein nach die Sorte B nicht. 3 5") >>> y = np. 3 5") >>> y = np.matrix(y) matrix([[17.2 Eine einfache praktische Anwendung In dem folgenden praktischen Beispiel kommen wir auf die Schokoladenseite des Lebens zu sprechen. BILD 29. 1]]) >>> mat ist übrigens eine Abkürzung für matrix.matrix(x) * np. [28. weil sie davon gleich 310 g gekauft hat. 160 g von B und 150 g von C. 1]]) >>> 29. 5 -1") >>> np. die wir Lukas. >>> import numpy as np >>> x = np. Wir hätten also auch ebensogut Folgendes schreiben können: >>> import numpy as np >>> x = np.mat(y) matrix([[17.6 Pralinen Nun wollen wir natürlich wissen.98 pro 100 g.mat("1 2. 1]. 50 von B und 100 g von C. Nehmen wir an.99 Euro. Mia.mat(x) * np. Leon kaufte 200 g von A. weil sie keine Pralinen dieser Sorte gekauft hat. Lukas kaufte 100 g der Marke A. wie viel jeder von ihnen zu zahlen hat.338 29 NumPy ■ Wir definieren x und y sofort als Matrix-Objekte. 5 -1") >>> np.

3.00000000e+00]]) >>> . 1..0.[120.[200. 11.linalg.]]) Im folgenden Beispiel entspricht E der Einheitsmatrix.00000000e+00. dann gilt. wenn man von numerischen Ungenauigkeiten absieht: >>> A = np.linalg.eye(3) >>> E array([[ 1.array([100. [ -5.A_inv) >>> E array([[ 1.dot(PersAnz. 0.150].55111512e-17.100.2]. Hat man die inverse Matrix A_inv zu einer quadratischen Matrix A berechnet.dot(A. 1].00000000e+00. 0. dass die Matrizenmultiplikation von A und A_inv die Einheitsmatrix ergibt.100]. 2.210].array([2.55111512e-17.dot(A_inv.90.inv(A) >>> E = np. Mia 11. -5. 0.1.90 Euro und Hannah 9. [ 0.98.907. 29..-2]]) >>> A_inv = np..50.310]]) >>> Preis_per_100_g = np. 1. 0. also die Matrix. 1.inv) kann man eine Matrix invertieren.77555756e-17]. dass Lukas 13.. [ 0. 9. [2.]. [1. 5.98 Euro. A_inv) = np. >>> 0..00000000e+00.11 Inverse Matrix Mit der Funktion inv (numpy.-1.[90.11022302e-16].array([[3.984.Preis_per_100_g) >>> Preis_in_ Euro = Preis_in_Cent / np.].11 Inverse Matrix 339 >>> PersAnz = np.99]) >>> Preis_in_Cent = np.100.175.dot(A. A) = E Hierbei ist E die Einheitsmatrix. [ -5..160. die auf der Diagonalen nur Einsen hat und ansonsten Nullen.97 Euro.9 . Die Einheitsmatrix lässt sich übrigens mit der Funktion eye von numpy generieren: >>> E = np.29. Leon 9. 1. 1. also: np.0.75 Euro zu zahlen haben.55111512e-17.745]) >>> Das bedeutet. 9.100]) >>> Preis_in_Euro array([ 13.array ([[100.

0. >>> import numpy as np >>> x = np. Dies wird manchmal auch als Drei-Finger-Regel bezeichnet. linalg bietet beispielsweise die Funktion solve zum Lösen von linearen Gleichungssystemen. erhalten wir ein Rechteck. 0]) >>> BILD 29.h. 0. Zeigefinger und Mittelfinger der rechten Hand. Die Länge des Ergebnisvektors entspricht der Fläche des von den beiden multiplizierten Vektoren aufgespannten Parallelogramms. Das Kreuzprodukt zweier Vektoren ⃗ a und ⃗ b wird mit ⃗ a ×⃗ b bezeichnet. Falls die beiden Vektoren senkrecht zueinander stehen.y) array([-1. der senkrecht zu den Vektoren ⃗ a und ⃗ b steht.array([0.0]) >>> np.FingerRegel ermittelt werden kann.13 Lineare Gleichungssysteme NumPy besitzt viele weitere Funktionen und Methoden zur Berechnungen von weiteren Anwendungen aus der Linearen Algebra. Sie verhalten sich wie Daumen. Das Ergebnis ist ein Vektor.cross(y. d.⃗ b )) · ⃗ n wobei der Vektor ⃗ n derjenige zu ⃗ a und ⃗ b senkrechte Einheitsvektor ist. Das Kreuz.x) array([1. die multipliziert werden.7 Kreuzprodukt 29. Der richtige ist der. Senkrecht im Sinne eines Rechtssystems. dem Kreuzprodukt oder Vektorprodukt. ⃗ n steht senkrecht auf der von ⃗ a und ⃗ b aufgespannten Ebene. die beiden Vektoren ⃗ a und ⃗ b sowie der Vektor ⃗ a ×⃗ b bilden ein Rechtssystem.340 29 NumPy 29. der mit der Drei.array([0. Dazu bietet sich vor allen Dingen das Paket linalg an.cross(x. dann ist ihr Kreuzprodukt gleich Null. 0.oder Vektorprodukt ist eine binäre Operation im dreidimensionalen Raum. der diese zu einem Rechtssystem ergänzt.1]) >>> y = np.1. die multipliziert werden.12 Kreuzprodukt / Vektorprodukt Nun müssen wir wieder den Konsum der leckeren Pralinen einstellen und uns einem kalorienärmeren. Das Kreuzprodukt ist definiert als: ⃗ a ×⃗ b = (| ⃗ a | · |⃗ b | · sin ∠(⃗ a . 0]) >>> np. . die diese Eigenschaft erfüllen. Falls einer der Vektoren. Null ist oder wenn die beiden Vektoren parallel sind. mathematischeren Thema zuwenden. Es gibt zwei Vektoren.

0].array([[4.b) >>> x array([ 1.-2].[-1. -8.5.[1.5.2.linalg.solve(A.2].7.29. Hier eine 4 x 4 Koeffizientenmatrix. die sogenannte Koeffizientenmatrix.-2.linalg >>> A = np. -1. wie es unserem Beispiel entspricht:   a1 1 a1 2 a1 3 a1 4  a 1 a 2 a 3 a 4  2 2 2 2     a 3 1 a 3 2 a 3 3 a 3 4 a4 1 a4 2 a4 3 a4 4 Mit den Werten aus unserem Beispielgleichungssystem sieht A dann wie folgt aus:   4 −2 7 0 −1 5 3 2     −1 2 5 −2 1 2 3 4 Der Vektor ⃗ b entspricht den Werten auf den rechten Seiten der Gleichungssysteme:   −7  12    ⃗ b=  −8 14 Damit sieht unser Gleichungssystem wie folgt aus:       4 −2 7 0 x1 −7 −1     5 3 2   x 2   12   ·  =   −1 2 5 −2 x 3  −8 1 2 3 4 x4 14 Nun kommen wir endlich zur Lösung dieses Gleichungssystems in Python: >>> import numpy as np. 12...4]]) >>> b = np.3. 3. 14]) >>> x = np.3.array([-7.13 Lineare Gleichungssysteme 341 Betrachten wir das folgende Gleichungssystem: 4x 1 − 2x 2 + 7x 3 = −7 −x 1 + 5x 2 + 3x 3 + 2x 4 = 12 −x 1 + 2x 2 + 5x 3 − 2x 4 = −8 x 1 + 2x 2 + 3x 3 + 4x 4 = 14 Ein solches Gleichungssystem kann man unter Benutzung der Matrix-Vektor-Multiplikation wie folgt schreiben: A ·⃗ x =⃗ b wobei A eine Matrix ist.]) >>> . 2.[-1.2.. numpy.

2 und -1 die Nullstellen von f. >>> >>> >>> 5 >>> 45 import numpy as np f = np. . Seien 3. d. Dabei müssen die Koeffizienten in absteigender Reihenfolge angegeben werden. dass poly1d ein ndarray mit den Koeffizienten der Funktion erwartet. Zur Darstellung von Polynomen 0 f (x ) = i =n a i · x i = a n · x n + a n −1 · x n −1 + . Dann kann man f schreiben als f (x ) = (x − 3)(x − 2)(x + 1) In NumPy definiert man f ebenfalls mit poly1d.-1].True) >>> f poly1d([ 1.h.5 .-2. Dann kann man eine Funktion auch in Produktschreibweise schreiben. 1. Beispiel: Wir wollen das folgende Beispielpolynom in Python implementieren: f (x ) = 3 · x 2 − 2 · x + 5 Wir sehen in der folgenden interaktiven Python-Shell.2.5]) f(0) f(4) Polynome kann man bekanntlich auch in Linearfaktoren über die Nullstellen zerlegen. -4. aber man muss den zweiten Parameter auf True setzen.14 Polynome NumPy eignet sich auch hervorragend zum Umgang mit Polynomen und stellt hierfür auch ein Paket polynomial zur Verfügung. >>> import numpy as np >>> f = np. die Koeffizienten von den höchsten Exponenten zuerst. sondern ein ndarry mit Nullstellen.342 29 NumPy 29. 6]) >>> f(3) 0 >>> f(2) 0 >>> f(-1) 0 >>> 5 1d steht für 1-dimensional. a 2 · x 2 + a 1 · x + a 0 dient die Klasse poly1d.poly1d([3. . Dann erwartet poly1d keine Koeffizienten.poly1d([3. .

29.15 Aufgaben

343

Von einem Polynom kann man sich auch die Nullstellen mit der Funktion roots6 bestimmen lassen: Beispiel: Wir berechnen die Nullstellen für das Polynom: f (x ) = x 3 − x 2 − 10 · x − 8 Die Berechnung in NumPy sieht wie folgt aus:
>>> import numpy as np >>> f = np.poly1d([ 1, >>> np.roots(f) array([ 4., -2., -1.]) >>>

-1, -10,

-8])

Mit numpy lassen sich auch die Ableitung und unbestimmte Integrale von Polynomen bestimmen. Dazu gibt es die Methoden deriv()7 und integ():
>>> import numpy as np >>> f = np.poly1d([3,-2,-1]) >>> f.deriv() poly1d([ 6, -2], dtype=int32) >>> f.integ() poly1d([ 1., -1., -1., 0.]) >>>

29.15
1. Aufgabe:

Aufgaben

Prüfen Sie, ob die folgenden Vektoren orthogonal (senkrecht) zueinander sind.     2 −2   1. ⃗ x = 7 und ⃗ y = 1  −3 1     2 −5 2. ⃗ x =  3  und ⃗ y = 4  −1 2 Lösung: Lösungen zu Kapitel 29 (NumPy), Seite 415

6 7

„roots” bezeichnet im Englischen auch die Nullstellen eines Polynoms Englisch: derivation

344

29 NumPy

2. Aufgabe: Bestimmen Sie den Winkel zwischen den beiden Vektoren:     5 −3   ⃗ x = 9 und ⃗ y = 0  −5 6 Lösung: Lösungen zu Kapitel 29 (NumPy), Seite 415

3. Aufgabe: Lösen Sie das folgende Gleichungssystem:
−2x 1 − 2x 2 + 2x 3 + x 4 = −5 −3x 1 + 4x 2 + −2x 4 = −1 −x 1 + 2x 2 + 3x 3 + 2x 4 = 0 3x 1 + 2x 2 + 3x 3 + 2x 4 = 4

Lösung: Lösungen zu Kapitel 29 (NumPy), Seite 416

4. Aufgabe: Berechnen Sie die Nullstellen für das folgende Polynom:
f (x ) = 4 · x 3 + 12 · x 2 − 7 · x − 5

Lösung: Lösungen zu Kapitel 29 (NumPy), Seite 416

5. Aufgabe: Bestimmen Sie für das folgende Polynom das unbestimmte Integral und die Ableitung:
f (x ) = 2 · x 3 − 3 · x 2 − 2 · x − 1

Lösung: Lösungen zu Kapitel 29 (NumPy), Seite 416

TEIL III
Umfassende Beispiele

30
30.1

Bruchklasse

Brüche à la 1001 Nacht

Bevor wir mit der Arbeit an unserem Modul und mit den Brüchen beginnen, möchten wir Sie noch in die Welt Aladins und Sinbads entführen. An einem Zwischenstopp an einer Oase finden wir drei Männer mit einer Herde Kamele. Sie jammern und wehklagen. Der Älteste der drei mit langem Bart und Turban wendet sich an Sie und sagt: — „Wir sind drei Brüder und haben diese 35 Kamele als unser Erbe erhalten. Nach dem Wunsch meines Vaters soll die Hälfte der Herde mir als dem ältesten Sohn gehören.”

BILD 30.1 Walter Heubach: Lagernde Karawane mit Dromedaren

— „Und ein Drittel soll mir gehören!”, sagt der mittlere der drei Brüder. — „Ich als jüngster soll mich mit einem Neuntel zufriedengeben!”, sagt der letzte der Dreien. — „Die Hälfte von 35 ist 17 und ein halb, und wir wollen kein Kamel zerteilen!”, fährt der Älteste fort. — „Die Schwierigkeiten, ein Drittel und ein Neuntel der Herde zu bestimmen, sind auch nicht kleiner!”, jammern die beiden anderen unisono. Plötzlich haben Sie einen genialen Einfall und schlagen den ratlosen Brüdern Folgendes vor: Sie geben Ihr einziges Kamel, das Sie noch weiter durch die Wüste tragen soll, der Herde hinzu und sagen zum ältesten Bruder: — „Vorher hättest du 17 und ein halbes Kamel erhalten sollen, doch nun sind es 18!” Zum mittleren der Brüder sagen Sie: — „Vorher hättest du 11 und zwei Drittel Kamele erhalten sollen, nun werden es 12 sein. Du hast also auch keinen Grund zum Klagen.”

348

30 Bruchklasse

Und zum Jüngsten sagen Sie: — „Du wirst nun 4 Kamele statt 3 und noch einen Teil von einem weiteren erhalten und hast auch keinen Grund zu Klage!” Die Brüder ziehen nun voller Freude mit ihren 34 Kamelen von dannen, und Sie haben nun zwei Kamele statt einem!

30.2

Zurück in die Gegenwart

Ja, damals zu Sinbads Zeiten war Bruchrechnen noch eine hohe und wenig erforschte Kunst, und mit solchen Geschichten konnte man die Leute leicht verzaubern. Sicherlich haben Sie das Problem gleich erkannt. 1 1 1 + + =? 2 3 9 Wir wollen nun eine Python-Klasse für das RechBILD 30.2 Brüche als Kuchennen mit Brüchen entwickeln, wobei wir uns aber auf diagramm die vier Grundrechenarten „Addition”, „Subtraktion”, „Multiplikation” und „Division” beschränken wollen. Zunächst müssen wir uns aber die Frage stellen, wie wir einen Bruch in Python darstellen wollen. Ein Bruch besteht ja bekanntlich aus einem Zähler, einem Bruchstrich und einem Nenner. Mathematisch relevant sind natürlich nur Zähler und Nenner, während der Bruchstrich bloß ein Repräsentationsdetail ist. Zur Repräsentierung eines Bruchs in unserer Bruchklasse genügt es also, wenn wir ein Attribut für den Nenner und eines für den Zähler definieren. Im folgenden Beispiel finden Sie 2 die __init__-Methode, und wir erzeugen Instanzen für die Brüche 1 2 und 5 :
class Bruch(object): def __init__(self,z,n): self.zaehler = z self.nenner = n if __name__ == "__main__": x = Bruch(1,3) y = Bruch(2,5)

Wie sieht es aus, wenn wir einen dieser Brüche versuchen auszudrucken? Wenn wir obiges Programm unter brueche.py gespeichert haben, können wir es direkt auf der interaktiven Python-Shell testen:
$ python3 Python 3.2.3 (default, Oct 19 2012, 19:53:57)

30.2 Zurück in die Gegenwart

349

[GCC 4.7.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from brueche import Bruch >>> x = Bruch(2,3) >>> print(x) <brueche.Bruch object at 0xb71994ec>

Positiv ist, dass wir einen Bruch ausgeben können, aber leider erhalten wir kein Ergebnis, dass wir uns wünschen würden. Für die Ausgabe der Variable x würden wir eher „2/3” erwarten. Dies lässt sich ziemlich einfach realisieren. Dazu erweitern wir unsere Klasse um eine Methode __str__.
def __str__(self): return str(self.zaehler)+'/'+str(self.nenner)

Die Methode stellt eine Wandlung des Klassenobjekts, in unserem Fall also ein Bruch, in die String-Repräsentation des Objekts dar. Wird print mit einem Klassenobjekt aufgerufen, wendet Python automatisch die __str__-Methode auf das Objekt an und druckt den Ergebnisstring aus:
$ python3 Python 3.2.3 (default, Oct 19 2012, 19:53:57) [GCC 4.7.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from brueche import Bruch >>> x = Bruch(2,3) >>> print(x) 2/3

Zur Bruchrechnung gehört das Kürzen. Unter dem Kürzen eines Bruchs versteht man, dass man Zähler und Nenner des Bruchs durch die gleiche Zahl dividiert. Kürzen dient der Vereinfachung von Brüchen. Der Wert des Bruchs bleibt beim Kürzen gleich. Man erhält lediglich eine neue Darstellung derselben Bruchzahl. So sind zum Beispiel die folgenden Brüche alle gleich: 1 2 3 , , , 3 6 9 und so weiter. Die Zahl, durch die man kürzt, wird als Kürzungszahl bezeichnet. Ein Bruch ist in vollständig gekürzter Form, wenn Zähler und Nenner teilerfremd sind. Also in obiger Folge der Bruch 1 3 . Um einen Bruch in eine vollständig gekürzte Form zu wandeln, muss man den größten gemeinsamen Teiler, abgekürzt ggT, ermitteln. Der Euklidische Algorithmus ist ein effizientes Verfahren, um den größten gemeinsamen Teiler zweier Zahlen zu berechnen. Bei diesem Algorithmus wird in aufeinanderfolgenden Schritten jeweils eine Division mit Rest durchgeführt, wobei der Rest im nächsten Schritt zum neuen Divisor wird und der vorige Divisor zum Dividenden. Der Divisor, bei dem sich Rest 0 ergibt, ist der größte gemeinsame Teiler der Ausgangszahlen.

350

30 Bruchklasse

Beispiel:
>>> 170 >>> 51 >>> 17 >>> 0 561 % 391 391 % 170 170 % 51 51 % 17

Also ist 17 der größte gemeinsame Teiler der Zahlen 561 und 391. Obige Berechnung hätte man interessanterweise auch mit 391%561 starten können. Im nächsten Schritt hat man dann 561%391 und die weitere Rechnung läuft wie oben weiter. Im Folgenden führen wir die gleichen Berechnungen mit Variablen aus:
>>> a = 170 >>> b = 391 >>> a, b = b, a >>> print(a,b) 391 170 >>> a, b = b, a >>> print(a,b) 170 51 >>> a, b = b, a >>> print(a,b) 51 17 >>> a, b = b, a >>> print(a,b) 17 0

% b

% b

% b

% b

Wir können unser Programm nun um eine Klassenmethode ggT, die obiges Verfahren anwendet, und eine Methode kuerze erweitern. Außerdem rufen wir kuerze bei der Initialisierung eines Bruchs auf, damit ein Bruch immer in vollständig gekürzter Form gespeichert wird. Unsere Klasse sieht nun wie folgt aus:
class Bruch(object): def __init__(self,z,n): self.zaehler = z self.nenner = n self.kuerze() def __str__(self): return str(self.zaehler)+'/'+str(self.nenner) def ggT(cls,a,b): while b != 0: a,b = b,a%b return a def kuerze(self): g = self.ggT(self.zaehler, self.nenner)

.. kann das Ergebnis der obigen Multiplikation noch durch den größten gemeinsamen Teiler von 6 und 15.y) Startet man obiges Programm. Bis jetzt fehlen aber noch die wichtigsten Methode in unserer Bruchklasse BIS HIER.3. In diesem Fall spricht man von Erweitern. .py 1/3 23/33 Man sieht. erhält man folgende Ausgabe: $ python3 brueche. und man erhält als Ergebnis einen neuen Bruch. wie man Brüche multipliziert. indem man ihre Zähler und Nenner miteinander multipliziert. Ebenso verändert sich ein Bruch nicht. wenn man Zähler und Nenner mit der gleichen ganzen Zahl multipliziert. wenn man Zähler und Nenner durch einen gemeinsamen Teiler dividiert.1 Multiplikation von Brüchen Als Erstes zeigen wir.30. 01. .. 30. Das Produkt der Zähler wird zum Zähler des Ergebnisses. da dies am einfachsten ist: Brüche werden multipliziert. − 1. aber wir können keine Operationen auf den Brüchen ausführen.3 Rechenregeln Wie auch beim Rechnen mit natürlichen Zahlen1 oder ganzen Zahlen2 werden beim Rechnen in den vier Grundrechenarten jeweils zwei Brüche miteinander verknüpft. .561) print(x. −2. Wir haben bereits im vorigen Abschnitt gezeigt. das Produkt der Nenner wird zum Nenner des Ergebnisses: Beispiel: 2 3 2·3 6 · = = 3 5 3 · 5 15 Wie wir sehen. Wir können Brüche definieren und ausgeben. dass sich der Wert eines Bruchs nicht ändert.nenner/g) if __name__ == "__main__": x = Bruch(2.zaehler/g) self.nenner = int(self. 30.. 2. gekürzt werden: 6 2 = 15 5 1 2 N = 1. dass die Brüche vollständig gekürzt wurden. also 3. Man spricht dann von Kürzen.3 Rechenregeln 351 self. 2.6) y = Bruch(391. 3. 3.zaehler = int(self. Z = −3.

Wir können nun zwei Brüche multiplizieren. 30.other): p = Bruch(self. um unsere Bruchklasse um eine Multiplikation zu erweitern. indem man mit seinem Kehrwert multipliziert. "credits" or "license" for more information. "copyright". self. 19:53:57) [GCC 4. .nenner * other.2. self. Oct 19 2012. rufen wir nach der Initialisierung noch die Methode kuerze mit „p.2] on linux2 Type "help".7.3) >>> y = Bruch(4. Der Name für die Division in Python 3 lautet __truediv__4 : def __truediv__(self. Dazu müssen wir die Methode __mul__ bereitstellen3 : def __mul__(self. damit entspricht x dem „self” und y dem „other”.kuerze() return p In der Methode __mul__ erzeugen wir einen neuen Bruch P .kuerze() return p 3 4 Siehe Kapitel Operator-Überladung.kuerze()” auf. Da der Bruch noch in nicht vollständig gekürzter Form vorliegen kann.zaehler) p.h.zaehler * other.352 30 Bruchklasse Nun haben wissen wir genug.__mul__(y) gewandelt.3 (default. >>> from brueche import Bruch >>> x = Bruch(2.2 Division von Brüchen Die Division von Brüchen ist ähnlich einfach wie die Multiplikation. Durch einen Bruch wird dividiert.zaehler * other.nenner) p.nenner * other. Seite 187 Vor Python 3 hieß diese Methode __div__. Beispiel: 2 5 2 3 2·3 6 : = · = = 3 3 3 5 3 · 5 15 Unsere Methode für die Division zweier Brüche lässt sich nahezu analog zur Multiplikation realisieren.zaehler.nenner. Dieser wird mit der Initialisierung sofort auf das Ergebnis der Multiplikation gesetzt.other): p = Bruch(self.15) >>> print(x * y) 8/45 >>> z = x * y >>> print(z) 8/45 Intern wird ein Ausdruck „x * y” in den Aufruf „x.3. wie wir im folgenden Beispiel sehen: $ python3 Python 3. d.

Oct 19 2012.3 (default.3) >>> y = Bruch(15. nenner.nenner. 19:53:57) [GCC 4.4) >>> print(x/y) 8/45 30. d.3 Addition von Brüchen Im Vergleich zur Multiplikation und Division von Brüchen gestaltet sich die Addition ebenso wie die Subtraktion etwas schwieriger. dass anschließend die beiden Nenner gleich sind.nenner+other.h.zaehler*other.2. Bevor man zwei Brüche addieren kann.nenner*other. "copyright".h. "credits" or "license" for more information. müssen sie zuerst gleichnamig gemacht werden.nenner+other.reduce() return s 30.3 Rechenregeln 353 Im Folgenden zeigen wir. .3.zaehler * self.3.2] on linux2 Type "help".4 Subtraktion von Brüchen Die Subtraktion läuft analog zur Addition.zaehler * self. Beispiel: 2 3 2 4 3 3 2 · 4 + 3 · 3 17 + = · + · = = 3 4 3 4 4 3 3·4 12 Nun können wir die Python-Methode für die Addition (__add__) angeben: def __add__(self. Sind die Nenner gleich. d. können die Zähler einfach addiert werden. wie man Brüche in unserer Bruchklasse dividieren kann: $ python3 Python 3.30. erst müssen die Brüche gleichnamig gemacht werden und dann kann man die Zähler subtrahieren.other): s = fraction(self. Beispiel: 3 2 3 3 2 4 3·3−2·4 1 − = · + · = = 4 3 4 3 3 4 3·4 12 Die Python-Methode für die Subtraktion (__sub__) kann fast gleich wie die Additionsmethode geschrieben werden: def __sub__(self. >>> from brueche import Bruch >>> x = Bruch(2.nenner) s.7.other): s = Bruch(self.zaehler*other. self. sie müssen so erweitert werden.

nenner) def ggT(cls.zaehler * other. other): return self. „<=”: def __eq__(self. 30.zaehler)+'/'+str(self.nenner > other.nenner def __ne__(self.zaehler * other.zaehler = z self.n): self.nenner) self.zaehler. eine Methode __cmd__ zu definieren anstelle der obigen sechs Methoden. Aber diese Methode ist mit Python 3 entfallen.354 30 Bruchklasse self.zaehler * self.zaehler * self.nenner < other. „>=”.kuerze() def __str__(self): return str(self.nenner def __lt__(self.5 Die Bruchklasse im Überblick Unsere Bruchklasse ist nun fertig.zaehler. other): return self.nenner = int(self. also für „==”.zaehler/g) self.nenner) .b): while b != 0: a.nenner*other. „<”. class Bruch(object): def __init__(self.nenner/g) def __mul__(self.ggT(self.b = b.nenner def __ge__(self.zaehler * other.zaehler * self.nenner >= other.nenner == other.zaehler * other. other): return self.zaehler = int(self.nenner <= other.zaehler * self.a%b return a def kuerze(self): g = self.nenner In Python 2.zaehler * other.nenner) s. other): return self.kuerze() return s Im Folgenden wollen wir noch die Methoden für die Vergleichsoperatoren von Brüchen angeben.nenner = n self. „!=”. other): return not self. self.zaehler * other.x genügte es übrigens.other): p = Bruch(self.a.nenner * other.zaehler * self. „>”. und im Folgenden sehen wir die gesamte Klasse im Überblick.nenner def __le__(self.z.__eq__(other) def __gt__(self. self. other): return self.3.

nenner if __name__ == "__main__": x = Bruch(2. other): return self.zaehler * other.nenner+other. other): return self.nenner def __lt__(self.nenner > other.other): s = Bruch(self.zaehler * other. other): return self.nenner def __ge__(self.nenner.zaehler*other.zaehler * other.30.__eq__(other) def __gt__(self.zaehler * other.nenner .zaehler * self.3 Rechenregeln 355 p.nenner < other. other): return self.nenner) s. other): return self. self.zaehler * self.zaehler * self.zaehler * other.nenner * other.nenner*other. self.y) if x < y: print("x < y") else: print("x >= y") print(x) == other.nenner >= other.nenner def __ne__(self. other): return not self.nenner) s.nenner*other.6) y = Bruch(3.other): p = Bruch(self.nenner.nenner def __le__(self.zaehler * self.other): s = Bruch(self.kuerze() return s def __eq__(self.zaehler * self.nenner.kuerze() return p def __truediv__(self.14) print(x * y) print(x / y) print(x + y) print(x .zaehler * self.kuerze() return s def __sub__(self.zaehler * other.kuerze() return p def __add__(self.zaehler*other. self.zaehler) p.zaehler * self.nenner+other.nenner <= other.

1 Das Spiel wurde im Jahre 1970 von dem israelischen Spieledesigner Mordechai Meirovitz erfunden. BILD 31.uk/mastermind/history.tnelson. Genauer gesagt hat er „nur” die Umsetzung eines alten Spiels mit dem Namen „Cows and Bulls” in eine Spielbrettversion erfunden. Jahrhundert zurückverfolgen. Dieses „Cows and Bulls”2 kann man bis ins 19.1 Mastermind 1 2 Toby Nelson: „A Brief History of the MasterMindTM Board Game”. Es wird von zwei Spielern gespielt. Wir wollen eine Version des Spiels Mastermind schreiben.1 Mastermind Die Ursprünge des Spiels In diesem Kapitel wollen wir einige der Funktionen und Programme. http://www. Die Spielidee von „Mastermind” und „Cows and Bulls” ist im Wesentlichen identisch. in einer größeren Anwendung zusammenfließen lassen. Mastermind ist eines der erfolgreichsten Spiele der 1970er-Jahre. die wir im Laufe des Buches geschrieben haben. einen Code zu knacken.co. .html Das Spiel ist auch unter den Namen „Pigs and Bulls” und „Bulls and Cleots” bekannt. die in der Lage ist. um die Codierung vorzunehmen. Während Mastermind farbige Stifte benutzt. Die Beurteilung eines Versuchs wird in Mastermind mit schwarzen und weißen Stiften beurteilt.demon. basiert „Cows and Bulls” auf der Benutzung von Ziffern.31 31. 55 Millionen Exemplare dieses Spiels in über 80 Ländern verkauft. Bis zum Jahr 2000 wurden weltweit ca.

Allerdings gibt es auch Versionen des Spiels.2 Mastermind Die Spielregeln von Mastermind sind analog zu „Bulls and Cows”. aber es werden Farben statt Ziffern benutzt. Das Spiel wird normalerweise zu zweit gespielt. darf man eine vierstellige Zahl raten. 31. Die zwei Bullen („Bulls”) bedeuten. so beurteilt der Mitspieler dies mit zwei Bulls und einer Cow. Das erste bekannte Programm nannte sich „moo” und war in PL/I geschrieben. Der Gegner muss diesen Versuch beurteilen. Die eine Kuh („Cow”) bedeutet. in der das mehrfache Vorkommen von Ziffern in einer Zahl erlaubt ist. Der erste Spieler.4 Die Aufgabe des Spiels besteht nun darin. Statt Zahlen werden hier farbige Stecker verwendet. Man benötigt lediglich einen Stift und Papier. der den gesamten Code des Gegners richtig geraten hat. BILD 31. den Geheimcode des Mitspielers herauszufinden. . aber an der falschen Stelle steht. Gewonnen hat derjenige. den Code des anderen zu erraten. Dieses Spiel wurde sehr häufig implementiert. Die Ziffern dieser vierstelligen Zahl müssen verschieden sein.2 31.2.358 31 Mastermind 31. ist der Sieger des Spiels. die 4 und die 3.1 Die Spielregeln „Bulls and Cows” Um „Bulls and Cows” spielen zu können. In unserem Fall die Ziffer 2. Ansonsten sind die Spielregeln nahezu analog.2 Mastermind als Spielbrett 3 4 Es können natürlich auch mehr oder weniger Stellen vereinbart werden. dass eine Ziffer zwar richtig geraten worden ist. Man gibt an. wie viele „Cows” und wie viele „Bulls” in dem Versuch stecken. muss man nichts kaufen. Zum Spielen benutzt man ein käuflich erhältliches Spielbrett.2. dem es als Erstem gelingt. Gilt es zum Beispiel die Ziffernfolge „4 3 2 5” des Mitspielers zu erraten und besteht der eigene Versuch aus „4 3 1 2”.h. dass zwei Ziffern korrekt an der richtigen Stelle geraten worden sind. Um den Code des Mitspielers herauszufinden. Jeder Spieler schreibt eine vierstellige3 Zahl auf ein Blatt Papier. Zur Beurteilen gibt es statt „Bulls” schwarze Stecker und statt „Cows” weiße Stecker. d.

implementieren.31.2.py: import random def fac(n): if n == 0: return 1 else: return (fac(n-1) * n) def permutations(items): n = len(items) if n==0: yield [] else: for i in range(len(items)): for cc in permutations(items[:i]+items[i+1:]): yield [items[i]]+cc def k_permutations(items. Oct 19 2012. max) i = 0 for p in permutations(list): if i == index: return p i += 1 def all_colours(colours. positions): colours = random_permutation(colours) for s in k_permutations(colours.3 Kombinatorikmodul Wir wollen nun das Mastermind-Spiel in Python umsetzen. $ python3 Python 3. 19:53:57) . Er generiert einen Iterator für alle k-Permutationen eines sequentiellen Datentyps „colours”.randrange(0. Wir speichern den folgenden Programmcode unter combinatorics. positions): yield(s) Der Generator all_colours() gehört streng genommen nicht in das obige Modul. n-1): if (not items[i] in ss): yield [items[i]]+ss def random_permutation(list): length = len(list). index = random. Im Laufe unseres Buchs haben wir bereits alle zur Implementierung unseres MastermindAlgorithmus notwendigen kombinatorischen Funktionen entwickelt.3 Kombinatorikmodul 359 31. n): if n==0: yield [] else: for i in range(len(items)): for ss in k_permutations(items.3 (default.h. max = fac(length). d. da es sich schon um einen für unser Problem maßgeschneiderten Iterator handelt.

'b']. '. 'b']. '.7. 'b']. 'a'. Die Anzahl der Stellen legen wir in number_of_positions fest. 'a']."c". ['d'. 'b'."orange". 'a'. 'a']. information. 'b'. ['c'. '. 'c']. 'a']. 'b']. 'a']. >>> list(all_colours("abc". 'a'. 'a']. 'b'].2] on linux2 Type "help".360 31 Mastermind [GCC 4. 'c']. 'a'. 'b']] 'c']. 'c'. 'b'. ['a'. 'a'. ['d'. '. 'c'. ['c'. ['d'. ['c'. ['a'. ['a'. 'c'. 'a'. 'c']. 'b']."pink"] ausdenkt. 'b']. '. 'b']. '. 'd']. ['b'. 'c']. ['a'. 'c']. 'c'. 'd']. 'b']. ['b'. 'b']. ['b'. 'd'."d"]. 'b']. 'c'. ['a'. 'd']. >>> list(all_colours("abc". ['b'. 'c']. 'b'. ['a'. 'c']. 'a']. ['b'. 'd']. die später die Versuche und deren Bewertungen enthalten wird: guesses = [] .2)) [['c'. 'a']] 31. 'a'. ['c'. 'c']. 'd']. ['d'. "copyright". ['c'.4 Mastermind in Python Nun können wir mit der Implementierung unseres eigentlichen Mastermind-Programms beginnen. ['a'. ['a'."c". 'c']. 'b'. 'c'].3)) [['c'. '. den ein menschlicher Spieler sich aus einer Menge Farben. ['b'. 'b'. 'b'. 'c']."yellow". 'c'. 'd'. ['a'. ['b'. 'd']. ['c'. 'd'. ['d'. ['a'. 'd'. 'b']] 'c']. 'c']. 'a']. 'c'. 'a']. ['a'. >>> list(all_colours("abcd". ['b'. ['a'. 'd'. 'd']. 'd'. ['b'. ['b'."b". 'b'. 'a']. 'c'. ['d'. 'a'. ['c'. also zum Beispiel colours = ["red". 'b']. 'b']. 'd'. 'a']. '. 'b']. ['c'. ['c'.3) <generator object all_colours at 0xb7176a54> >>> list(all_colours(["a". 'c'. 'd'. ['c'. 'c']. ['a'. 'b']. 'c']. ['c'. 'a']. ['b'. 'd'. 'b'. 'c'].3)) [['d'. 'd']] ['d ['a ['b ['b ['c ['c ['d ['b ['b ['a Der Unterschied zu unserem k_permutations-Generator besteht darin. 'a'. 'c'. ['b'. 'd']. 'd'. 'c'. 'a']] 'a']. Unser Programm soll den n-stelligen Farbcode herausfinden. 'd'. ['d'. 'a']. Also zum Beispiel den Wert 4: number_of_positions = 4 Wir erzeugen eine leere Liste. 'd']. '. 'b'. ['b'. 'b']."b". ['a'. ['c'. '. 'd']. ['b'. 'c']. ['a'. ['b'. ['a'. ['d'. 'a'. ['c'.2)) [['a'. 'd']. 'b']. "credits" or "license" for more >>> from combinatorics import all_colours >>> all_colours(["a". 'a'. 'a'. 'b']. 'c']."d"]. 'a']. 'a'].2)) [['c'. 'c']] 'a']. 'd'. 'a']. 'c'. 'b'. ['b'.2)) [['a'. ['c'."green". >>> list(all_colours("abc". ['c'. 'b'. 'a']."blue". ['d'. dass wir immer mit einer Zufallspermutation starten: >>> list(all_colours("abc".

0). ■ Schauen wir uns nun die Funktion new_evaluation genauer an: def new_evaluation(current_colour_choice): rightly_positioned. also das Tupel (number_of_ positions.31. wenn ■ das Programm die Farbauswahl erfolgreich geraten hat. Drei andere Farben waren zwar richtig. 'red'. [(['blue'. 3) Obige Bewertung bedeutet also: Eine Farbe war richtig und stand auch an der richtigen Stelle. 'yellow'].h. 0). permutated)) . Als Nächstes erzeugen wir einen Iterator für alle möglichen k-Permutationen der Farben „colours”: permutation_iterator = all_colours(colours. in unserem Fall (4. number_of_positions) Dann erzeugen wir eine erste Farbauswahl. 'yellow'] und das zweite Element entspricht einer Bewertung. (rightly_positioned. standen aber an der falschen Position. ein Tupel bestehend aus dieser Farbliste und einer Bewertung.0) zurückgeliefert. also zum Beispiel: ['blue'.4 Mastermind in Python 361 Diese Liste besteht aus 2-Tupeln. zurückgeliefert wird oder die Antworten des menschlichen Mitspielers widersprüchlich waren. d. weil wir nichts Näheres wissen und weil dieses Tupel für den folgenden Ablauf gesetzt sein muss: new_guess = (current_colour_choice. 'red'. Als Endekriterium dient die Bewertung. d.h. 'yellow '. die die Funktion new_evaluation für eine Farbauswahl zurückliefert: Die Schleife endet.0). 'orange']. (1. (0. 'orange'. permutated = get_evaluation(current_colour_choice) if rightly_positioned == number_of_positions: return(current_colour_choice. es wird das Tupel (-1.0) ) Die while-Schleife erzeugt Versuche. 'orange'. Wir setzen die Bewertung auf (0. 3))] Das erste Element eines solchen 2-Tupels entspricht einer Liste mit einer 4-stelligen Farbauswahl.B. also vier Zufallsfarben aus der durch „colours” definierten Liste von möglichen Farben: current_colour_choice = next(permutation_iterator) Mit dieser Liste erzeugen wir nun einen „Versuch”. 'red'. 3)). die nicht im Widerspruch zu vorigen Versuchen stehen. also einem 2-Tupel mit einer Zahl als erster Komponente für die Anzahl der schwarzen Stifte (also richtige Farben an der richtigen Position) und der Anzahl der weißen Stifte (also der richtigen Farben an der falschen Stelle): (1. z. (1. (['blue'.

permutated ))) view_guesses() current_colour_choice = create_new_guess() if not current_colour_choice: return(current_colour_choice.append((current_colour_choice. Anschließend wird mit create_new_guess versucht. the input makes no sense") return(current_colour_choice. (-1. permutated) = guess[1] . Falls der Wert von rightly_positioned gleich der Anzahl der Positionen ist. ob die Bewertung des menschlichen Mitspielers Sinn macht.py: import random from combinatorics import all_colours def inconsistent(p. if a permutation p. eine neue mögliche Farbkombination zu erzeugen. permutated)): print("Input Error: Sorry. permutated)) Die Variablen rightly_positioned und permutated entsprechen der Anzahl der schwarzen und der weißen Stifte. (-1. Mit der Funktion get_evaluation wird eine Bewertung vom menschlichen Mitspieler erfragt. permutated)) Im Folgenden finden Sie ein komplettes Listing von mastermind. 'yellow'. (-1.e. wird der Versuch und die Bewertung in der Liste der guesses mit der Methode append aufgenommen. also number_of_positions. Mit der Funktion answer_ok wird überprüft.362 31 Mastermind if not answer_ok((rightly_positioned. So darf zum Beispiel die Summe der Werte von rightly_positioned und permutated nicht größer als die Anzahl der Positionen number_of_positions sein: if not answer_ok((rightly_positioned. a list of colours like p = ['pink'. 'green'. (rightly_positioned. the input makes no sense") return(current_colour_choice. permutated)) guesses. guesses): """ the function checks. i. permutated)) return(current_colour_choice. p) (rightly_positioned. (rightly_positioned. Each previous colour permutation guess[0] compared (check()) with p has to return the same amount of blacks (rightly positioned colours) and whites (right colour at wrong position) as the corresponding evaluation (guess[1] in the list guesses) """ for guess in guesses: res = check(guess[0]. die im Einklang mit den bisherigen Versuchen steht. Falls nicht wird eine -1 im Bewertungstupel übergeben: current_colour_choice = create_new_guess() if not current_colour_choice: return(current_colour_choice. (rightly_positioned. permutated)) Falls die die Bewertung okay war. 'red'] is consistent with the previous colours. permutated)): print("Input Error: Sorry. (-1. sind alle Farben geraten und stehen an der richtigen Position. permutated)) return(current_colour_choice.

4 Mastermind in Python 363 if res != [rightly_positioned. (rightly_positioned. adds the choice together with the evaluation as a tuple to the list of guesses. the input makes no sense") return(current_colour_choice. (rightly_positioned. checks the consistency of this choice.""" rightly_positioned. (-1. permutated)) if not answer_ok((rightly_positioned.append((current_colour_choice. (rightly_positioned. permutated) = a if (rightly_positioned + permutated > number_of_positions) \ or (rightly_positioned + permutated < len(colours) number_of_positions): return False if rightly_positioned == 3 and permutated == 1: return False return True def get_evaluation(guess): """ asks the human player for an evaluation """ show_current_guess(guess) rightly_positioned = int(input("Blacks: ")) permutated = int(input("Whites: ")) return (rightly_positioned. permutated = get_evaluation(current_colour_choice) if rightly_positioned == number_of_positions: return(current_colour_choice. permutated)) def check(p1. consistent def answer_ok(a): """ checking of an evaluation given by the human player makes sense.e.31. permutated)): print("Input Error: Sorry. p2): """ check() calculates the number of bulls (blacks) and cows (whites) of two permutations """ blacks = 0 whites = 0 for i in range(len(p1)): . """ (rightly_positioned. (-1. permutated)) return(current_colour_choice. 3 blacks and 1 white make no sense for example. permutated) def new_evaluation(current_colour_choice): """ This function gets a new colour choice. permutated]: return True # inconsistent return False # i. permutated)) guesses. permutated ))) view_guesses() current_colour_choice = create_new_guess() if not current_colour_choice: return(current_colour_choice. It returns a tuple with the colour choice and the evaluation of this choice.

(0.0) ) while (new_guess[1][0] == -1) or (new_guess[1][0] != number_of_positions) : print(guesses) new_guess = new_evaluation(new_guess[0]) . guesses): try: next_choice = next(permutation_iterator) except StopIteration: print("Error: Your answers were inconsistent!") return () return next_choice def show_current_guess(new_guess): """ The current guess is printed to stdout """ print("New Guess: "."orange". end=" ") for i in guess[1]: print(" %i " % i.end=" ") for c in new_guess: print(c."pink"] guesses = [] number_of_positions = 4 permutation_iterator = all_colours(colours. end=" ") print() colours = ["red"."blue". end=" ") print() def view_guesses(): """ The list of all guesses with the corresponding evaluations is printed """ print("Previous Guesses:") for guess in guesses: guessed_colours = guess[0] for c in guessed_colours: print(c. number_of_positions) current_colour_choice = next(permutation_iterator) new_guess = (current_colour_choice. whites] def create_new_guess(): """ a new guess is created.364 31 Mastermind if p1[i] == p2[i]: blacks += 1 else: if p1[i] in p2: whites += 1 return [blacks."yellow"."green". which is consistent to the previous guesses """ next_choice = next(permutation_iterator) while inconsistent(next_choice.

Dieser „Jemand” könnte auch ein automatisches Textklassifikationssystem sein. wohin. Grafiken.1 Textklassifikation Einführung in die Textklassifikation Die Klassifikation und Kategorisierung von Dokumenten ist ein Thema der Informationswissenschaft. Dabei geht es um die Auswertung. Kategorisierung von Dokumenten benötigen. um welches Anliegen es geht. Partituren usw. Sehr häufig handelt es sich bei den Dokumenten um reine Textdokumente. die auch Bilder. Musik. also beispielsweise „Adressänderung”. Üblicherweise hat ein großer Teil dieser Eingangspost weder einen korrekten Betreff noch eine Namens. Aber erst der unglaubliche Anstieg in verfügbaren Online-Dokumenten in den letzten beiden Jahrzehnten im Zusammenhang mit der Expansion des Internets hat sich das Interesse an der automatischen Dokumentenklassifikation und dem Data Mining erneuert und intensiviert. und dann spricht man von Textklassifikation. „Anfrage zu einem Produkt” usw. die jeden Tag Berge von Eingangspost zu bewältigen hat.32 32. das Suchen und Finden sowie das Bereitstellen und Verwerten von Informationen. aus der eindeutig hervorgeht. aber heutzutage gibt es viele Situationen. kann man sich BILD 32. sowohl in elektronischer als auch in papiergebundener Form. die sich mit der Untersuchung von Informationen und Wissen beschäftigt. die sich Klassen oder Kategorien zuordnen lassen. das Erschließen. Jemand muss also diese Post lesen und entscheiden. d. Dieser Ansatz stellte sich als hochgradig ineffizient für kom- . also zu welcher Person oder Abteilung. Dokumentenklassifikation sind allgemeine Dokumente. Wenn es um Dokumente geht. die Aufgaben dadurch zu lösen. Anfänglich war die Dokumentenklassifikation auf heuristische Methoden fixiert. dass man Expertenwissen in Regelwerke packte. „Beschwerdeschreiben”.oder Abteilungsnennung. Die Geschichte der automatischen Textklassifikation geht zurück bis in an den Anfang der 1960er-Jahre. Dies mag ziemlich abstrakt klingen. enthalten können. eine Wissenschaft. in denen Firmen die automatische Klassifikation bzw. Man denke nur beispielsweise an eine große Firma. die Selektion.h. man versuchte. das Poststück weitergeleitet werden kann.1 Textklassifikation als Prisma der automatischen Dokumentenklassifikation bedienen.

Die Lernphase kann man grob in drei Arten unterteilen: ■ Die notwendige Information für das Lernen. die dennoch in der praktischen Anwendung zu hervorragenden Ergebnissen führt.366 32 Textklassifikation plexe Aufgaben heraus. Abwesenheit von allen anderen Merkmalen.h. sodass heutzutage der Fokus auf automatischem Lernen und der Anwendung von Clustering-Methoden liegt. d. erfolgt beim überwachten Lernen durch „Eingriff” eines externen Mechanismus. also die korrekte Labelung der Dokumente. ■ ■ Wir werden einen Textklassifikator in Python implementieren. Die Aufgabe der Textklassifikation besteht darin. der auf dem naiven BayesKlassifikator basiert. Nicht überwachtes Lernen (automatisches Lernen) erfolgt komplett ohne Einwirkung von außen. Dokumente in Abhängigkeit ihres semantischen Inhaltes einer oder mehreren Kategorien oder Klassen zuzuordnen. . Man unterscheidet eine Lernphase und eine Klassifikationsphase. Naive Bayes ist der am häufigsten benutzte Textklassifikator und steht im Fokus der Forschung. üblicherweise menschliches Feedback. Ein naiver Bayes-Klassifikator geht von der strengen Unabhängigkeit der verwendeten Merkmale aus. Eine „naive” Annahme. Unter halbüberwachtem Lernen (semi-supervised learning) versteht man eine Mischung aus überwachtem und nicht überwachtem Lernen. das Vorhandensein oder die Abwesenheit eines bestimmten Merkmals in einer Klasse steht in keiner Beziehung zum Vorhandensein bzw.

von einer strengen Unabhängigkeit der verwendeten Merkmale auszugehen.. d. den Wert 0.. Die Aufgabe der Textklassifikation besteht nun darin. Beim Naive-Bayes-Klassifikator wird jedes Objekt.d n }. aber dennoch werden häufig mit diesem „naiven” Ansatz ausreichend gute Ergebnisse erzielt.2 Bayes-Theorem Definition unabhängiger Ereignisse: Zwei Ereignisse E und F sind unabhängig. c 2 . jedem Paar (c i . wenn das Dokument d j nicht zur Klasse c i gehört. .3 32. Die wichtigsten sind wohl: ■ Naive Bayes Support Vector Machine Nearest Neighbour ■ ■ 32. wobei 1 ≤ i ≤ m ∧ 1 ≤ j ≤ n ) gilt. Die zugrunde liegende Annahme beim Naive-Bayes-Klassifikator besteht darin. einen Wert 0 oder 1 zuzuordnen. d. zu der es mit der größten Wahrscheinlichkeit gehört.32. nicht beeinflusst und umgekehrt: P (E |F ) = P (E ) und P (F |E ) = P (F ) Die „bedingte Wahrscheinlichkeit” ist die Wahrscheinlichkeit des Eintretens eines Ereignisses A unter der Bedingung.1 Naive-Bayes-Klassifikator Definition Ein Naive-Bayes-Klassifikator ist ein probabilistischer Klassifikator. . Eine Voraussetzung.3. d j ) ∈ C × D . dass das Eintreten eines anderen Ereignisses B bereits bekannt ist. dieses Entscheidungsproblem zu lösen. durch die sich der NBK auszeichnet. Es gibt verschiedene Ansätze. 32.c m } und eine Menge von Dokumenten D = {d 1 . eine Klasse oder Kategorie zugeordnet.h. in unserem Fall jedem Textdokument. die in der praktischen Anwendung des Naive-Bayes-Konzeptes meist nicht gegeben ist. Abwesenheit von allen anderen Merkmalen.3..2 Textklassifikation: Aufgabe 367 32. das Vorhandensein oder die Abwesenheit eines bestimmten Merkmales in einer Klasse steht in keiner Beziehung zum Vorhandensein bzw. und das bei einer schnellen Berechenbarkeit.h. dass F eintritt. der nach dem englischen Mathematiker Thomas Bayes benannt ist.2 Textklassifikation: Aufgabe Gegeben ist eine Menge von Klassen C = {c 1 . d 2 . Er leitet sich aus dem Bayes-Theorem ab. .. Diese Annahme ist mit dem Namensbestandteil „Naive” gemeint. wenn das Auftreten von E die Wahrscheinlichkeit. ansonsten 1.

P (B ) ist die A-priori-Wahrscheinlichkeit für das Ereignis B und P ( A ) ist die A-prioriWahrscheinlichkeit für das Ereignis A .. dass B gilt.368 32 Textklassifikation Für die bedingte Wahrscheinlichkeit gilt: P ( A |B ) = P (A ∩ B ) P (B ) Bayes-Theorem: P ( A |B ) = P (B | A )P ( A ) P (B ) P ( A |B ) bezeichnet die bedingte Wahrscheinlichkeit für ein Ereignis A unter der Bedingung.d n }. Die Wahrscheinlichkeit für ein Wort w t unter der Bedingung. dass er nur eine kleine Trainingsmenge benötigt. wird wie folgt berechnet: P ( w t |c j ) = 1 + Nt |V | cj Cj |V | + s Ns 1 englisch: labelled . dass A gilt. Die Menge D von Dokumenten wird benötigt. P ( A |B ) wird im Zusammenhang mit dem Bayes-Theorem häufig auch als Aposteriori-Wahrscheinlichkeit bezeichnet. Jedes Dokument ist mit einer Klasse etikettiert1 . C Nt bezeichnet die Anzahl der Vorkommen eines Wortes w t in allen Dokumenten einer gegebenen Klasse C. (B | A ) bezeichnet die bedingte Wahrscheinlichkeit für ein Ereignis B unter der Bedingung.4 Formale Herleitung der Naive-Bayes-Klassifikation Gegeben ist eine Menge von Klassen C = {c 1 . ansonsten 0. dass die Klasse c j gegeben ist. .. c 2 . d 2 . P (d i |c j ) ist 1. um die zur Klassifikation notwendigen Parameter einzustellen. Wir bezeichnen die Anzahl der Vorkommen eines Wortes w t in einem Dokument d i mit Ni t . Ein Vorteil des Naive-Bayes-Klassifikators besteht darin. die wahrscheinlichste Klasse für ein unbekanntes Dokument auszuwählen.. falls d i mit c j etikettiert ist. Die Klassifikation besteht darin. um den Klassifikator zu trainieren.c m } und eine Menge von Dokumenten D = {d 1 . 32.. .

Wir ändern dies. die wir zur Klassifikation eines Dokuments benötigen.32. indem wir den Kehrwert berechnen und den Ausdruck als Summe von stabilen Quotienten berechnen: 1 P (c |d ) Dies führt zu folgendem Ausdruck: (1 + Nd1 )(|V | + k c |V | s =1 |V | s =1 1 P (c 1 ) |d | = P (c |d ) P (c ) k =1 c Ns ) +.h. des Lernsets: |D | P (d i |c j ) P (c j ) = i =1 |D | Nun kommen wir zu der Formel. die Wahrscheinlichkeit für eine Klasse c j unter der Bedingung. dass ein Dokument d i gegeben ist: di P (c j ) P (c j |d i ) = k =1 |C | P ( w d i k |c j ) |d i | (P (c r ) r =1 k =1 P (w di k |c r )) Leider ist die vorherige Formel für P (c |d i ) numerisch nicht stabil. weil der Nenner wegen fortschreitender Rundungsfehler Null werden kann.. d.4 Formale Herleitung der Naive-Bayes-Klassifikation 369 Die Wahrscheinlichkeit P (c j ) für eine Klasse c j ist der Quotient aus der Anzahl der Dokumente der Klasse c j und der Anzahl der Dokumente aller Klassen.+ c P (c |C | ) P (c ) |d | k =1 (1 + Nd|C | )(|V | + k c |V | s =1 c Ns ) c c (1 + Nd )(|V | + k Ns 1 ) c (1 + Nd )(|V | + k |V | s =1 N s |C | ) Die folgenden Zwischenschritte haben wir oben ausgelassen: |C | |d | 1 = P (c |d ) (P (c r ) r =1 k =1 |d | P (w k |c r )) P ( w k |c ) P (c ) k =1 |C | |d | (P (c r ) r =1 k =1 1 + N dr |V | c k ) c |V | + s =1 c 1 + Nd |V | k Ns r = P (c ) |d | k =1 |V | + s =1 c Ns .h.. d.

.. words corresponding with their frequency of usages in a "document" for usage by the Document class.+ k |V | + s =1 c 1 + Nd |V | |C | Ns = P (c ) |d | k =1 |d | |d | P (c ) k =1 P (c ) k =1 k |V | + s =1 c Ns |V | + s =1 c Ns |V | + s =1 c Ns 32.__number_of_words = 0 self. Weiterhin werden mit dem Modul re leistungsstarke Tools zur Verfügung gestellt. DocumentClass class and the Pool class. class BagOfWords(object): """ Implementing a bag of words.__bag_of_words. Die Dokumente werden in unserer Implementierung nach dem sogenannten „bag of words”-Modell implementiert.5 Textklassifikation in Python Python ist ideal für die Textklassifikation wegen seiner Stringklasse und deren mächtiger Methoden. die weit über den Rahmen anderer Programmiersprachen hinausgehen.""" def __init__(self): self. Die vorliegende Python-Implementierung eines Naive-Bayes-Klassifikators ist nicht auf Effizienz optimiert. zählt. was wir im folgenden Diagramm illustrieren: 32.370 32 Textklassifikation |d | (P (c 1 ) k =1 1 + N d1 |V | c k |d | ) c (P (c 2 ) k =1 1 + N d2 |V | c k |d | ) c (P (c |C | ) k =1 |C | 1 + Nd k |V | ) |V | + s =1 c 1 + Nd |V | Ns 1 + k |V | + s =1 c 1 + Nd |V | Ns 2 +. das Wörter mit ihren Häufigkeiten enthält bzw.__bag_of_words = {} .5.1 BagOfWords-Klasse Die Klasse BagOfWords verwaltet im Wesentlichen ein Dictionary self.

__bag_of_words: sum[key] += other.word): """ Returning the frequency of a word """ if word in self.word): """ A word is added in the dictionary __bag_of_words""" self.__bag_of_words[key] return erg def add_word(self.keys() def BagOfWords(self): """ Returning the dictionary.__bag_of_words: sum[key] = self.__bag_of_words[key] for key in other.__bag_of_words[word] += 1 else: self.__bag_of_words: if key not in sum: sum[key] = other.__bag_of_words. also eine Klasse im Sinne der Textklassifikation.__bag_of_words) def Words(self): """ Returning a list of the words contained in the object """ return self. .__bag_of_words[key] if key in other.2 Document-Klasse Die Klasse Document wird sowohl für die eigentlichen Textdokumente verwendet als auch als Basisklasse für die DocumentClass.__number_of_words += 1 if word in self.5.__bag_of_words[word] else: return 0 32.32.other): """ Overloading of the "+" operator to join two BagOfWords """ erg = BagOfWords() sum = erg.5 Textklassifikation in Python 371 def __add__(self.__bag_of_words[word] = 1 def len(self): """ Returning the number of different words of an object """ return len(self.__bag_of_words: self.__bag_of_words for key in self. containing the words (keys) with their frequency (values)""" return self.__bag_of_words: return self.__bag_of_words def WordFreq(self.

_words_and_freq._number_of_words = 0 for word in words: self. if a classificator should be trained._vocabulary. that the document is either encoded in utf-8 or in iso-8859. learn=False): """ A document is read._words_and_freq = BagOfWords() Document._words_and_freq. """ def __init__(self.. vocabulary): self.read() text = text. i. (latin-1).read() except UnicodeDecodeError: text = open(filename.text) self._words_and_freq + other. containing the words (keys) with their frequency (values) as contained in the BagOfWords attribute of the document""" return self._words_and_freq = self. _words_and_freq return res def vocabulary_length(self): """ Returning the length of the vocabulary """ return len(Document. It is assumed.._vocabulary = vocabulary def read_document(self.other): """ Overloading the "+" operator._words_and_freq = BagOfWords() """ try: text = open(filename.add_word(word) if learn: Document. self. encoding='utf-8')._vocabulary) res.lower() words = re._vocabulary) def WordsAndFreq(self): """ Returning the dictionary.__document_class = None self.e.split("[^\wäöüÄÖÜß]*"."r". The optional parameter learn has to be set to True. Adding two documents consists in adding the BagOfWords of the Documents """ res = Document(Document. The words of the document are stored in a Bag of Words."r". encoding='latin-1').__name = "" self.filename.BagOfWords() . If it is a test document learn has to be set to False.add_word(word) def __add__(self.372 32 Textklassifikation class Document(object): """ Used both for learning (training) documents and for testing documents.

__init__(self.other): """ Overloading the "+" operator.word): """ returns the probability of the word "word" given the class " self" """ voc_len = Document._number_of_docs = 0 def Probability(self._vocabulary. other): """ Intersection of two documents.word): """ Returning the number of times the word "word" appeared in the document """ bow = self.BagOfWords() return d._vocabulary.5 Textklassifikation in Python 373 def Words(self): """ Returning the words of the Document object """ d = self.WordFreq(word) N = self.BagOfWords() if word in bow: return bow[word] else: return 0 def __and__(self._words_and_freq._words_and_freq. vocabulary): Document.32.3 DocumentClass-Klasse Diese Klasse implementiert die Klassen im Sinne der Textklassifikation.5. class DocumentClass(Document): def __init__(self. vocabulary) self.Words(): if word in words1: intersection += [word] return intersection 32. A list of words occuring in both documents is returned """ intersection = [] words1 = self._words_and_freq.WordFreq(word) erg = 1 + N erg /= voc_len + SumN return erg def __add__(self.keys() def WordFreq(self.len() SumN = 0 for i in range(voc_len): SumN = DocumentClass.Words() for word in other. Adding two DocumentClass objects consists in adding the BagOfWords of the DocumentClass objects """ .

directory.und Klassifikationsmethoden.__document_classes[dclass_name] = x x.__vocabulary) print(directory + "/" + file) d. dclass_name): """ directory is a path.__document_classes[dclass].Words(): WaF = self._number_of_docs 32.SetNumberOfDocs(len(dir)) def Probability(self. learn = True) x = x + d self._vocabulary) res.__vocabulary = BagOfWords() def sum_words_in_class(self._words_and_freq + other._words_and_freq = self. dclass): """ The number of times all different words of a dclass appear in a class """ sum = 0 for word in self. class Pool(object): def __init__(self): self. doc.__vocabulary) dir = os._number_of_docs = number def NumberOfDocuments(self): return self.WordsAndFreq() if word in WaF: sum += WaF[word] return sum def learn(self.listdir(directory) for file in dir: d = Document(self. where the files of the class with the name dclass_name can be found """ x = DocumentClass(self. _words_and_freq return res def SetNumberOfDocs(self. dclass = ""): .__vocabulary.__document_classes = {} self. number): self.374 32 Textklassifikation res = DocumentClass(self. Außerdem befinden sich hier die allgemeinen Lern.read_document(directory + "/" + file.5.4 Pool-Klasse Diese Klasse verwaltet die Dokumentenklassen und das Vokabular.

__document_classes: sum_j = self. learn=False) o = self. intersection_ratio) return res Die obigen Klassen befinden sich in der Datei „NaiveBayes.32.5 Textklassifikation in Python 375 """Calculates the probability for a class dclass given a document doc""" if dclass: sum_dclass = self.__document_classes[dc] & d intersection_ratio = len(o) / len(d. dclass) prob_list.Probability(doc.read_document(doc) for j in self.__document_classes[dclass]. Dabei handelt es sich um verschiedene Klassen mit Witzen: .__vocabulary) d. NumberOfDocuments() / self.WordFreq(i) r = wf * sum_dclass / (wf_dclass * sum_j) prod *= r prob += prod * self.__document_classes: d = Document(self.prob]) prob_list. WordFreq(i) wf = 1 + self.append([dclass.__document_classes: prob = self.__document_classes[dclass ].py” in unserem Beispielverzeichnis.NumberOfDocuments() if prob != 0: return 1 / prob else: return -1 else: prob_list = [] for dclass in self.__document_classes[j].sum_words_in_class(j) prod = 1 for i in d.Words()) res += (dc. doc_name): res = [doc_name] for dc in self. reverse = True) return prob_list def DocumentIntersectionWithClasses(self. Im Beispielverzeichnis befinden sich auch die Verzeichnisse „learn” und „test” mit Lernund Testsets für die folgende Beispielanwendung zur Textklassifikation.__document_classes[j].Words(): wf_dclass = 1 + self.read_document(doc_name.sum_words_in_class(dclass) prob = 0 d = Document(self.sort(key = lambda x: x[1].__vocabulary) d.

0. "math". ['sex'.914992628977959e-10]. und dann folgen die Klassifikationsergebnisse: .674688944524231e-10].txt: [['clinton'. 1. 7. Pool "lawyer". 2. "medical". 5.txt learn/clinton/clinton25.4074110973205754e-12].txt learn/clinton/clinton10. 5. ['music'. ['music'. 1.txt: [['clinton'.Probability(base + i + "/" + file) print(i + ": " + file + ": " + str(res)) Startet man das Programm. 2.1459928139047106e-12]. erhält man das folgende Ergebnis: bernd@saturn:~/bodenseo/python/beispiele$ python3 NaiveBayes_test. 1.txt learn/clinton/clinton1. 1. 0.listdir(base + i) for file in dir: res = p. ['math'.2295982769832164e-09]. ['lawyer'.520351011801854e-10].72601686083638e-12]. i) base = "learn/" for i in DClasses: dir = os.9999999994344095]. ['sex'.3811580908948818e-29].txt: [['clinton'. ['medical'. "music". 5.441826815920904e-07].txt learn/clinton/clinton15.py | head learn/clinton/clinton20.txt learn/clinton/clinton69. ['lawyer'. 2.txt learn/clinton/clinton14. ['lawyer'...txt: [['clinton'. 0.9999999992386299]. 6. ['sex'. ['music'.txt learn/clinton/clinton56.901960867214498e -22].txt learn/clinton/clinton34. ['lawyer'. 2. clinton: clinton20. ['music'.9999997364637545]. . ['medical'. 3.592331193036529e -29].. 6. 1. 9.760021719870858e-13]] clinton: clinton36.1520143389502419e-11]] clinton: clinton56.txt .68058228879274e-28]. 2. ['math'. ['sex'.648015266828207e-11].948648939490094e -35]] clinton: clinton15.learn(base + i. ['medical'. ['math'..7744976589393507e-08].0].376 32 Textklassifikation from NaiveBayes import import os DClasses = ["clinton". "sex"] base = "learn/" p = Pool() for i in DClasses: p.txt learn/clinton/clinton36.

914323838547423e-42]. 4. 7. 1.6849007485121964e-51]] clinton: clinton14.6481471984787215e -32]. 4. 3.071780957518354e-44].5179052741540378e-12]. ['music'. ['medical'. 0.7595454063410785e-14]. 1..966110616318117e -39]. 7.1389115763215046e-15].0].215593474577993e-20].4206270940103888e-18]. ['lawyer'.514449565885636e-19].txt: [['clinton'.txt: [['clinton'. ['sex'. ['music'. ['math'. 3.486402118341457e-18].2215177549148766e -45]. ['sex'. ['sex'. 1.0]. 1.0839574950384394e-13]] clinton: clinton10. 5. 1. 1. 1. 1. ['math'. ['math'. ['math'. ['medical'. ['sex'. 0.1549302112730125e-17]] . 1. ['music'. 0. ['music'. ['medical '.txt: [['clinton'.990905914149136e -42]. 4.4639896765847644e-42]. ['sex'. 3.7642685540607824e-12]. ['medical'. 4.9999999998207063].112918004222222e -46]] clinton: clinton69. 1.419633484697798e-19].502049137268664e-14]. 5.9999999999999882]. 1.595073346783043e-21]] clinton: clinton25. ['medical'. 4. ['lawyer'.752336117034771e-15].0029914377606443e-45]. 4. ['lawyer'.1795522781235521e-14]. ['music'. ['lawyer'.5 Textklassifikation in Python 377 1. . 1. ['math'. 1. ['lawyer'. ['medical'.613944672153929e-19]] clinton: clinton1.7923166491945231e-10]. ['math'. 1..64894907605748e-17]. 2.9999999999999825]. 1.32.txt: [['clinton'.txt: [['clinton'.

dann spricht man das erste Element mit liste[0] an. dass l eine Variable vom Typ list ist. Aufgabe ■ ■ Lösungen zu den Aufgaben Lösungen zu Kapitel 5 (Sequentielle Datentypen) Wir haben die folgenden Datentypen kennengelernt: str: Zeichenketten. dann können wir das letzte Element am einfachsten mit l[-1] ansprechen. Aufgabe Nehmen wir an.33 33.79] >>> liste[0] 45 >>> 3. Beispiel: >>> liste = [45.1 1. meistens als Strings bezeichnet : list: Listen tuple: Tupel bytes und bytearry: Binärdaten ■ ■ 2.87. . Aufgabe Wenn die Variable „liste” eine Liste bezeichnet.

aber weniger elegant als obige Lösung."787". "Welt". sodass wir oben versucht hatten. line 1.9) s = "Ich bin ein String" l = [45. in <module> TypeError: 'str' object does not support item assignment Strings sind unveränderlich.8. in <module> IndexError: tuple index out of range Der höchste Index des Tupels entspricht 2. line 1. d.[45. und erhielten daher die Meldung „IndexError: tuple index out of range” >>> t(3) Traceback (most recent call last): File "<stdin>". "Das letzte Element"] >>> l[-1] 'Das letzte Element' >>> l[len(l) . ist dies auch korrekt.1] als Lösung gefunden hatten.h.380 33 Lösungen zu den Aufgaben Falls Sie l[len(l) .4]] t2 = (4. Daher die Fehlermeldung „TypeError: ’tuple’ object is not callable”.[3. da es keine Funktion.7. line 1.1] 'Das letzte Element' >>> 4.98]) >>> t[0] 4 >>> t[3] Traceback (most recent call last): File "<stdin>". Mit runden Klammern wird auf Funktionen zugegriffen. Aufgabe >>> >>> >>> >>> t = (4. Beispiel: >>> l = ["Hallo". >>> l[2][0] = "g" Traceback (most recent call last): File "<stdin>". in <module> TypeError: 'str' object does not support item assignment . auf einen nicht existierenden Index zuzugreifen. >>> s[4] 'b' >>> s[4] = "x" Traceback (most recent call last): File "<stdin>". line 1. t ist „nicht aufrufbar (not callable). in <module> TypeError: 'tuple' object is not callable Zugriffe auf Tupel oder Listen benötigen eckige Klammern.98. sondern ein Tupel ist.

98." save as":"Save as"."open":"Open". >>> s = "Der ist der beste Lehrer.u rd eSre lsbiscthh inlafceh iumnmde rn aucnhs eürbee rofbleürssstieg Mmaaxcihmte. 4]] >>> t2[2][0] = 42 5. der sich nach und nach überflüssig macht. Um das Folgende zu verstehen.' >>> s[1::2] 'In dem Sinne ist Hilfe zur Selbsthilfe immer unsere oberste Maxime.join(["".2 Lösungen zu Kapitel 6 (Dictionaries) 381 Wir haben wieder versucht.join(x) for x in zip(s. wenn man einmal mit dem Index 0 und einmal mit dem Index 1 beginnt: >>> s = 'DIenr diesmt Sdienrn eb eisstte HLielhfree rz." >>> s = "".' >>> Vielleicht interessiert es Sie auch. müssen Sie allerdings das Kapitel 26 (Listen-Abstraktion/List Comprehension) bereits bearbeitet haben.2 1. >>> l[3][0] = "g" >>> l [45." >>> t = "In dem Sinne ist Hilfe zur Selbsthilfe immer unsere oberste Maxime. "print":"Print". der sich nach und nach überflüssig macht. Aufgabe Lösungen zu Kapitel 6 (Dictionaries) menu = {"en" : {"file":"File". kann man die beiden verborgenen Sätze extrahieren. .u rd eSre lsbiscthh inlafceh iumnmde rn aucnhs eürbee rofbleürssstieg Mmaaxcihmte. "save":"Save". einen String zu verändern. "print preview":"Print Preview". ['g'. "close":"Close". wie wir den String erzeugt hatten. "new":"New".t)]) >>> s 'DIenr diesmt Sdienrn eb eisstte HLielhfree rz. Aufgabe Stellt man die Schrittweite des Sclicing-Operators auf step = 2. "exit":"Exit"}.' >>> s[::2] 'Der ist der beste Lehrer.33..' >>> 33. '787'..

2) ("g". ("Bauer". "weiss")."open":"Ouvrir". "weiss").7) : : : : : : : : : : : : : : : : : : : : : ("Turm". ("Springer". ("Bauer". ("Turm". "weiss"). 'exit': 'Esci'. ("Bauer".2) ("f".2) ("h". ("Läufer". "weiss").1) ("f". ("Bauer"."save as":"Salva come". ("Dame". "close":"Schließen".1) ("e".3) ("d".6) ("d". 'save as': ' Salva come'. "schwarz").2) ("e". "schwarz"). "exit":"Esci"} } language = input("Which language? ") current_dic = menu[language] print(current_dic) Ein Aufruf des obigen Programms liefert beispielsweise folgende Ausgaben: $ python3 nested_dictionaries."open":"Apri". ("Läufer". "exit":"Quitter"}. "print preview ":"Apercu avant impressioner". ("Läufer". 'close': 'Chiudi'.2) ("c". 'open': 'Apri'} 2.3) ("f".6) ("d". "weiss")."open":"Öffnen". "new":"Neu". ("König". "weiss"). "schwarz"). ' new': 'Nuovo'. ("Bauer". "print":"Stampa". "weiss"). "schwarz").6) ("h".6) ("a".2) ("b"."save as":"Enregistrer sous".2) ("c". "weiss"). "weiss"). "weiss"). "weiss"). "print":"Imprimer". "weiss"). "save":"Salva ". ("Bauer". "new":"Nouveau". "save":" Speichern"."save as":"Speichern unter".4) ("h". "de" : {"file":"Datei". "print":"Drucken". ("Springer". 'save': 'Salva'. "print preview":"Anteprima di stampa". ("Bauer". 'print': 'Stampa'. ("Bauer". .1) ("h". "schwarz"). "print preview":" Druckansicht".382 33 Lösungen zu den Aufgaben "fr" : {"file":"Fichier". Aufgabe board = { ("a". "weiss"). "close":" Fermer". "weiss").1) ("a". ("Bauer". "weiss"). 'file': 'File'. "close":"Chiudi". ("Bauer". "it" : {"file":"File". ("Bauer". "exit ":"Verlassen"}. "new":"Nuovo".1) ("d". ("Bauer". "save ":"Enregistrer".py Which language? it {'print preview': 'Anteprima di stampa'. "weiss").4) ("c".

("Bauer". 'schwarz') 33. "ist ein Schaltjahr") else: print(jahr.8) ("h".33.8) ("d". Aufgabe Lösungen zu Kapitel 8 (Verzweigungen) #!/usr/bin/python3 jahr = int(input("Jahreszahl: ")) if jahr % 4 == 0: if jahr % 100 == 0: if jahr % 400 == 0: schaltjahr = True else: schaltjahr = False else: schaltjahr = True else: schaltjahr = False if schaltjahr: print(jahr. "schwarz").7) ("e". "schwarz"). ("Bauer".py ('Springer'. "schwarz").3 Lösungen zu Kapitel 8 (Verzweigungen) 383 ("b". ("Dame". "ist kein Schaltjahr") Alternativ zu obiger Lösung kann man die Aufgabe auch wie folgt lösen.8) ("g". erhält man folgende Ausgabe: $ python3 chess. "schwarz"). "schwarz"). "schwarz") print(board[("g".8) ("f". "schwarz"). In diesem Fall müssen wir die Variable schaltjahr auf False vorbesetzen: .7) ("g".8)]) Ruft man das Programm auf. ("Springer".8) ("e".3 1. ("Bauer". ("Läufer". "schwarz"). "schwarz"). "schwarz").8) } : : : : : : : : : : : ("Bauer". ("Turm". ("König". "schwarz").7) ("d".7) ("f". ("Turm". ("Springer".7) ("a".

"ist kein Schaltjahr") 2. Aufgabe hours = int(input("hours: ")) minutes = int(input("minutes: ")) seconds = int(input("seconds: ")) if seconds == 59: seconds = 0 if minutes == 59: minutes = 0 if hours == 23: hours = 0 else: hours += 1 else: minutes += 1 else: seconds += 1 # Wandlung in Strings hours = str(hours) if len(hours) < 2: hours = "0" + hours minutes = str(minutes) if len(minutes) < 2: minutes = "0" + minutes seconds = str(seconds) if len(seconds) < 2: seconds = "0" + seconds print("New time: " + hours + ":" + minutes + ":" + seconds) . "ist ein Schaltjahr") else: print(jahr.384 33 Lösungen zu den Aufgaben #!/usr/bin/python3 jahr = int(input("Jahreszahl: ")) schaltjahr = False if jahr % 4 == 0: schaltjahr = True if jahr % 100 == 0: schaltjahr = False if jahr % 400 == 0: schaltjahr = True if schaltjahr: print(jahr.

roman_number = input("Bitte römische Zahl eingeben: ") . Aufgabe Lösungen zu Kapitel 9 (Schleifen) Haben Sie die den römischen Zahlen zugrunde liegenden Regeln erkannt? Die Regeln: 1.4 1. Stehen gleiche Zahlen nebeneinander.10.seconds)) 33.format(hours. Es dürfen höchstens drei Grundzahlen nebeneinander stehen. Ausnahme „M”. werden sie addiert. Allerdings möchten wir Ihnen die elegantere Lösung nicht vorenthalten: hours = int(input("hours: ")) minutes = int(input("minutes: ")) seconds = int(input("seconds: ")) if seconds == 59: seconds = 0 if minutes == 59: minutes = 0 if hours == 23: hours = 0 else: hours += 1 else: minutes += 1 else: seconds += 1 print("New time: {0:02d}:{1:02d}:{2:02d}". 4. Beispiele: III = 3 oder XX = 20 2.minutes. Beispiele: IV entspricht 5 . Steht eine Zahl mit einem kleineren Wert neben einer Zahl mit einem größeren Wert. und zum anderen wird die ifAnweisung bei der Wandlung weiter vertieft. 3. so wird der kleinere Wert vom größeren subtrahiert.1 also 4 oder XL entspricht 50 . Die obige Lösung hat zum einen den Vorteil. Die Grundzahlen I.33. X und C dürfen nur von der nächsthöheren Zahl (Zahlzeichen) subtrahiert werden.4 Lösungen zu Kapitel 9 (Schleifen) 385 Mit Hilfe einer formatierten Ausgabe kann man das Hinzufügen von Nullen bei einstelligen Werten einfacher realisieren. dass sie keinen Vorgriff auf noch nicht behandelte Themen macht.

'X': 10. 'L': 50. 'C': 100. Aufgabe Es gibt natürlich viele Wege.py | more 0. 'M': 1000 } previous_value = 0 for char in roman_number: if char in roman_digits: if roman_digits[char] > previous_value: decimal -= previous_value else: decimal += previous_value previous_value = roman_digits[char] decimal += previous_value print("Ergebnis: " + str(decimal)) Ein Aufruf des Programms sieht so aus: $ python3 roman2decimal.py Bitte römische Zahl eingeben: MCDXLVIII Ergebnis: 1448 2. Wir haben uns für eine Lösung entschieden. 'D': 500.0001 i = 1 while sum .5 1 . sum) Die Ausgabe dieses Programms liefert uns folgende Werte: $ python3 frog. diese Aufgabe zu lösen. 'V': 5.386 33 Lösungen zu den Aufgaben decimal = 0 roman_digits = { 'I': 1. Man hätte auch eine for-Schleife wählen können. bei der wir eine while-Schleife beenden.old_sum > eps: old_sum = sum sum += i i = i / 2 print(i. sobald die zurückgelegte Entfernung kleiner als eine Schranke eps ist: sum = 0 old_sum = -1 eps = 0.

103515625e-05 1. die 2.999755859375 6.0001220703125 1. .0009765625 1. erhält man die in der Aufgabenstellung angegebene Anzahl von Weizenkörnern: $ python3 weizenkorn.99951171875 0.015625 1.9990234375 0.00048828125 1. die natürlich viel Rechenzeit benötigt.001953125 1. Wir können diese Exponentiation durch eine Summe ersetzen.03125 1. .5 m breite Straße zu überqueren.125 1.0078125 1.33. die die Menge der Weizenkörner pro Schritt beinhaltet: koerner = 0 zuwachs = 1 for i in range(64): koerner += zuwachs . n −1 5 4 8 2 3. indem wir eine zusätzliche Variable „zuwachs” einführen.25 1.4 Lösungen zu Kapitel 9 (Schleifen) 387 0.0625 1.75 0.00390625 1. dass der Frosch mit seiner Sprungweise nicht mehr als 2 Meter zurücklegen wird.9921875 0.99993896484375 Aus den numerischen Werten liegt es nahe zu folgern.5 0.9375 0.py 18446744073709551615 In obiger Lösung haben wir in jedem Schritt der Schleife eine Exponentiation.96875 0. Aufgabe Eine Lösung sieht wie folgt aus: koerner = 0 for i in range(64): koerner += 2 ** i print(koerner) Startet man dieses Programm.875 0.99609375 0. Damit schafft er es also nicht.998046875 0.000244140625 1.0517578125e-05 1.984375 0. Übrigens kann man auch den n-ten Summenwert der folgenden Reihe entnehmen: 1+ 2n − 1 3 7 15 + + + .9998779296875 3.

haben wir uns ja bewusst unwissend gestellt. Um diese Aufgabe zu lösen. fobj_in = open("namen. wenn wir uns in einer Zeile mit einem Vornamen befinden. Aufgabe Lösungen zu Kapitel 10 (Dateien lesen und schreiben) Die Variable output ist ein leerer String. Die Anzahl der Körner auf n Feldern berechnet sich als: n i =0 2i = 2n +1 − 1 Damit brauchen wir für die Lösung der Aufgabe nur noch die interaktive Python-Shell: >>> 2 ** 64 -1 18446744073709551615 >>> Für die mathematisch Interessierten: Allgemein gilt für die Summe von Potenzen mit konstanter Basis k und steigendem Exponenten: n i =0 ki = k n +1 − 1 k −1 33.txt".rstrip() + "\n" fobj_out.close() fobj_out. "w") output = "" for line in fobj_in: if output: output += " " + line.5 1. Befinden wir uns in einer Zeile mit einem Nachnamen.rstrip() fobj_in.close() .txt") fobj_out = open("namen2. enthält die Variable output den zugehörigen Vornamen.write(output) output = "" else: output = line. Für dieses Problem gibt es schließlich eine Formel. dann machen wir es gleich richtig schnell.388 33 Lösungen zu den Aufgaben zuwachs += zuwachs print(koerner) Aber wenn wir nun schon am „schneller machen” sind.

denn in diesem Fall kann noch nichts ausgegeben werden.rstrip() if counter % 3 == 0: if counter: fh_out.txt") counter = 0 new_line = "" for line in fh: line = line.txt".close() 3. Die einzige Ausnahme stellt die Zeilennummer 0 dar. Aufgabe fh_in = open("musicians.33.close() fh_in.txt") fh_out = open("musicians2. fh = open("musicians.write(new_line + "\n") new_line = line elif counter % 3 == 1: new_line += " " + line else: new_line += " (" + line + ")" counter += 1 fh_out. Immer wenn eine Zeilennummer durch drei teilbar ist.5 Lösungen zu Kapitel 10 (Dateien lesen und schreiben) 389 2. Aufgabe Die Variable „counter” dient dazu die aktuelle Zeilennummer aufzunehmen. "w") counter = 0 new_line = "" for line in fh_in: line = line.rstrip() if counter % 3 == 0: if counter: print(new_line) _ new line = line elif counter % 3 == 1: new_line += " " + line else: new_line += " (" + line + ")" counter += 1 fh.close() . geben wir den Inhalt der vorhergehenden drei Zeilen aus.

390 33 Lösungen zu den Aufgaben 33.(2. Aufgabe def flatten(x): """flatten(sequence) -> list""" result = [] for el in x: #if isinstance(el. sie leert die Eingabeliste.3. 1."d"] liste = rev(liste) print liste 2.2] on linux2 Type "help". 'auch'. "credits" or "license" for more information."b".extend(flatten(el)) else: result. ["noch tiefer". 3.h. tuple)): if (type(el) == list) or (type(el) == tuple): result.1.3.(2.7. Oct 19 2012."c". 'noch tiefer'. Aufgabe Lösungen zu Kapitel 11 (Listen und Tupel im Detail) Die folgende Funktion „rev” kehrt die Reihenfolge einer Liste um. >>> from flatten import flatten >>> liste = [["test". "auch"]].3 (default. def rev(lst): revl = [] while lst: el = lst.4))] print(flatten(liste)) Obige Funktion testen wir in der Python-Shell: bernd@saturn:~/bodenseo/python/beispiele$ python3 Python 3.(2. ["noch tiefer".2. "copyright". "auch"]].4))] >>> flatten(liste) ['test'.6 1. 19:53:57) [GCC 4.(2.pop() revl. 4] >>> . d. 2.(list. 2.append(el) return result liste = [["test". Die Funktion ist „destruktiv”.append(el) return revl liste = ["a".1.

2404). 12196). ('m'. 30481). ('s'. 18. 4. 1343). 50. ('z'. 27. ('h'.reverse=True) return f txt = letter_frequency(open("ulysses.sort(key = lambda x: x[1]. 92704). 22879). 'Baker'. 70986). ('u'. 21413). 'James'. 'Turner'. 10. ('y'. ('d'. 143221). key = str) [1. ('f'. 46. ('Henry'.99). 53.items()) f. 31891).75). 1464). ('j'. 82494). 48.lower(): if char in relevant_letters: if char in frequency_dict: frequency_dict[char] += 1 else: frequency_dict[char] = 1 f = list(frequency_dict. ('w'. ('Andrea'.py [('e'. ('l'. 'Miller'. 40. 73053). 22. 9865). ('Eve'. ('g'. 'Baker'.67). 41] 4. 31.31. ('x'.2. 101654). 31. ('Randy'. ('c'. 23. 1079)] bernd@saturn:~/bodenseo/python/beispiele$ 5.1. 77656). 94103). 44. 27016). 33. 55522). ('v'. ('t'.23). 28189) .33. ('r'. Aufgabe >>> l = [3. 26424). Weiter unten finden Sie eine Lösung ohne lambda: umsaetze = [ ('John'. ('i'.56)] . 24571).10.6 Lösungen zu Kapitel 11 (Listen und Tupel im Detail) 391 3. ('o'.22] >>> sorted(l. ('Tina'. 81133). 'Steiner'.4.read()) print(txt) Started man dieses Programm erhält man die Buchstabenhäufigkeiten des Romans Ulysses von James Joyce: bernd@saturn:~/bodenseo/python/beispiele$ python3 letter_frequency. 2. ('b'. 27. ('q'.41. ('n'. 18. Aufgabe Wir geben zuerst die elegantere Lösung mit der lambda-Notation. ('k'. ('p'.33. 49609). 33767). ('a'. 3.99). Aufgabe def letter_frequency(line): relevant_letters = "abcdefghijklmnopqrstuvwxyz" frequency_dict = {} for char in line.txt").

'Baker'. 46. 31.392 33 Lösungen zu den Aufgaben print("Sortiert nach Verkaufserlös:") for i in sorted(umsaetze. Wir müssen deshalb explizit zwei Funktionen definieren. 'Baker'.99). 18.99) bernd@venus:~/bodenseo/python/beispiele$ Das folgende Programm stellt eine Lösung ohne die Verwendung von lambda dar. ('Tina'. ('Henry'. ('Randy'. key=gesamtpreis): print(i) print("\nSortiert nach Nachname und Vorname:") .py”. 18. 50. key=lambda x: x[1] + x[0]): print(i) Speichern wir das obige Programm unter „umsaetze. 18. 'Baker'. 31.99) ('John'. 27. 'Turner'. 'James'. 'Turner'. 48.56) ('Andrea'. Sie finden auch diese Lösung in unserem Beispielverzeichnis unter dem Namen „umsaetze2.67) ('Henry'.67) ('Randy'.23) Sortiert nach Nachname und Vorname: ('Andrea'. 23. 40. 40. key=lambda x: x[2] * x[3]): print(i) print("\nSortiert nach Nachname und Vorname:") for i in sorted(umsaetze.56)] def gesamtpreis(x): return x[2] * x[3] def name(x): return x[1] + x[0] print("Sortiert nach Verkaufserlös:") for i in sorted(umsaetze. ('Eve'. 31. 27. 53. 'James'.75) ('Randy'. 53.56) ('John'. 'Baker'. 'James'. 46.99). 27. erhalten wir folgende Ausgaben beim Start: bernd@venus:~/bodenseo/python/beispiele$ python3 umsaetze. 44.23). 48. 50. 'Turner'. 23. 18. 18.py”: umsaetze = [ ('John'. 53.75) ('Tina'. 23. 'Miller'. 'Steiner'.99) ('Tina'. 46. 27. 50. ('Andrea'.99) ('Eve'. 48.py Sortiert nach Verkaufserlös: ('Eve'. 27. 'Baker'. 18. 44. 27. 'Baker'. 'Miller'.23) ('Henry'. 40. 'Miller'.67).75). 44. 'Steiner'. 'Steiner'.

33.10): print(mult3(i)) 2. Aufgabe def sum_n(n): if n== 0: return 0 else: return n + sum_n(n-1) 3. key=name): print(i) 33. f(n+1) = f(n) + 3 Die Funktion in Python: def mult3(n): if n == 1: return 3 else: return mult3(n-1) + 3 for i in range(1.7 Lösungen zu Kapitel 15 (Rekursive Funktionen) 393 for i in sorted(umsaetze.append(previous_line[i] + previous_line[i+1]) .7 1. Aufgabe def pascal(n): if n == 1: return [1] else: line = [1] previous_line = pascal(n-1) for i in range(len(previous_line)-1): line. Aufgabe Lösungen zu Kapitel 15 (Rekursive Funktionen) Mathematisch können wir es wie folgt formulieren: f(1) = 3.

fib_sum) = fib_pascal(n-1. fib_sum) def fib(n): return fib_pascal(n.0)[1] # and now printing out the first ten Fibonacci numbers: for i in range(1. Aufgabe def fib_pascal(n.append(1) return line print(pascal(6)) 4.10): print(fib(i)) 5. Aufgabe Iterative-Lösung für das Sieb des Eratosthenes für die ersten 100 Zahlen: from math import sqrt def sieve(n): .append(previous_line[i] + previous_line[i+1]) line += [1] if fib_pos < len(line): fib_sum += line[fib_pos] return (line.insert(0.394 33 Lösungen zu den Aufgaben line += [1] return line print(pascal(6)) Alternativ können wir eine Lösung mit List Comprehension schreiben: def pascal(n): if n == 1: return [1] else: p_line = pascal(n-1) line = [ p_line[i]+p_line[i+1] for i in range(len(p_line)-1)] line.fib_pos): if n == 1: line = [1] fib_sum = 1 if fib_pos == 0 else 0 else: line = [1] (previous_line. fib_pos+1) for i in range(len(previous_line)-1): line.1) line.

Aufgabe memo = {0:0.n+1)) max = sqrt(n) num = 2 while num < max: i = num while i <= n: i += num if i in primes: primes. n) if x not in no_p] return p print(primes(100)) 6. i)] p = [x for x in range(2. n.33. empfehlen wir unser Kapitel über Listen-Abstraktion (List Comprehension) zu Rate zu ziehen: from math import sqrt def primes(n): if n == 0: return [] elif n == 1: return [1] else: p = primes(int(sqrt(n))) no_p = [j for i in p for j in range(i*2. 1:1} def fib(n): if not n in memo: memo[n] = fib(n-1) + fib(n-2) return memo[n] def find_index(*x): """ finds the natural number i with fib(i) = n """ if len(x) == 1: # started by user .remove(i) for j in primes: if j > num: num = j break return primes print(sieve(100)) In diesem Kapitel geht es jedoch um rekursive Funktionen und in der Aufgabenstellung haben wir auch bei der Berechnung der Primzahlen Rekursion verlangt.7 Lösungen zu Kapitel 15 (Rekursive Funktionen) 395 # returns all primes between 2 and n primes = list(range(2. Um die folgende Lösung besser verstehen zu können.

0) else: n = fib(x[1]) m = x[0] if n > m: return -1 elif n == m: return x[1] else: return find_index(m. fib(i). find_index(square))) Die Ausgabe für das vorige Skript sieht wie folgt aus: index of a | a | b | sum of squares | index ===================================================== 0 | 0 | 1 | 1 | 1 1 | 1 | 1 | 2 | 3 2 | 1 | 2 | 5 | 5 3 | 2 | 3 | 13 | 7 4 | 3 | 5 | 34 | 9 5 | 5 | 8 | 89 | 11 6 | 8 | 13 | 233 | 13 7 | 13 | 21 | 610 | 15 8 | 21 | 34 | 1597 | 17 9 | 34 | 55 | 4181 | 19 10 | 55 | 89 | 10946 | 21 11 | 89 | 144 | 28657 | 23 12 | 144 | 233 | 75025 | 25 13 | 233 | 377 | 196418 | 27 14 | 377 | 610 | 514229 | 29 .396 33 Lösungen zu den Aufgaben # find index starting from 0 return find_index(x[0]. square. Aufgabe # code from the previous example with the functions fib() and find_index () print(" index of a | a | b | sum of squares | index ") print("=====================================================") for i in range(15): square = fib(i)**2 + fib(i+1)**2 print( " %10d | %3d | %3d | %14d | %5d " % (i. fib(i+1).x[1]+1) 7.

py Meyer Frank. ) 397 33. 07531/70021 Huber Ottmar. firstname. . 07732/43452 Rabe Peter. . encoding="iso-8859-1") for address in fh: address = address. " + city + ".rsplit(". Radolfzell. Aufgabe Lösungen zu Kapitel 17 (Alles über Strings . Rosenheim. Konstanz. ) Die Lösung besteht darin. 08031/7877-0 Rabe Anna. encoding="iso-8859-1") l = [] for address in fh: address = address.txt". address. Radolfzell. dass man zweistufig split anwendet: fh = open("addresses. dass wir einmal ein normales splitt mit maxsize = 1 und ein rsplit mit maxsize = 1 aufrufen: fh = open("addresses.8 1.33. Aufgabe Die Lösung besteht darin. Konstanz. 08031/787878 Rabe Sarah. 089/3434544 Huber Franziska. city.1)[0].append(t) print(l) Alternativ kann man auch ein split ohne maxsize verwenden und dann auf den ersten und letzten Index zugreifen: fh = open("addresses. 07531/343454 bernd@saturn:~/bodenseo/python/beispiele$ 2.8 Lösungen zu Kapitel 17 (Alles über Strings .py”: bernd@saturn:~/bodenseo/python/beispiele$ python3 split_addresses_mixed. encoding="iso-8859-1") . " + phone) Die Ausgabe des Programms „split_addresses_mixed. phone) = address. München.') print(firstname + " " + lastname + ".split('. 07732/2343 Lindner Oskar.'.txt".1)[1]) l. 07531/890 List Anna. . Rosenheim. München. 089/3434544 List Anna.txt".strip() (lastname.strip() t = (address.split('. .". Konstanz.

') l. start+1) if start == -1: return -1 num += 1 return start if __name__ == "__main__": s = "abc xyz abc xyz abc xyz" print(findnth(s. Aufgabe def findnth(str. n): num = 0 start = -1 while num < n: start = str. "xyz".\n' >>> print(s) Hat der alte Hexenmeister Sich doch einmal wegbegeben! Und nun sollen seine Geister Auch nach meinem Willen leben. "xyz". 'Sich doch einmal wegbegeben!'.splitlines()) + "\n" >>> s 'Hat der alte Hexenmeister\nSich doch einmal wegbegeben!\nUnd nun sollen seine Geister\nAuch nach meinem Willen leben.append((t[0]. substr.'] >>> s = "\n".\n""" >>> s.split('. Aufgabe >>> s = """Hat der alte Hexenmeister\nSich doch einmal wegbegeben!\r\nUnd nun sollen seine Geister\rAuch nach meinem Willen leben. 3)) Dieses Programm befindet sich in unserem Beispielverzeichnis unter „findnth.398 33 Lösungen zu den Aufgaben l = [] for address in fh: address = address. Startet man das Programm erhält man folgende Ausgaben: . t[-1])) print(l) 3.py”.join(s.find(substr. 'Und nun sollen seine Geister'. >>> 4.splitlines() ['Hat der alte Hexenmeister'. 1)) print(findnth(s.strip() t = address. 'Auch nach meinem Willen leben.

33. die wir im vorigen Beispiel erstellt hatten.8 Lösungen zu Kapitel 17 (Alles über Strings ."yes". ) 399 bernd@saturn:~/bodenseo/python/beispiele$ python3 findnth. "credits" or "license" for more information.2.py 4 20 bernd@saturn:~/bodenseo/python/beispiele$ 5. . n): pos = findnth(source. 19:53:57) [GCC 4."no". Oct 19 2012.1) 'And no he said yes!' >>> . . "copyright". n) if pos == -1: return source return source[:pos] + replacement + source[pos+len(search):] Beispiel für die Anwendung der Funktion „replacenth”: bernd@saturn:~/bodenseo/python/beispiele$ python3 Python 3. Für die eigentliche Ersetzung brauchen wir dann lediglich Slicing und die Konkatenation von Strings: def findnth(str."no". replacement.7."yes". n): num = 0 start = -1 while num < n: start = str. search. substr.2] on linux2 Type "help". >>> from replacenth import replacenth >>> replacenth("And yes he said yes!". Aufgabe Für die Funktion „replacenth” benutzen wir die Funktion „findnth”. search. start+1) if start == -1: return -1 num += 1 return start def replacenth(source. um die Position des n-ten Vorkommens zu ermitteln.2) 'And yes he said no!' >>> replacenth("And yes he said yes!".3 (default.find(substr.

name="marvin"): self. 4]) >>> """ Roboterklasse zur Positionsbeschreibung und Veränderung von Objekten in einem zweidimensionalen Koordinatensystem. dann erhält man beispielsweise die folgenden Ausgaben: >>> x <robot.position. aber __repr__ definiert. als print(x) für ein Objekt x der Klasse Robot ruft __str__ auf. Sowohl mit der Methode __str__ als auch mit der Methode __repr__ wird ein Objekt der Klasse in eine Stringdarstellung gewandelt. 4]) >>> print(x) (Marvin.400 33 Lösungen zu den Aufgaben 33.9 1. orientation = "north". Tippt man hingegen nur x in der interaktiven Shell ein. north. Aufgabe Lösungen zu Kapitel 19 (Objektorientierte Programmierung) Ein Objekt der Klasse „robot” wird von den Attributen self. x=0. „south” und „west” gerichtet sein. Die Koordinate wird in Form einer Zweierliste gespeichert. """ class Robot(object): def __init__(self. Ist nur die Methode __str__ aer nicht __repr__ definiert. self. [3.orientation = orientation . wenn man die Methode move auf ihn anwendet. [3. wird __repr__ aufgerufen.Robot object at 0xb71bfcac> >>> print(x) marvin faces north at position [3.name Alle Dinge sollten einen Namen haben. north. y=0.position = [x.orientation und self. in die er sich bewegt. self.position enthält die Position eines Roboters in einem zweidimensionalen Koordinatensystem.orientation Ein Roboter kann in eine der vier Richtungen „north”. 4] >>> Ist hingegen die Methode __str__ nicht definiert. Ansonsten ist dieses Attribut natürlich nicht von besonderer Wichtigkeit für unsere Klasse. self.name definiert: self.y] self. dann wird in beiden Fällen __repr__ zur Ausgabe verwendet: >>> x (Marvin. „east”. Das ist dann auch die Richtung. String verändert aber gewissermaßen das interne „Aussehen” eines Objektes und wird beispielsweise aufgerufen von print. so auch unsere robot-Objekte.

""" if self.33.name = name def __str__(self): """ Stringdarstellung einer Instanz """ s = self. also x."west".orientation s += ".position[1] -= distance elif self.9 Lösungen zu Kapitel 19 (Objektorientierte Programmierung) 401 self."south".getPosition() == .orientation == "south": self."west".position[1] += distance elif self. " + str(self. o has to be in {"north". dann bewegt er sich 10 Felder östlich und befindet sich anschließend in Position [3.. also eine der Richtungen .orientation s += " at position " + str(self.move(10) aufgerufen und ist dieser Roboter östlich orientiert.position[0] -= distance elif self. distance): """ Methode zum Bewegen eines Roboters in Richtung seiner aktuellen Orientierung.name + " faces " + self.getOrientation() für einen Roboter x liefert dessen aktuelle Orientierung zurück.orientation == "north": self.orientation = o def getOrientation(self): """ Ein Aufruf von x.orientation == "west": self.position) return s def __repr__(self): """ Allgemeine Darstellung einer Instanz """ s = "(" + self.east'' und ist beispielsweise [3.position) + ")" return s def move(self.orientation == "east": self.7] die aktuelle Position des Roboters. o): """ Mit der Methode newOrientation ändern wir die Orientierung des Roboters.position[0] -= distance def newOrientation(self.17]."east"} Falls eine unbekannte Orientierung übergeben wird.name + ". """ if o in {"north"."east"}: self. " + self."south". Wird ein Roboter x mit x. wird der Roboter nicht bewegt.

orientation def getPosition(self): """Liefert eine 2er-Liste mit [x. list)) and len(pos) == 2: self."north". pos muss eine Liste oder ein Tupel mit zwei Elementen sein.""" return self. """ return self. this is Andrew Andrew faces west at position [0.position = pos def rename(self.0]) print(x) Ruft man obiges Modul direkt auf.y] zurück. erhält man folgende Ausgaben: $ python3 robot. (tuple.name): """ Damit kann man dem Roboter einen neuen Namen geben.newOrientation("west") x. "Marvin") print(x) x.move(7) print(x) new_name = "Andrew" print(x. Ansonsten wird nichts getan. """ return self.rename(new_name) print("Hi.4.pos): """Damit kann man den Roboter auf eine neue Position im Koordinatensystem positionieren. """ self. 0] .move(10) x. this is " + x.py Marvin faces north at position [3.getName()) x. 14] Marvin will be renamed as Andrew Hi.""" if isinstance(pos. "east" oder "north".402 33 Lösungen zu den Aufgaben "west".position def setPosition(self.name if __name__ == "__main__": from robot import Robot x = Robot(3.setPosition([0.name = name def getName(self): """ Liefert den Namen des Roboters zurück. 4] Marvin faces west at position [-4. "south".getName() + " will be renamed as " + new_name) x.

n): """ A CaveInt can be either initialized by an integer or by a string consisting solely of tally marks.number def __int__(self): """ A CaveInt is converted into an integer """ return len(self. The number 0 . Aufgabe """ This module is implementing a Cave Man arithmetic "CaveInt". the simplest numeral system representing the natural numbers. other): """ Subtraction of two CaveInt numbers """ diff = int(self) .int(other) diff = diff if diff > 0 else 0 res = CaveInt(diff) return res def __mul__(self.is represented by an empty string """ class CaveInt(object): def __init__(self.number)) return res .count("|"): self.completely unknown to Neanderthal Man is .number = n def __str__(self): """ String representation of a CaveInt """ return self.number * len(other. A number n is represented by a string consisting of n tally marks (vertical strokes). other): """ Addition of two CaveInt numbers """ res = CaveInt(self.number = "" if type(n) == int: self.33. """ self.9 Lösungen zu Kapitel 19 (Objektorientierte Programmierung) 403 2. A positive integer n will be turned into a string with n tally marks. The number 0 and negative numbers are turned into an empty string.number) return res def __sub__(self.other): """ Multiplication of two CaveInt numbers """ res = CaveInt(self.number = "|" * n elif type(n) == str: if len(n) == n.number + other.number) def __add__(self.

append(item) def splice(self. l) def push(self.99]) . l): list. replacement): self[offset:offset+length] = replacement if __name__ == "__main__": x = Plist([33. int(z)) 3.8. item): self.34.y) z = x + y print(z) z = x . length.x print(z) z = CaveInt("") print(z) z = CaveInt(0) print(z) z = y / x print(z) z = x * y print(z.404 33 Lösungen zu den Aufgaben def __truediv__(self. Aufgabe class Plist(list): def __init__(self.y print(z) z = y .456.number) / len(other. offset.__init__(self.other): """ Division is of course integer division """ d = int(len(self.number)) res = CaveInt(d) return res if __name__ == "__main__": x = CaveInt("||||") y = CaveInt(12) print(x.

10 1. 99.2}b+. 5 . Diese rekursive Lösung ist höchst ineffizient.?d* (a) matcht 1. 3. Aufgabe Lösungen zu Kapitel 20 (Tests und Fehler) Die Formulierungen für den Doctest sind in Ordnung. 456.11 1. 6 (e) matcht 1. Sie müssen nur Geduld haben. Tage oder Wochen Sie warten müssen hängt von Ihrem Rechner ab. 47] [33. Aufgabe (1) (2) (3) (4) (5) (6) abc ac abbb bbc aabcd b (a) (b) (c) (d) (e) (f) (g) Lösungen zu Kapitel 24 (Reguläre Ausdrücke) ab+c? a?b*c b+c* ^b+c*$ a. 'Hey'.+b?c b{2. 4. 5 (d) matcht 4.3. erhält man folgende Ausgabe: $ python3 standardklassen. 'you'. 33.10 Lösungen zu Kapitel 20 (Tests und Fehler) 405 x. bis der Test terminiert.["Hey". 34. Das Problem liegt in der Implementierung der Fibonacci-Funktion. 3. 6 (g) matcht 1.py [33. 5 (c) matcht 1. 2. 456. Wie viele Stunden.33. 4.splice(2. "you"]) print(x) Startet man das Programm.}c? ^a{1. 5 (b) matcht 1. 47] 33.push(47) print(x) x. 3. 8. 5 (f) matcht 4.

denn in allen anderen kommt der Teilausdruck „xx” vor! Würde das Fragezeichen zum Ausdruck gehören. "Anchorage AK 99577-0727". 3. GA 30309". GA 3030-12345". wenn man annimmt. Aufgabe Die Frage lautete.search(r"[^-\d][0-9]{5}(-?[0-9]{4})?$". "Anchorage AK 9957-0727". Vielleicht hatten Sie irrtümlich gedacht. Antwort: Nur 2 matcht nicht.dest): print(dest + " okay") else: print(dest + " not okay") . der das Problem löst lautet. "Juneau AK 99750-0077". MN 554169". dass das Fragezeichen zum regulären Ausdruck gehört. "Mountain View. "Defreestville NY 12144-705". "Defreestville NY 12144-7050".406 33 Lösungen zu den Aufgaben 2. "Washington TX 778-800305"] for dest in destinations + erroneous: if re. "Mountain View. "Washington TX 778800305"] erroneous = ["Minneapolis. "Atlanta. CA 94 043". Aufgabe Ein regulärer Ausdruck. das der Zip-Code am Ende einer Zeile stehen muss. so wie es bei US-Briefen der Fall ist: r"\b[0-9]{5}(-?[0-9]{4})?$" Ein kleines Testprogramm finden Sie im Folgenden: import re destinations = ["Minneapolis. "Juneau AK 99750--0077". "Atlanta. CA 94043". MN 55416". Es gehört natürlich zur Frage. würde der reguläre Ausdruck auf alle Strings passen. auf welchen der Strings (1) (2) (3) (4) (5) xx xyxyxyx xxyxy xyxx xxyxyx der Ausdruck x(xy)*x matcht.

'battleship'. 'us'). 'chelaship'. 'steamship'} >>> len(words) 17 >>> 5. 'courtship'. 'gee'). 'la'). 'puff')} . Aufgabe >>> import re >>> x = open("ulysses.py Minneapolis. 'quis'). 'pull'). ('chinchin'. 'schschsch'). 'ee'). GA 30309 okay Washington TX 778800305 okay Minneapolis. ('whatwhat'. ('cancan'. ('tartar'. 'coo'). 'loo'). ('chokeechokee'. CA 94043 okay Atlanta. ' ooddle'). ('papa'. 'tar'). 'Lordship'.findall(r"\b((\w{2. 'chin'). 'lordship'.txt"). 'yum'). 'hip'). ('addleaddle'. erhält man folgende Ausgabe: $ python3 us_zip_codes.txt"). x)) >>> words {('eeee'. ('rara'. ('hellohello'. ('murmur '. 'lightship'. ' pleasureship'. 'marksmanship'.read() >>> words = set(re. MN 554169 not okay Defreestville NY 12144-705 not okay Anchorage AK 9957-0727 not okay Juneau AK 99750--0077 not okay Mountain View. CA 94 043 not okay Atlanta. x)) >>> words {'pumpship'. ('ooddleooddle'. (' yumyum'. Aufgabe >>> import re >>> x = open("ulysses. 're'). 'consulship'.findall(r"\b(\w+ship)\b". GA 3030-12345 not okay Washington TX 778-800305 not okay 4. ('lala'. ' worship'. ('poohpooh'. ('nyumnyum'. ('dumdum'. 'ra'). 'what'). 'dum'). 'friendship'. 'chokee'). 'fathership'. ' hello'). 'no'). ('curchycurchy'. ('bangbang'. (' looloo'. ('nono'.read() >>> words = set(re. MN 55416 okay Defreestville NY 12144-7050 okay Anchorage AK 99577-0727 okay Juneau AK 99750-0077 okay Mountain View.11 Lösungen zu Kapitel 24 (Reguläre Ausdrücke) 407 Startet man obiges Programm. ('coocoo'. 'pa'). (' hiphip'. 'bang'). 'mur'). 'nyum'). ('usus'. ('rere'. ' pooh'). 'tee'). ('geegee'. (' schschschschschsch'. 'debtorship'. 'township'. 'addle'). ('pullpull'. ('teetee'.33. ('quisquis '. 'jam').})\2)\b". 'curchy'). 'can'). 'fellowship'. ('puffpuff'. ('jamjam'.

'dumdum'. 'quisquis'.read(). 'teetee'. 'murmur'. 'curchycurchy'. 'eeee'. 'nono'.x)) word_frequency = {} for word in words: l = len(word) if l in word_frequency: word_frequency[l] += 1 else: word_frequency[l] = 1 print("Wortlänge Häufigkeit") word_frequency_list = list(word_frequency.lower() words = list(re. ' ooddleooddle'. 'puffpuff'} 6. 'rara'. 'addleaddle'. 'papa'. 'pullpull'. 'geegee '.freq)) Startet man obiges Programm. 'chokeechokee'. 'hiphip'. 'coocoo '.408 33 Lösungen zu den Aufgaben >>> words = { w[0] for w in words} >>> words {'whatwhat'.py Wortlänge 1 14930 2 43064 3 59122 4 47067 5 32513 6 23706 7 19561 8 11989 9 7901 10 4834 11 2706 12 1426 13 714 14 295 15 113 16 53 17 30 Häufigkeit . 'lala'. 'hellohello'.txt"). freq) in sorted(word_frequency_list): print("{0:8d} {1:8d}". 'cancan'. 'jamjam'. 'rere '. 'yumyum'. 'chinchin'. 'tartar'. ' looloo'. Aufgabe import re x = open("ulysses.findall(r"\b([a-z]+)\b". 'schschschschschsch'. 'nyumnyum'. 'usus'.format(wl.items()) for (wl. 'poohpooh'. 'bangbang'. erhält man unten stehende Ausgabe: $ python3 word_lengths.

x)) durch folgende Zeile zu ersetzen: words = set(re. Das Ergebnis sieht nun deutlich anders aus: $ python3 word_lengths. Dadurch werden automatisch mehrfache Vorkommen eines Wortes eliminiert.findall(r"\b([a-z]+)\b".11 Lösungen zu Kapitel 24 (Reguläre Ausdrücke) 409 18 19 20 21 22 23 24 25 26 27 28 30 33 34 36 37 39 69 16 6 7 6 1 2 1 3 2 1 1 1 1 1 2 1 1 1 Möchte man nur die Häufigkeitsverteilungen für verschiedene Wörter nach Wortlängen berechnen.py Wortlänge Häufigkeit 1 26 2 141 3 732 4 2038 5 3279 6 4331 7 4566 8 4273 9 3399 10 2441 11 1619 12 938 13 490 14 214 15 100 16 42 17 23 18 13 19 6 20 6 .33.x)) Man benutzt also eine Menge statt einer Liste.findall(r"\b([a-z]+)\b". braucht man nur die Zeile words = list(re.

410

33 Lösungen zu den Aufgaben

21 22 23 24 25 26 27 28 30 33 34 36 37 39 69

4 1 2 1 3 2 1 1 1 1 1 2 1 1 1

33.12
1. Aufgabe

Lösungen zu Kapitel 25 (lambda, map, filter und reduce)

orders = [ ["34587","Learning Python, Mark Lutz", 4, 40.95], ["98762","Programming Python, Mark Lutz", 5, 56.80], ["77226","Head First Python, Paul Barry", 3, 32.95]] min_order = 100 invoice_totals = list(map(lambda x: x if x[1] >= min_order else (x[0], x [1] + 10) , map(lambda x: (x[0],x[2] * x[3]), orders))) print(invoice_totals)

2. Aufgabe
from functools import reduce orders = [ ["34587",("5464", 44.95)], ["34588",("5464", ["34588",("5464", ["34587",("8732", 39.95)] ] min_order = 100 4, 9.99), ("8274",18,12.99), ("9744", 9, 9, 9.99), ("9744", 9, 44.95)], 9, 9.99)], 7, 11.99), ("7733",11,18.99), ("9710", 5,

33.13 Lösungen zu Kapitel 26 (Listen-Abstraktion/List Comprehension)

411

invoice_totals = list(map(lambda x: [x[0]] + list(map(lambda y: y[1]*y [2], x[1:])), orders)) invoice_totals = list(map(lambda x: [x[0]] + [reduce(lambda a,b: a + b, x [1:])], invoice_totals)) invoice_totals = list(map(lambda x: x if x[1] >= min_order else (x[0], x [1] + 10), invoice_totals)) print (invoice_totals)

33.13

Lösungen zu Kapitel 26 (Listen-Abstraktion/List Comprehension)

1. Aufgabe
>>> n = 30 >>> [(x, y) for x in range(1,n+1) for y in range(1,n+1) if not x % y and x != y ] [(2, 1), (3, 1), (4, 1), (4, 2), (5, 1), (6, 1), (6, 2), (6, 3), (7, 1), (8, 1), (8, 2), (8, 4), (9, 1), (9, 3), (10, 1), (10, 2), (10, 5), (11, 1), (12, 1), (12, 2), (12, 3), (12, 4), (12, 6), (13, 1), (14, 1), (14, 2), (14, 7), (15, 1), (15, 3), (15, 5), (16, 1), (16, 2), (16, 4), (16, 8), (17, 1), (18, 1), (18, 2), (18, 3), (18, 6), (18, 9), (19, 1), (20, 1), (20, 2), (20, 4), (20, 5), (20, 10), (21, 1), (21, 3), (21, 7), (22, 1), (22, 2), (22, 11), (23, 1), (24, 1), (24, 2), (24, 3), (24, 4), (24, 6), (24, 8), (24, 12), (25, 1), (25, 5), (26, 1), (26, 2), (26, 13), (27, 1), (27, 3), (27, 9), (28, 1), (28, 2), (28, 4), (28, 7), (28, 14), (29, 1), (30, 1), (30, 2), (30, 3), (30, 5), (30, 6), (30, 10), (30, 15)]

2. Aufgabe
Die Wahrscheinlichkeit dafür, dass die Summe der Augenzahlen 7 ist berechnet sich aus dem Quotienten der Anzahl aller Würfe mit Summe 7 („casts_of_sum_7”) dividiert durch die Anzahl aller möglichen Würfe („all_casts”):
>>> all_casts = [ (x,y) for x in range(1,7) for y in range(1,7)] >>> casts_of_sum_7 = [ x for x in all_casts if sum(x) == 7 ] >>> casts_of_sum_7 [(1, 6), (2, 5), (3, 4), (4, 3), (5, 2), (6, 1)] >>> probability7 = len(casts_of_sum_7) / len(all_casts) >>> probability7 0.16666666666666666

412

33 Lösungen zu den Aufgaben

3. Aufgabe
def prob_for_sum(number): all_casts = [ (x,y) for x in range(1,7) for y in range(1,7)] casts_of_sum = [ x for x in all_casts if sum(x) == number ] return len(casts_of_sum) / len(all_casts)

if __name__ == "__main__": for i in range(14): print("sum: {0:2d}, prob: {1:5.2f} %".format(i,prob_for_sum(i) *100 ) )

Startet man obiges Programm, erhält man folgende Ausgabe:
$ python3 sum_of_dices_prob.py sum: 0, prob: 0.00 % sum: 1, prob: 0.00 % sum: 2, prob: 2.78 % sum: 3, prob: 5.56 % sum: 4, prob: 8.33 % sum: 5, prob: 11.11 % sum: 6, prob: 13.89 % sum: 7, prob: 16.67 % sum: 8, prob: 13.89 % sum: 9, prob: 11.11 % sum: 10, prob: 8.33 % sum: 11, prob: 5.56 % sum: 12, prob: 2.78 % sum: 13, prob: 0.00 %

33.14
1. Aufgabe

Lösungen zu Kapitel 27 (Generatoren und Iteratoren)

def fibonacci(): """Ein Fibonacci-Zahlen-Generator""" a, b = 0, 1 while True: yield a a, b = b, a + b f = fibonacci() counter = 0

33.14 Lösungen zu Kapitel 27 (Generatoren und Iteratoren)

413

for x in f: print x, counter += 1 if (counter > 10): break

2. Aufgabe
def city_generator(): cities = ["Paris","Berlin","London","Vienna"] for city in cities: yield city def round_robin(g): while True: for i in g(): yield i

if __name__ == "__main__": for i in round_robin(city_generator): print(i)

Dies Ausgabe dieses Programms sieht wie folgt aus:
Paris Berlin London Vienna Paris Berlin London Vienna Paris Berlin London Vienna Paris ...

3. Aufgabe
def city_generator(): cities = ["Paris","Berlin","London","Vienna"] for city in cities: yield city

414

33 Lösungen zu den Aufgaben

def pendulum(g): while True: l = [] for i in g(): l.append(i) yield i while l: yield l.pop() if __name__ == "__main__": for i in pendulum(city_generator): print(i)

Starten wir dieses Programm, erhalten wir die folgende Ausgabe:
Paris Berlin London Vienna Vienna London Berlin Paris Paris Berlin London Vienna Vienna London Berlin Paris ...

4. Aufgabe
def numbers(): for i in range(1,10): yield i def pair_sum(g): it = g() previous = next(it) while True: try: x = next(it) yield x + previous previous = x except StopIteration: it = g()

33.15 Lösungen zu Kapitel 29 (NumPy)

415

if __name__ == "__main__": for i in pair_sum(numbers): print(i, end=", ")

Die Ausgabe sieht wie folgt aus:
3, 5, 7, 9, 11, 13, 15, 17, 10, 3, 5, 7, 9, 11, 13, 15, 17, 10, 3, 5, 7, 9, 11, ...

33.15
1. Aufgabe

Lösungen zu Kapitel 29 (NumPy)

Wenn zwei Vektoren senkrecht zueinander stehen, muss das Skalarprodukt 0 ergeben, weil der cos π 2 gleich Null ist. Wir prüfen dies für die beiden Vektorpaare:
>>> >>> >>> 0 >>> >>> >>> 0 >>> x = np.array([2,7,-3]) y = np.array([-2,1,1]) np.dot(x,y) x = np.array([2,3,-1]) y = np.array([-5,4,2]) np.dot(x,y)

2. Aufgabe
>>> import numpy as np >>> x = np.array([5,9,-5]) >>> y = np.array([-3,0,6]) >>> abs_x = np.sqrt(np.dot(x,x)) >>> abs_y = np.sqrt(np.dot(y,y)) >>> cos_xy = np.dot(x,y) / (abs_x * abs_y) >>> angle = np.arccos(cos_xy) >>> angle 2.1970314908665638 >>> angle * 360 / np.pi / 2 125.88063188398918 >>>

416

33 Lösungen zu den Aufgaben

3. Aufgabe
>>> A = >>> b = >>> x = >>> x array([ >>> np.array([[-2,-2,2,1],[-3,4,0,-2],[-1,2,3,2],[3,2,3,2]]) np.array([-5, -1, 0, 4]) np.linalg.solve(A,b) 1., 1., -1., 1.])

4. Aufgabe
Es sollten die Nullstellen für das Polynom f (x ) = 4 · x 3 + 12 · x 2 − 7 · x − 5 berechnet werden:
>>> import numpy as np >>> f = np.poly1d([4,12,-7,-5]) >>> np.roots(f) array([-3.40604443, 0.84193743, -0.43589299]) >>>

5. Aufgabe
>>> import numpy as np >>> f = np.poly1d([2,-3,-2,-1]) >>> f.integ() poly1d([ 0.5, -1. , -1. , -1. , 0. ]) >>> f.deriv() poly1d([ 6, -6, -2], dtype=int32) >>>

Das Integral F von f lautet also: F (x ) = 1 4 · x − 1 · x3 − 1 · x2 − 1 · x 2

Die Ableitung von f lautet: f ′ (x ) = 2 · x 3 − 3 · x 2 − 2 · x − 1

Stichwortverzeichnis

∧ bei regulären Ausdrücken 269 . Match eines beliebigen Zeichens 266 $ bei regulären Ausdrücken 269

A
abort 226 abspath 240 access 227 __add__ 403 Allgemeine Klasse → Basisklasse Anagramm – als Beispiel einer Permutation 309 Andrew 402 Angestelltenklasse → Personklasse append 75 Archivdatei erzeugen 251 Arrays 328 – flach machen → NumPy – konkatenieren → NumPy – ones() 332 – umdimensionieren → NumPy – zeros() 332 assertAlmostEqual 207 assertCountEqual 207 AssertEqual 206 assertEqual 207 assertFalse 208 assertGreater 208 assertGreaterEqual 208 assertIn 208 AssertionError 205 assertIs 208 assertIsInstance 209 assertIsNone 209 assertIsNot 209 assertItemsEqual 209 assertLess 208 assertLessEqual 208 assertListEqual 209

assertNotRegexpMatches 209 assertTrue 208 assertTupleEqual 209 assoziative Arrays 33 assoziatives Feld 33 atime 243 Attribute 162 – private 162 – protected 162 – public 162 AttributeError 172 Aufspalten von Zeichenketten 132 Auskellern 75 Ausnahme – StopIteration 306 Ausnahmebehandlung 149 – except 149 – finally 153 – try 149 Automatentheorie 261

B
Barry 195 basename 241 Bash 212 Basisklasse 169 Bayes-Theorem 367 bedingte Anweisungen 55 Bibliothek 90 Bierdeckelarithmetik 191 Bierdeckelnotation 191 binäre Operatoren 187 Binärsystem 191 Boehm 195 Bourne-Shell 212 Bruch – kürzen 349 – Kürzungszahl 349

267 erben → Vererbung errare humanum est 195 erweiterte Zuweisungen 188 Euklidischer Algorithmus 349 except 149 execl 225 execle 226 execlp 225 . 139 ctime 243 Decorator → Dekorateur Definition einer Variablen 21 Dekorateur 318 – Beispiel Fakultätsfunktion 320 – Benutzung in Python 319 – zur Implementierung eine Memoisation 320 – zur Überprüfung von Funktionsargumenten 320 deriv 343 derivation 343 Destruktor 160 Dezimalsystem 191 Diamond-Problem 176 Dictionary 33 – aus Listen erzeugen 43 – clear 38 – copy 38 – flache Kopie 38. 101 – fromkeys 38 – get 39 – items 39 – keys 39 – nested Dictionaries 37 – pop 40 – popitem 40 – setdefault 40 – tiefe Kopie 38.py 359 commonprefix 241 copy 249 → Dictionary copy2 249 copyfile 249 copyfileobj 249 copymode 249 copystat 250 copytree 250 count 78.418 Stichwortverzeichnis – Repräsentierung in Python|hyperpage 348 – vollständig gekürzte Form 349 Bruchklasse 347 Bruchrechnen 348 Bulls and Cows 358 bztar-Datei → Archivdatei erzeugen C Calendar-Klasse 177 CalendarClock-Klasse 177 Caret-Zeichen 267 Cast 24 Casting 24 CaveInt 403 → Neanderthal-Arithmetik center 144 chdir 227 chmod 227 Chomsky-Grammatik 117 chown 228 chroot 228 clear → Dictionary CLI 212 Clock-Klasse 177 close 218 Closure 318 Codeblock 59 combinatorics. 219 Dateigröße 244 Datenkapselung 157 Datentypen 21 Deadly Diamond of Death 176 E Eingabeprompt 9 Einheitsmatrix 339 Einkellern 75 Einschubmethode → Hook-Methode endliche Automaten 261. 101 – update 41 – verschachtelte Dictionaries 37 dirname 241 doctest 200 Dokumentenklassifikation 365 Donald Michie → Memoisation Drei-Finger-Regel 340 dup 220 dynamische Attribute 168 dynamische Typdeklaration 23 D Datei 69 – lesen 69 – öffnen 69 – schreiben 71 – zum Schreiben öffnen 71 Dateibaum – rekursiv durchwandern 240 Dateibearbeitung mit os 215 Dateideskriptor 218.

Stichwortverzeichnis

419

execlpe 226 execv 224 execve 224 execvp 222 execvpe 223 exists 242 expandvars 242 explizite Typumwandlung 24 extend 76 extsep 228

Frosch – Aufgabe mit Summenbildung 66 – Straßenüberquerung 66 frozensets 49 fully qualified 90 functools 294 Funktion 103 Funktionsabschluss 318

G
ganze Zahlen 22 Ganzzahlen 22 Generator – all_colours() 359 – Allgemein 305 – CLU 305 – Endlosschleife in 307 – firstn 312 – Icon 305 – isclice zur Ausgabe von unendlichen Generatoren 312 – k-Permuationen aus Zufallspermutation 359 – k-Permutationen 359 – k_permutations() 359 – pair_sum 315 – pendulum 314 – Permutationen 309, 359 – permutations() 359 – round_robin 314 – send-Methode 312 – Werte empfangen 312 – yield 307 – zur Erzeugung von Selektionen 310 Generator-Ausdrücke 313 Generator-Comprehension 302 Generatoren-Abstraktion 302 get → Dictionary get_archive_formats 251 getatime 243 getcwd 229, 247 getcwdb 229 getegid 229 getenv 213 getenvb 213 geteuid 229 get_exec_path 228 getgid 229 getgroups 229 getloadavg 229 getlogin 230 getmtime 243 getpgid 230

F
Fakultätsfunktion 117 – iterative Lösung 119 – rekursive Implementierung 118 – unter Benutzung eines Dekorateurs 320 Fehler – Semantik 196 – Syntax 195 Fehlerarten 195 fib → Fibonacci-Modul fiblist → Fibonacci-Modul Fibonacci 120 Fibonacci-Folge → Fibonacci-Zahlen – rekursive Berechnung 126 Fibonacci-Modul 197 – fib-Funktion 197 – fiblist-Funktion 197 Fibonacci-Zahlen – formale mathematische Definition 120 – Generator 314, 412 – Modul zur Berechnung der Fibonacci-Zahlen 197 – rekursive Berechnung mit Dekorateuren 318 – rekursive Funktion 119 filter 289 finally 153 find 78, 139 Finite State Machine 268 firstn-Generator 312 flache Kopie 38, 101 for-Schleife 62 – optionaler else-Teil 62 – StopIteration 306 – Unterschied zur while-Schleife 63 – Vergleich zu C 62 fork 228, 255 Forking 255 forkpty 228 formale Sprachen 261 fromkeys → Dictionary

420

Stichwortverzeichnis

getpgrp 230 getpid 230 getppid 230 getresgid 230 getresuid 230 getsize 244 → os.path getter 166 getuid 230 get_unpack_formats 251 ggT 349 Girokonto 170 Gleichungssysteme 340 grafische Veranschaulichung von Matrixwerten → Hinton-Diagramm größter gemeinsamer Teiler 349 Gruppierungen 274 GUI 212 gztar-Datei → Archivdatei erzeugen

H
Hash 33 Hinton-Diagramm 323 Hook-Methode 206 Hooks → Hook-Methode

isdir 245 isfile 245 isinstance 25 islice 312 – als Ersatz für firstn 312 islink 245 islower 145 ismount 246 isspace 145 istitle 145 isupper 145 itemgetter 84 items → Dictionary __iter__ 306 Iteration – for-Schleife 305 Iteratoren 305 – for-Schleife 305 itertools 312 – islice 312

J
join 139, 246 Junit 204

I
if-Anweisung 55 ignore_patterns 251 implizite Typumwandlung 25 import-Anweisung 90 in – Dictionaries 36 index 78, 139 index-Funktionen 220 Inheritance → Vererbung __init__.py 95 inneres Produkt 335 insert 79 Instanz 155 Instanzattribute 168 integ 343 Integer 22 interaktive Shell – Befehlsstack 13 – Starten unter Linux 9 – Starten unter Windows 10 – Unterstrich 12 inverse Matrix 339 isabs 244 isalnum 145 isalpha 145 isdigit 145

K
kanonischer Pfad 247 Kapselung 157 Keller 75 Kellerspeicher 75, 188 KeyError 35 keys → Dictionary kill 230 killpg 231 Klasse 156 – Erzeugen von Objekten 158 – Kopf 158 – Körper 158 – minimale Klasse in Python 158 Klassenattribute 168 – Zähler zum zählen der Objekte 168 Kombination 310 Kombinatorik-Modul 359 Kompilierung von regulären Ausdrücken 280 Komponententest 197 Konstruktor 160 Kontoklasse 158, 170 – mit Unterklassen 170 Kontrollstrukturen 55 Kopieren – von Unterlisten 100 – von verschachtelten Listen 97

Stichwortverzeichnis

421

Kreuzprodukt 335, 340 Kuchenklasse 155 Kundenklasse → Personklasse Kürzen 349

lseek 219 lstat 231

M
__main__ 197 major 231 make_archive 251 makedev 232 makedirs 232 map 289, 292 Mapping 33 Marvin 402 Mastermind 357 Match eines beliebigen Zeichens 266 Match-Objekte 274 Matching-Problem 264 – Over Matching 264 – Under Matching 264 MATLAB 323 Matrix-Klasse → NumPy Matrix-Produkt → NumPy Matrizenaddition 333 Matrizenmultiplikation 333, 337 Matrizensubtraktion 333 maxsplit – split 132 Mehrfachvererbung 174 – Beispiel CalendarClock 177 – Tiefensuche 174 Memoisation 123, 317 Memoization → Memoisation Memoize 319 memoize-Funktion 318 Menge 47 Mengen-Abstraktion 301 Mengenlehre 47 Methode 155, 159 – Overloading → Überladen – Overwriting → Überschreiben – Überladen 171 – Überschreiben 171 – Unterschiede zur Funktion 159 minor 231 mkdir 232 mkfifo 233 Modul – dir() 93 – Dokumentation 94 – dynamisch geladene C-Module 91 – eigene Module schreiben 93 – Inhalt 93 – lokal 90

L
lambda 289 Länge eines Vektors 335 Leonardo von Pisa → Fibonacci-Zahlen lexists 246 Liber Abaci 120 Lieferant → Personklasse linalg → NumPy lineare Algebra 340 lineare Gleichungssysteme 340 linesep 231 link 231 Linux 212 – Python unter 9 list – append 75 – extend 76 – find 78 – index 78 – pop 75 – sort 82 List Comprehension 297 – Kreuzprodukt 299 – pythagoreisches Tripel 299 – Sieb des Eratosthenes 300 – Syntax 298 – Vergleich mit konventionellem Code 298 – Wandlung Celsius in Fahrenheit 299 – Weitere Beispiele 299 – zugrundeliegende Idee 299 list:count 78 list:insert 79 list:remove 77 listdir 231 list_iterator 306 Listen-Abstraktion 297 – Kreuzprodukt 299 – pythagoreisches Tripel 299 – Sieb des Eratosthenes 300 – Syntax 298 – Vergleich mit konventionellem Code 298 – Wandlung Celsius in Fahrenheit 299 – Weitere Beispiele 299 – zugrundeliegende Idee 299 ljust 144 Lösung von Gleichungssystemen 340 lower 143

422

Stichwortverzeichnis

– math 90 – Modularten 91 – Namensraum 90 – re 263 – Suchpfad 92 modulare Programmierung 89 modulares Design 89 Modularisierung 89 Modultest 197 Modultests – unter Benutzung von __name__ 197 Monty Python 34 move 252 mtime 243 __mul__ 403

N
Naiver Bayes-Klassifikator 366, 367 __name__ 197 Namensraum – umbenennen 91 Neanderthal-Arithmetik 191 Nested Dictionaries 37 next 306 nice 233 Noam Chomsky 117 normcase 246 normpath 247 Nullstellen berechnen 343 Numarray → NumPy Numeric → NumPy Numeric Python → NumPy NumPy 323 – Array mit Nullen und Einsen initialisieren 332 – Array neue Dimension hinzufügen 332 – Arrays 325 – Arrays flach machen 327 – Arrays konkatenieren 330 – Arrays umdimensionieren 328 – deriv 343 – Drei-Finger-Regel 340 – Einheitsmatrix 339 – eye 339 – Gleichungssysteme 340 – inneres Produkt 335 – integ 343 – inv 339 – inverse Matrix 339 – Kreuzprodukt 335, 340 – Länge eines Vektors 335 – linalg 340

– – – – – – – – – – – – – – – – – – – – – – – –

lineare Algebra 340 lineare Gleichungssysteme 340 Lösung von Gleichungssystemen 340 Matrix-Klasse 336 Matrix-Produkt 337 Matrixarithmetik 333 Matrizenaddition 333 Matrizenmultiplikation 333, 337 Matrizensubtraktion 333 Nullstellen 341 Nullstellen berechnen 343 ones() 332 ones_like() 333 polynomial-Paket 341 Punktprodukt 335 Rechtssystem 340 roots 343 Skalarprodukt 335 Vektoraddition 334 Vektorprodukt 340 Vektorsubtraktion 334 Winkel zwischen Vektoren 335 zeros() 332 zeros_like() 333

O
Oberklasse 169 object 169 Objekt 155 Objektorientierte Programmiersprache 155 Objektorientierte Programmierung 155 ones_like() 333 OOP 155 – Datenkapselung 157 – Kapselung 157 – Kuchenklasse 155 open 216 open() 69 openpty 219 operator-Modul 84 – itemgetter 84 Operator-Überladung 187 Operatoren überladen – binäre Operatoren 187 – erweiterte Zuweisungen 188 – unäre Operatoren 188 os – abort 226 – access 227 – chdir 227 – chmod 227 – chown 228

Stichwortverzeichnis

423

– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – –

chroot 228 close 218 dup 220 execl 225 execle 226 execlp 225 execlpe 226 execv 224 execve 224 execvp 222 execvpe 223 extsep 228 fork 228 forkpty 228 getcwd 229 getcwdb 229 getegid 229 getenv 213 getenvb 213 geteuid 229 get_exec_path 228 getgid 229 getgroups 229 getloadavg 229 getlogin 230 getpgid 230 getpgrp 230 getpid 230 getppid 230 getresgid 230 getresuid 230 getuid 230 kill 230 killpg 231 linesep 231 link 231 listdir 231 lseek 219 lstat 231 major 231 makedev 232 makedirs 232 minor 231 mkdir 232 mkfifo 233 nice 233 open 216 openpty 219 popen 233 putenv 214 read 218 readlink 235

– remove 235 – removedirs 235 – rename 236 – renames 236 – rmdir 237 – sep 241 – setegid 237 – seteuid 237 – setgid 237 – setgroups 229 – setpgid 237 – setpgrp 237 – setregid 237 – setresgid 237 – setresuid 237 – setreuid 237 – setsid 237 – setuid 237 – stat 237 – stat_float_times 238 – strerror 238 – supports_bytes_environ 215 – symlink 238 – sysconf 239 – system 239 – times 239 – umask 239 – uname 239 – unlink 239 – unsetenv 215 – urandom 239 – utime 240 – wait 240 – wait3 240 – waitpid 240 – walk 240 – write 215 os-Modul 212, 226 os.path 240 os.python – abspath 240 – basename 241 – commonprefix 241 – dirname 241 – exists 242 – expandvars 242 – getatime 243 – getmtime 243 – getsize 244 – isabs 244 – isdir 245 – isfile 245

424

Stichwortverzeichnis

– islink 245 – ismount 246 – join 246 – lexists 246 – normcase 246 – normpath 247 – realpath 247 – relpath 247 – samefile 248 – split 248 – splitdrive 248 – splitext 248 Over Matching 264 Overloading → Überladen overloading 172 Overwriting → Überschreiben

R
random-Methode – sample 311 read 218 readlink 235 re-Modul 263 realpath 247 Rechtssystem 340 reduce 294 Regeln zur Interpretation von römischen Zahlen 385 register_archive_format 253 register_unpack_format 253 reguläre Ausdrücke 261 – Alternativen 279 – Anfang eines Strings matchen 269 – beliebiges Zeichen matchen 266 – compile 280 – Ende eines Strings matchen 269 – Kompilierung 280 – optionale Teile 271 – Qunatoren 272 – Teilstringsuche 263 – Überlappungen 263 – vordefinierte Zeichenklassen 268 – Wiederholungen von Teilausdrücken 272 – Zeichenauswahl 266 reguläre Auswahl – Caret-Zeichen, Zeichenklasse 267 reguläre Mengen 261 reguläre Sprachen 261 Rekursion 117 – Beispiel aus der natürlichen Sprache 117 rekursiv → Rekursion rekursive Funktion 117, 118 relpath 247 remove 77, 235 removedirs 235 rename 236 renames 236 replace 142 __repr__ 400 – Unterschied zu __str__ 400 rfind 139 rindex 139 rjust 144 rmdir 237 rmtree 253 Robot-Klasse 400 Roboterklasse 189 römische Zahlen 65 roots 343

P
Paket 95 Paketkonzept 95 Parameterliste 104 partion 139 Pascalsches Dreieck 124 – Fibonacci-Zahlen 125 peek 75 Permutationen 309 – mit Wiederholungen 309 – ohne Wiederholungen 309 Permutations-Generator 309 Personklasse → Vererbung Pfadname – absolut 244 – relativ 244 Polymorphismus 185 Polynome 341 pop 75, 188 → Dictionary popen 233 popitem → Dictionary Private Attribute – lesender und schreibender Zugriff mittels Methoden 166 Programmiersprache – Unterschied zu Skriptsprache 17 Properties 166 Punktprodukt 335 push 75, 188 putenv 214

Q
Quantoren 272

Stichwortverzeichnis

425

Rossum, Guido van 289 round_robin 314 rsplit 136 – Folge von Trennzeichen 137 rstrip 143 Rückwärtsreferenzen 274

S
samefile 248 sample 311 Schachbrett mit Weizenkörnern 66 Schaltjahre 58 Schleifen 55, 59 – Endekriterium 59 – for-Schleife 62 – Schleifendurchlauf 59 – Schleifenkopf 59 – Schleifenkörper 59 – Schleifenzähler 59 – while-Schleife 60 Schleifenzähler 59 Schlüssel – Dictionary 33 – zulässige Typen 36 Scientific Python → SciPy SciPy 323 Sekunden – Additon zu Uhrzeiten 58 Semantik 196 – Fehler 196 semantische Fehler 196 send-Methode 312 sep 241 set 47 set comprehension 301 setdefault → Dictionary setegid 237 seteuid 237 setgid 237 setgroups 229 setpgid 237 setpgrp 237 setregid 237 setresgid 237 setresuid 237 setreuid 237 sets – copy 50 – difference_update 51 – discard 51 – intersection 52 – isdisjoint 52

– issubset 53 – issuperset 53 – Operationen auf sets 49 – pop 53 – remove 52 setsid 237 setter 166 setuid 237 setUp-Methode 206 Shell 211 – Bash 212 – Bourne 212 – C-Shell 212 – CLI 212 – GUI 212 – Herkunft und Bedeutung des Begriffes 211 Shihram 66 shutil – copy 249 – copy2 249 – copyfile 249 – copyfileobj 249 – copymode 249 – copystat 250 – copytree 250 – get_archive_formats 251 – get_unpack_formats 251 – ignore_patterns 251 – make_archive 251 – move 252 – register_archive_format 253 – register_unpack_format 253 – rmtree 253 – unpack_archive 253 – unregister_archive 254 – unregister_unpack_format 254 shutil-Modul 249 Sieb des Eratosthenes 300 – Rekursive Berechnung 125 – Rekursive Funktion mit Mengen-Abstraktion 301 Simula 67 155 Skalarprodukt 335 Skriptsprache – Unterschied zu Programmiersprache 17 sort 82 – eigene Sortierfunktionen 83 – reverse 83 – Umkehrung der Sortierreihenfolge 83 sorted 82 Sparbuch 170 spezialisierte Klasse → Unterklasse

426

Stichwortverzeichnis

splice 192 split 132, 248 – Folge von Trennzeichen 137 – maxsplit 132 splitdrive 248 splitext 248 splitlines 138 Sprachfamilie 261 Stack 75 – Stapelspeicher 75 Standardbibliothek 90 Standardklassen als Basisklassen 188 Stapelspeicher 75, 188 stat 237 stat_float_times 238 statische Attribute 168 statische Typdeklaration 23 Stephen Cole Kleene 261 StopIteration 306 __str__ 349, 400 – Unterschied zu __repr__ 400 strerror 238 Strings – Suchen und Ersetzen 142 String-Tests 145 Stringmethoden – Alles in Großbuchstaben 143 – Alles in Kleinbuchstaben 143 – capitalize 143 – center 144 – count 139 – find 139 – index 139 – isalnum 145 – isalpha 145 – isdigit 145 – islower 145 – isspace 145 – istitle 145 – isupper 145 – ljust 144 – lower 143 – replace 142 – rfind 139 – rindex 139 – rjust 144 – rstrip 143 – String-Tests 145 – strip 143 – title 143 – upper 143 – zfill 144

strip 143 Strukturierungselement 103 __sub__ 403 Subklasse → Unterklasse Suchen und Ersetzen 142 Suchen von Teilstrings 139 Suchstrategie bei Mehrfachvererbung 174 Summe von n Zahlen 60 – Berechnung mit while-Schleife 60 SUnit 204 supports_bytes_environ 215 symlink 238, 245 syntaktische Fehler 195 Syntax 195 – Fehler 195 Syntaxfehler 195 sysconf 239 system 239 Systemprogrammierung 211

T
tar-Datei → Archivdatei erzeugen TDD → test-driven development tearDown-Methode 206 Tests 195 test first development 204 test-driven development 204 TestCase 206 – Methoden 206 – setUp-Methode 206 – tearDown-Methode 206 testCase 204 Testgesteuerte Entwicklung 204 Testgetriebene Entwicklung 202, 204 Testmethoden 206 Textklassifikation 365 Textverarbeitung 131 Theoretische Informatik 261 tiefe Kopie 38, 101 Tiefensuche 174 times 239 __truediv__ 403 try 149 Tupel – leere 80 – mit einem Element 80 – Packing 80 – Unpacking 80 type 25 type conversion 24 TypeError 199 – unhashable type 37

169 – Beispiel Angestelltenklasse. die von Person erbt 169 – Beispiel Kundenklasse. die von Person erbt 169 – Beispiel Lieferantenklasse. 169 Unterstrich – Bedeutung in der interaktiven Shell 12 update → Dictionary upper 143 urandom 239 utime 240 Vererbung 158. die von Person erbt 169 – Beispiel Personenklasse 169 Vererbungsbaum 174 verschachtelte Dictionaries 37 Verzeichnis löschen 237 Verzweigungen 55 Vollstandige Rekursion 117 W wait 240 wait3 240 waitpid 240 walk 240 Weizenkornaufgabe 66 while-Schleife 60 – optionaler else-Teil 61 Winkel zwischen Vektoren 335 write 215 Y yield 307 – im Vergleich zur return-Anweisung 307 Z Zahlenratespiel 61 Zeichenauswahl 266 Zeitrechnung 58 zeros_like() 333 zfill 144 zip-Datei → Archivdatei erzeugen Zufallspermutation 359 Zustandsautomat 268 Zustandsmaschine 268 Zuweisung 21 V Variablen 21 Variation 310 Vektoraddition 334 Vektorprodukt 340 Vektorsubtraktion 334 .Stichwortverzeichnis 427 Typumwandlung 24 – explizit 24 – implizit 25 U Überladen 171 – von Methoden 185 Überlappungen 263 Überschreiben 171 umask 239 Umgebungsvariablen 213 uname 239 unäre Operatoren 188 Unärsystem 191 Unary System → Unärsystem Under Matching 264 unhashable type 37 unittest 204 → Modultest Unix 212 unlink 239 unpack_archive 253 unregister_archive_format 254 unregister_unpack_format 254 unsetenv 215 Unterklasse 156.

.

den Stoff zu vertiefen. die sowohl von Programmier-Neulingen als auch von Programmierern mit Erfahrung in anderen Programmiersprachen besucht werden. Mengen und Dictionaries ■ Verzweigungen ■ Schleifen mit while und for ■ Modularisierung ■ Funktionen und rekursive Funktionen ■ Listen.eu und www. Forks. In diesem Buch werden alle grundlegenden Sprachelemente von Python 3 behandelt und auf dieser Basis auch weiterführende Themen wie Systemprogrammierung. Die wesentlichen Begriffe und Techniken der Programmierung und die zugrundeliegenden Ideen werden hier anschaulich erklärt. AUS DEM INHALT // ■ Erste Schritte mit Python ■ Datentypen: Listen. sondern zeigen vor allem auch exemplarische Vorgehensweisen.99 [D] | € 25. C++ oder Perl ■ Systematische und praxisnahe Einführung in die Kunst der Programmierung ■ Praxisnahe Übungen mit ausführlich dokumentierten Musterlösungen zu jedem Kapitel Kann man in einer Woche programmieren lernen? Genauer gesagt: Kann man in einer Woche mit Python programmieren lernen? Es ist möglich! Dies erfährt der Autor des Buches regelmäßig in seinen fünftägigen Python-Kursen.EINFÜHRUNG IN PYTHON 3 // ■ Besonders geeignet für Programmieranfänger.python-course. Besondere Anerkennung finden seine Python-Webseiten www. Implementierung des Spieles Mastermind und eine komplette Einführung in die automatische Dokumentenklassifikation. Der Diplom-Informatiker Bernd KLEIN ist Inhaber des international agierenden Schulungsanbieters Bodenseo.de/computer . »map« und »filter« ■ Text. Mastermind und Textklassifikation € 24.und Mengenabstraktion im Vergleich zu »lambda«.eu. Im Laufe seines Studiums und seiner beruflichen Tätigkeit hat er sich mit vielen Programmiersprachen intensiv beschäftigt. Tupel. aber auch für Umsteiger von anderen Sprachen wie C.hanser-fachbuch. Und die Übungsaufgaben mit ausführlich dokumentierten Musterlösungen helfen nicht nur.python-kurs. in den letzten Jahren jedoch auf Python spezialisiert. Zu den Problemstellungen werden typische Beispiele zur Verdeutlichung verwendet. Ausnahmebehandlung und Modultests. Threads. In interessanten Anwendungsfällen werden alle erlernten Konzepte zusammengeführt: Design einer Klasse »Bruch« für Bruchrechnung. Er studierte Informatik an der Universität des Saarlandes. die sich leicht auf andere Anwendungsfälle übertragen lassen.und Dateiverarbeitung ■ Reguläre Ausdrücke ■ Ausnahmebehandlung ■ Objektorientierte Programmierung ■ Module ■ Anwendungsbeispiele: Bruchklasse.70 [A] ISBN 978-3-446-43547-6 www. die in vielen anderen Bereichen Verwendung finden können.