Objektorientiert Programmieren mit Python 3 Lern- und Übungsheft Informatik Jahrgangsstufe 10 Stand vom 5.Oktober 2013 OStR Martin Frenkler Arnold-Gymnasium Neustadt b.Coburg Inhaltsverzeichnis Modellieren und Programmieren .....................................................................................4 1 Programmieren ..............................................................................................................5 1.1 Erste Schritte .................................................................................................................................5 1.2 Die ersten Schritte mit Python .......................................................................................................6 1.2.1 Interpretieren.........................................................................................................................6 1.2.2 Kompilieren..........................................................................................................................6 1.2.3 Installieren............................................................................................................................6 Aufgaben zu Kapitel 1 .......................................................................................................................6 2 Programmieren mit Python ............................................................................................7 2.1 Arbeiten mit der Idle .....................................................................................................................7 2.2 Codierung und „böse“ Zeichen .....................................................................................................7 2.3 Die Ausgabe auf dem Bildschirm ..................................................................................................8 2.3.1 Die print()-Funktion..............................................................................................................8 2.3.2 Datentypen............................................................................................................................8 2.4 Typumwandlung ...........................................................................................................................9 2.5 Die erweiterte Bildschirmausgabe ...............................................................................................10 2.5.1 Noch einmal die print()-Funktion........................................................................................10 2.5.2 Escape- und Steuerzeichen..................................................................................................10 2.5.3 Tastatureingabe...................................................................................................................11 Aufgaben zu Kapitel 2 .....................................................................................................................11 3 Imperatives Programmieren ........................................................................................13 3.1 Die Programm-Datei ...................................................................................................................13 3.1.1 Dateinamen.py....................................................................................................................13 3.1.2 Shebang..............................................................................................................................13 3.1.3 Doppelklick unter Windows................................................................................................13 3.1.4 Der Kommentar..................................................................................................................14 3.2 Sequenz und Pseudo-Code ..........................................................................................................14 3.2.1 Sequentiell – imperativ – prozedural...................................................................................14 3.2.2 Die Anweisungs-Zeile.........................................................................................................15 Aufgaben zu Kapitel 3 .....................................................................................................................15 4 Die einfache Variable ..................................................................................................16 4.1 Die Variable in der Mathematik ..................................................................................................16 4.2 Die Variable in der Informatik ....................................................................................................16 4.2.1 Die Variable als Box...........................................................................................................16 4.2.2 Wertzuweisung...................................................................................................................17 4.2.3 Ringtausch..........................................................................................................................18 Aufgaben zu Kapitel 4 .....................................................................................................................18 5 Die Sammelvariable ....................................................................................................19 5.1 Warum noch ein Variablen-Typ? ................................................................................................19 5.2 Informatiker zählen anders ..........................................................................................................19 5.3 Array, ArrayList und Liste ..........................................................................................................20 5.3.1 Listentypen.........................................................................................................................20 5.3.2 Punkt-Notation....................................................................................................................20 5.3.3 Listenumwandlung..............................................................................................................21 5.4 Der Listendurchlauf ....................................................................................................................21 5.4.1 Anweisung und Anweisungs-Block....................................................................................21 5.4.2 Der Listendurchlauf mit for.................................................................................................22 5.4.3 Der Wiederholung mit fester Anzahl...................................................................................22 5.5 Listen von Listen .........................................................................................................................23 5.6 String und Liste ...........................................................................................................................23 5.6.1 String-Listen in Strings umwandeln....................................................................................23 5.6.2 Buchstaben als Ziffern verwenden......................................................................................23 5.7 Methoden eines Listenobjekts .....................................................................................................24 Aufgaben zu Kapitel 5 .....................................................................................................................25 6 Die Variable im Arbeitsspeicher .................................................................................27 6.1 Die einfache Variable ..................................................................................................................27 6.2 Die Sammelvariable ....................................................................................................................27 6.3 Unterschiedliches Verhalten der Variablentypen .........................................................................28 6.3.1 Call by Value......................................................................................................................28 6.3.2 Call by Reference................................................................................................................28 6.3.3 Deep Copy..........................................................................................................................28 6.4 Identität und Gleichheit von Werten ............................................................................................29 Aufgaben zu Kapitel 6 .....................................................................................................................29 7 Kontrollstrukturen .......................................................................................................30 7.1 Wahrheitswerte (boolsche Werte) ...............................................................................................30 7.2 Die Wiederholung .......................................................................................................................31 7.2.1 Die bedingte Wiederholung................................................................................................31 7.2.2 Wiederholung mit Zähler....................................................................................................32 7.2.3 Die Wiederholung mit fester Anzahl (einfaches for)...........................................................32 7.2.4 Inkrement und Dekrement...................................................................................................32 7.2.5 Erweiterte For-Schleife (foreach)........................................................................................33 7.2.6 Ganzzahl-Teilung und Modulo-Rechnung..........................................................................33 7.2.7 Multiplikation und Divison als Wiederholung....................................................................33 7.3 Die Verzweigung ........................................................................................................................34 7.3.1 Die einfache Verzweigung..................................................................................................34 7.3.2 Die Alternative....................................................................................................................34 7.3.3 Kombination von Wahrheitswerten.....................................................................................34 7.3.4 Mehrfachverzweigung und Kombination von Wahheitswerten...........................................35 7.4 Geschachtelte Kontrollstrukturen ................................................................................................36 Aufgaben zu Kapitel 7 .....................................................................................................................36 8 Einfache Algorithmen ..................................................................................................38 8.1 Algorithmus ................................................................................................................................38 8.2 Beispiele .....................................................................................................................................38 8.2.1 Der größte gemeinsame Teiler (euklidischer Algorithmus).................................................38 8.2.2 Bubble Sort.........................................................................................................................39 Aufgaben zu Kapitel 8 .....................................................................................................................39 9 Strukturiertes Programmieren ......................................................................................40 9.1 Blackbox-Prinzip ........................................................................................................................40 9.2 Funktion ohne Rückgabewert (Prozedur) ....................................................................................41 9.2.1 Die verdeckte Variable........................................................................................................41 9.3 Funktion mit Rückgabewert ........................................................................................................42 9.3.1 Das return-statement...........................................................................................................42 9.3.2 Vergleich zur Tabellenkalkulation......................................................................................42 9.3.3 Ausblick: Funktionen und Methoden..................................................................................43 9.3.4 Benannte Parameter............................................................................................................43 9.3.5 Überladene Parameter.........................................................................................................44 9.3.6 Listen als Parameter............................................................................................................44 9.4 Für Profis: Funktionen der Tabellenkalkulation ..........................................................................45 9.4.1 Einfache Verschlüsselung...................................................................................................45 9.4.2 Uhrzeit, Datum, Geld und Kommazahlen..........................................................................45 9.5 Für Profis: Ausnahmebehandlung ...............................................................................................46 Aufgaben zu Kapitel 9 .....................................................................................................................46 10 Modulares Programmieren ........................................................................................47 10.1 Modul – import ........................................................................................................................47 10.2 Lexikon wichtiger Python-Module ............................................................................................47 10.2.1 Zufallswerte......................................................................................................................47 10.2.2 Zugriff auf das Betriebssystem (platform, os)*.................................................................48 10.2.3 Zugriff auf das Laufzeitsystem (sys)*...............................................................................48 10.2.4 Das Zeitsystem (time)*.....................................................................................................48 Aufgaben zu Kapitel 10 ...................................................................................................................49 11 Klassen und ihre Objekte ...........................................................................................50 11.1 Programmier-Prinzipien ............................................................................................................50 11.1.1 Maschinenabhängig..........................................................................................................50 11.1.2 Problemorientiert..............................................................................................................50 11.1.3 Objektorientiert.................................................................................................................50 11.1.4 Vorteile der Objektorientierung........................................................................................51 11.2 Klassen und Objekte .................................................................................................................51 11.2.1 Reales Objekt und Programm-Objekt................................................................................51 11.2.2 Objekte handeln nach innen und nach außen.....................................................................51 11.3 Mit Objekten arbeiten: Liste und Turtle ....................................................................................52 11.3.1 Listen als Objekte.............................................................................................................52 11.3.2 Die Turtle..........................................................................................................................52 Aufgaben zu Kapitel 11 ...................................................................................................................55 12 Selbst erstellte Klassen und ihre Objekte ..................................................................56 12.1 Die einfache Klasse ...................................................................................................................56 12.1.1 Klasse, Konstruktor und Objekt........................................................................................56 12.1.2 Das Objekt........................................................................................................................57 12.1.3 Methoden und Funktionen................................................................................................57 12.1.4 Methoden geben Werte aus...............................................................................................58 12.1.5 Objekte initialisieren - Attribute........................................................................................58 12.1.6 Geheimnisprinzip..............................................................................................................59 12.1.7 Methoden, die Werte setzen..............................................................................................60 12.1.8 Klassen- und Objektdiagramm..........................................................................................61 12.1.9 Kommunikation von Objekten - Sequenzdiagramm..........................................................61 12.1.10 Zustand und Zustandsübergang.......................................................................................62 12.1.11 has_a-Beziehung.............................................................................................................63 12.2 Vererbung .................................................................................................................................64 12.2.1 Die Flexibilisierung bei der Programmierung...................................................................64 12.2.2 Typ-Prüfung......................................................................................................................64 12.2.3 Spezialisieren....................................................................................................................65 12.2.4 Generalisieren (is_a-Beziehung).......................................................................................66 12.2.5 Polymorphie......................................................................................................................67 12.2.6 Schnittstellen.....................................................................................................................68 Aufgaben zu Kapitel .......................................................................................................................69 13 Probleme objektorientiert lösen .................................................................................70 13.1 Projektplanung ..........................................................................................................................70 13.2 Mögliche Projekte .....................................................................................................................70 13.3 Die Schule, ihre Schüler und Lehrer ..........................................................................................71 Beispiele für eine Hausaufgabe .....................................................................................75 ooP mit Python Modellieren und Programmieren Modellieren und Programmieren Modellierung reduziert Kompexität. Als informatische Modellierung entwirft sie ein Bild von der Wirklichkeit, das so auf die notwendigsten Daten reduziert ist, dass deren Bearbeitung automatisiert werden kann. Ist das Modell gelungen – erfasst es den richtigen Ausschnitt der Wirklichkeit und lässt sich mit dem aus dem Modell heraus entwickelten Informationssystem gut arbeiten, sind die Mühen der Entwicklung schnell vergessen. Das Ergebnis wirkt wie die Arbeit eines Künstlers, der scheinbar nur den überflüssigen Stein wegzuschlagen hatte. Die Skulptur steckt schon längst im Stein! Du musst nur das Überflüssige wegschlagen Tatsächlich aber benötigen Künstler wie Informatiker nicht nur ein klares Modell. Sie müssen auch Techniken beherrschen, um ihr Material angemessen bearbeiten zu können. Denn das Ergebnis des Gestaltens soll ja auch dem Bild entsprechen, das zu Beginn im Kopf war. Übertragen auf den Informatik-Unterricht der 10. Jahrgangsstufe benötigen die Schülerinnen und Schüler also nicht nur ein Wissen um die Grundideen der informatischen Modellierung. Sie müssen auch die sprachlichen Mittel der Programmierung kennen, um ein Modell zu formulieren, das sie dann in ein Softwareprojekt umsetzen. Das vorliegende Lern- und Übungsheft bietet einen Lernweg, der sich an der Evolution des imperativen Programmierens orientiert. Jeder Schritt, angefangen bei der einfachen Zuweisung über die strukturierte Programmierung bis zum objektorientierten Programmieren, ist so angelegt, dass er nichts voraussetzt, was noch nicht gelernt ist. Dabei finden die Lernenden in jedem Abschnitt bereits bekannte Konzepte im neuen Kontext wieder vor und können so den erweiterten Bedeutungsumfang erfassen. Kontrollstrukturen führen zu Algorithmen, die dann in Funktionen gekapselt werden und in der objektorientierten Programmierung als funktionale Methoden zur Verfügung stehen. Von hier aus ist der Weg zum Entwurfsmuster Singleton in der Oberstufe nicht weit. Gleichzeitig wird deutlich, dass Objektorientierung sich nicht in funktionalen Objekten erschöpft. Die Programmiersprache Python wurde gewählt, weil sie bei der Codierung viele Fallstricke aus dem Weg räumt, was gerade AnfängerN entgegen kommt. Das Konzept des Wortschatzes zeigt, dass bestimmte Sprachelemente stets im Kopf und damit griffbereit sein sollten. Der Rückblick auf die Arbeit mit der Tabellenkalkulation ermöglicht das Einbinden älteren Wissens und der immer wieder angesetzte Seitenblick nach Java macht deutlich, dass nicht drill and practice einer bestimmten Programmiersprache im Vordergrund stehen, sondern die Grundkonzepte des Modellierens und Programmierens. 4 ooP mit Python 1 Programmieren 1.1 Erste Schritte Programmieren Der älteste kommerziell eingesetzte Computer steht heute im Deutschen Museum in München. Er wurde von Konrad Zuse während der letzten Jahre des II.Weltkriegs als mechanischer Rechner für den Flugzeugbau in Berlin gebaut. Nach dem Krieg wurde der Rechner zunächst von der ETH Zürich genutzt. Für Zuses Maschine gab es eine eigene Programmiersprache, den Plankalkül. Zuse-Rechner Z4 im Deutschen Museum ENIAC, der erste US-amerikanische elektronische Computer musste mit Hilfe von Steckverbindungen programmiert werden. Was hier die beiden Operator nach Plan organisieren, leistet heute das Betriebssystem (englisch: Operating System) Später wurden die Steckverbindungen durch Lochkarten ersetzt und durch Programme, die tatsächlich nur aus Nullen und Einsen bestanden. Eine erste Vereinfachung kam mit der Assembler-Programmierung. Jede Maschine besitzt einen bestimmten Befehlssatz, auf den mit symbolischen Begriffen zugegriffen werden kann. Eniac im Einsatz der US-Army Die Maus wird dann etwa mit den folgenden Befehlen angeschaltet: mov ax, 01h int 33h Dass wir heute Programme in Klartext entwickeln können, der dann von einem anderen Programm in Maschinencode übersetzt wird, haben wir der Computerpionierin Grace Hopper zu verdanken, die im Jahr 1952 den ersten Compiler schrieb. 5 Grace Hopper am Univac - einem Röhren-Computer ooP mit Python Programmieren 1.2 Die ersten Schritte mit Python 1.2.1 Interpretieren Python ist eine sehr einfach zu erlernende objektorientierte Programmiersprache. Sie kann auf allen Betriebssystemen (wie Windows, Linux, Mac) eingesetzt werden. Programme in Python werden lesbar geschrieben und abgespeichert. Auf jedem Rechner, auf dem Python-Programme laufen sollen, muss die Programmierumgebung Python installiert sein. Phython übersetzt die Programme während sie ablaufen in Maschinensprache, das heißt das Laufzeitsystem Python interpretiert das Programm. Phyton zählt deshalb zu den interpretierenden Scriptsprachen. Die Dateiendung .py für Python-Programme weist Windows daraufhin, dass es die Python-Umgebung einsetzen soll, um diese Datei zu lesen. 1.2.2 Kompilieren Programme dagegen, die in C oder C++ geschrieben wurde, müssen vor ihrem Einsatz für das jeweilige Betriebssystem kompiliert werden. Die Dateiendung .exe weist Windows darauf hin, dass das Programm direkt ausgeführt werden kann. 1.2.3 Installieren Um mit Python arbeiten zu können muss das Laufzeitsystem installiert werden. Lexikon: Python installieren Installion unter Windows Installationsdatei laden von python.org/download/ x86 oder x68-64 MSI Installer Ein Doppelklick reicht zum installieren Installation unter Linux und auf dem Mac Unter Linuxsysteme wie auf dem Mac wird Python mit dem jeweiligen Paketmanager installiert Aufruf von Python Idle3 alle Aufgaben können ab jetzt auf der Eingabezeile der Pythonkonsole ausgeführt werden Aufgaben zu Kapitel 1 1 Die ersten Schritte 1) Installiere Python auf deinem Rechner 2) Suche im Internet nach Python-Tutorials 6 Python-Versionen Python 2.x und Python 3.x Versionen sind nicht kompatibel. Wir verwenden Python 3.x, weil es besser strukturiert ist, Python 2.x läuft auf vielen WebServern, weil es dazu noch mehr Module gibt. ooP mit Python Programmieren mit Python 2 Programmieren mit Python 2.1 Arbeiten mit der Idle Programme werden mit einem Texteditor geschrieben. Textverarbeitungsprogramme sind dafür nicht geeignet. Eine Programmierumgebung wie etwa Eclipse ist für Anfänger wieder zu schwer zu bedienen. Python liefert statt dessen einen eigenen einfachen Editor mit, die Idle. Er beherrscht Syntax-Highlighting, hebt also die verschiedenen Sprachelemente mit unterschiedlichen Farben hervor. von der Idle-Konsole zum Programmfenster Wir können den Idle-Editor als Konsole einsetzen, also im interaktiven Modus verwenden. Dann wird jeder eingegebene Befehl sofort ausgeführt (oder bei Programm-Fehlern mit einer Fehlemeldung verweigert). Programme können aber auch als Dateien geschrieben und gespeichert werden. Dazu muss aus der Idle-Konsole heraus ein neues Fenster geöffnet werden. Diese Programmdateien können mit dem Aufruf RunModule bzw. über die Taste F5 getestet werden. 2.2 Codierung und „böse“ Zeichen Die Urahnen unserer heutigen Computer entstanden in den USA. Sie kannten nur den amerikanischen Zeichensatz (ASCII-Code), zu dem die europäischen Sonderzeichen wie ä, ö, ü, ß nicht gehören. Das Leerzeichen wurde als Befehlstrenner verwendet. Auch wenn die meisten Betriebsysteme mit Umlauten und Leerzeichen in Dateinamen umgehen können, führt deren Verwendung immer wieder zu Fehlern, zum Beispiel beim Datentausch zwischen den Systemen, etwa über das Internet. Für den ProgrammCode und für Dateinamen sind Sonderzeichen deshalb tabu. Leerzeichen im Programmtext werden wie ehedem einzig und allein als Befehlstrenner eingesetzt. Python lässt in Texten (Strings) auch europäische Umlaute zu, sowie die Schriftzeichen anderer Sprachen. Diese UTF-Codierung muss aber der Programmier-Umgebung im Coding-Hinweis mitgeteilt werden. Er steht im Programm vor allen anderen Befehlen. Lexikon: Codierung # -*- coding: utf-8 -*- Coding: Hier gilt die UTF-8-Kodierung 7 ooP mit Python Programmieren mit Python 2.3 Die Ausgabe auf dem Bildschirm 2.3.1 Die print()-Funktion Funktionen kennen wir bereits aus der Tabellenkalkulation. Sie werden mit ihrem Funktionsnamen aufgerufen. Die Parameterliste kann leer sein bzw. mit einem oder oder mehreren Parameterwerten (Argumente) belegt sein. Funktionen geben immer einen Wert aus. Der Name der print()-Funktion verrät als sprechender Name, dass sie zum Schreiben da ist. Konkret gibt sie den zu schreibenden Text auf den Text-Bildschirm aus. Unter Windows ist das die Eingabeaufforderung, unter Linux heißt das Konsole. Die print()-Funktion erzeugt in der Standardversion immer einen Zeilenumbruch. Wortschatz: Die print()-Funktion print() print('Hallo Welt') print(1) 2.3.2 leere print()-Funktion print()-Funktion mit dem Text-Argument 'Hallo Welt' print()-Funktion mit der Zahl 1 als Argument Datentypen Texttypen wie Texte (String) und Zeichen (Character) werden immer zwischen Hochkomma gesetzt. Zahlen, wie die ganzen Zahlen (Integer) und die Kommazahlen (Float) bleiben unmarkiert. Datentypen haben unterschiedliche Eigenschaften und Fähigkeiten: So wird der +Operator (sprich 'Plus-Operator') von Text- und Zahlentypen unterschiedlich verwendet: Rechnen können nur die Zahlen-Datentypen. Bei Texttypen bewirkt der +Operator, dass die beiden Texte zusammengefügt werden. Vorsicht: Dabei entstehen neue Textobjekte, die alten Texte bleiben erhalten und müllen den Arbeitsspeicher zu. Wortschatz: Text-Typen “Hallo Welt“, 'Hallo Welt' “Hallo 'Welt'“, 'Hallo “Welt“' print(“Hallo“ + “Welt“) print('Hallo'+ 'Halloechen!') 'H', “H“ '1', “1“ print(“1“+'1') String (einfacher Text) wird mit einfachen Hochkommata oder Anführungszeichen markiert. Um innerhalb eines Textes einfache Hochkommata verwenden zu können, muss der ganze Text in Anführungszeichen stehen und umgekehrt Texte können zusammengefügt werden. Dazu dient der +Operator Der Textteil einer print()-Funktion kann auch auf mehrere Zeilen verteilt werden. Die Ausgabe geschieht trotzdem in einer Zeile. Character oder Char (Buchstabe) einzelne Buchstaben verhalten sich wie Text. Sie können aber auch in eine Zahl umgewandelt werden. Auch Zahlen können als Buchstaben geschieben werden, dann heißen sie Ziffern. Ziffern werden wie Texte zusammengefügt und nicht berechnet 8 ooP mit Python Programmieren mit Python Wortschatz: Zahlen Integer (ganze Zahlen) Zahlen brauchen keine Hochkommata oder Anführungszeichen – mit ihnen kann man in Python unmittelbar rechnen print(1) print(1+1) Float (Kommazahlen) Statt des Komma wird der amerikanische Punkt gesetzt Kommazahlen können aus ganzen Zahlen erzeugt werden print(72.0) print(3/2) Vorsicht: Die Nachkommastellen bei Floats werden ungenau berechnet, deshalb kann es beim Rechnen mit Floats zu seltsamen Ergebnissen kommen: 2.15+2.15+2.15=6.449999999999999 Wortschatz: Rechenoperatoren + - / * Potenz: ** Operatoren der Grundrechenarten Die Potenz wird als doppelte Mutliplikation dargestellt round(10.6) # Ergebnis: 11 round(10.5) # Ergebnis: 10 Mathematische Funktionen round(vorkomma.nachkomma) - rundet kaufmännisch ab- bzw. auf round(10.1234,2) # Ergebnis: 10.12 - kürzt die Nachkommastellen Das erste Argument gibt den FloatWert. Das zweite Argument nach dem Komma bestimmt die die Zahl der Nachkommastellen abs(-4) abs(zahl) erzeugt den absoluten Betrags 2.4 Typumwandlung Die verschiedenen Datentypen können mit einfachen Funktionen ineinander umgewandelt werden. Als sprechende Funktionen erzeugen die Umwandlungsfunktionen den Wert für den ihr Name steht. Auf der Konsole können sie auch ohne die print()-Funktion eingesetzt werden. Wortschatz: Typumwandlung ord() print(ord('H')) Mit Hilfe der ord()-Funktion können Chars in ganze Zahlen (Integer) umgewandelt werden: ord('H') erzeugt 72 chr() print(chr(72)+chr(72)) Mit Hilfe der chr()-Funktion werden ganze Zahlen (Integer) in Zeichen (Character) umgewandelt: chr(72) erzeugt 'H' str() print(str(72.0)+str(72.0)) Mit Hilfe der str()-Funktion können beliebige Werte in Text (String) umgewandelt werden: str(72.0) erzeugt '72.0' int() print(int(72.6)) Mit Hilfe der int()-Funktion werden Kommazahlen (Float) in ganze Zahlen (Integer) umgewandelt. Dabei werden die Kommawerte abgeschnitten: int(72.6) erzeugt 72 float() print(float(72)) Mit Hilfe der float()-Funktion werden ganze Zahlen (Integer) in Kommazahlen (Float) umgewandelt: float(72) erzeugt 72.0 9 ooP mit Python Programmieren mit Python 2.5 Die erweiterte Bildschirmausgabe 2.5.1 Noch einmal die print()-Funktion Die print()-Funktion erzeugt standardmäßig eine Bildschirm-Ausgabe und einen darauf folgenden Zeilenumbruch. Sie kann jedoch sehr flexibel eingesetzt und erweitert werden. Wortschatz: Die erweiterte print()-Funktion Standard Die leere Funktion gibt nur einen Zeilenumbruch aus Das Argument der Funktion (der Parameterwert) wird auf der Konsole ausgegeben, dann folgt der Zeilenumbruch print() print(1) / print('Text') Es können auch mehrere Argumente durch Komma getrennt übergeben werden. Sie werden dann durch Leerzeichen getrennt ausgegeben. Diese Argumente können auch zu unterschiedlichen Datentypen gehören. print("Text"," 'mein' Text",1) Das Separator-Argument hebt die Standard-Trennung auf. Statt durch das Leerzeichens werden die Argumente durch das dem sep-Parameter zugewiesene Zeichen getrennt. print(1,2,3, sep=“-“) Das End-Argument ersetzt den Zeilenumbruch, der standardmäßig vorgesehen ist. Nach der Ausführung der print()-Funktion wird die Zeile mit den Zeichen beendet, das dem end-Parameter zugewiesen wurde. Das kann z.B. ein Leerzeichen ' '' sein oder auch das leere Zeichen '' . print(''Wert'', end=“ENDE“) print(''Wert'', end=“ “) print(''Wert'', end=““) print(1,2,3, sep=“-“, end=“ENDE“) 2.5.2 Kombination: alle drei Parametertypen lassen sich beliebig kombinieren Escape- und Steuerzeichen Die Textverarbeitung kennt das Konzept der nicht-druckbare Steuerzeichen, wie TABULATOR oder ENTER. Solche Steuerzeichen gibt es auch in Python. Normale Zeichen werden mit dem Backslash als Ausnahmezeichen (Escape-Zeichen) markiert. Sie zeigen dann einen anderen Text an. Lexikon: Escape- und Steuerzeichen Zeichen und Beispiel Bedeutung Ausgabe \ Der Backslash (escape-Zeichen) markiert einige Zeichen zu Steuerzeichen um \n print('Ein\nUmbruch') Zeilenumbruch im Text \t print('ich\tund\tdu) erzeugt einen Tabulator \' bzw. \“ print(“Ein \“Text\“ - “) erzeugt ein einfaches bzw. eine doppeltes Hochkomma Ein “Text“ - \\ print('/\\') gibt dem Backslash seine ursprüngliche Bedeutung zurück. /\ Ein Umbruch Ich 10 und du ooP mit Python 2.5.3 Programmieren mit Python Tastatureingabe Interaktive Programme erwarten immer wieder Eingaben über die Tastatur. Dieser InputBefehl ist in den verschiedenen Programmiersprachen unterschiedlich umgesetzt, wir sagen: implementiert. In Python übernimmt diese Aufgabe die input()-Funktion. Wortschatz: Tastatureingabe Die input()-Funktion Der Input-Befehl bzw. die input()-Funktion wartet drauf, dass während des Programmablaufes ein Wert über die Konsole eingegeben wird. Dieser Wert wird vom Programm immer als Text gelesen. print(input('gib einen Wert ein: ')) print(int(input('Ganzzahl: '))+2) print(float(input('Kommazahl: '))+2) print(int(float((input('Kommazahl: ')))+2)) Zahlen Soll eine Zahl eingegeben werden, muss die eingegebene Zahl mit der int()- oder dem float()Funktion in eine Zahl umgewandelt werden Aufgaben zu Kapitel 2 1 Bildschirmausgabe 1) Schreibe mit Hilfe mehrerer print()-Funktionen deine vollständige Adresse. 2) Notiere für den Bildschirm deine Adresse und deine Klasse. Verwende dazu nur eine einzige print()-Funktion. 2 Datentypen 1) Printe auf der Idle-Konsole dein Alter in Jahren, Monaten und Tagen. Kläre, welche Datentypen du dafür am sinnvollsten einsetzt. 2) Rechne dein Alter auf der Idle-Konsole in Tage um. Addiere und multipliziere dabei geschickt und vergiss die Schaltjahre nicht! Kläre, welche Datentypen du hier einsetzen musst. 3) Berechne den Notendurchschnitt einer Ex, in der 4 mal die 1, 6 mal die 2, 8 mal die 3, 4 mal die 4, 2 mal die 5 und 1 mal die 6 vorgekommen sind. Setze dabei geschickt Klammern ein! 3 Typumwandlung 1) Finde mit Hilfe der ord()-Funktion heraus, welchen Zahlen die Klein- und Großbuchstaben des Alphabets zugeordnet sind. Überprüfe auf die gleiche Weise alle Ziffern. Suche z.B. in Wikipedia die ASCII-Tabelle und erkläre diese Ergebnisse 2) Teste int(3/2) und erkläre mit eigenen Worten, was bei der Verwendung int()-Funktion mit dem Bruchwert einer Kommazahl geschieht. 3) Teste die chr()-Funktion mit einer beliebigen Kommazahl und notiere die Ausgabe. Kläre, was sie bedeuten könnte. 4) Teste die folgende Funktion und erkläre ihr Ergebnis: chr(int(ord('z'))+4 11 ooP mit Python 4 Programmieren mit Python Die Zahl 42 In seinem ScienceFiction-Roman „Per Anhalter ins All“ erzählt der Autor Duglas Adams, dass die Menschen oder wie man immer auch diese Wesen nennen soll, 'den Sinn von allem und überhaupt' herausfinden wollten. Dazu wurde 'Deep Thought' gebaut, der größte Computer aller Zeiten. Nach etlichen Jahrmillionen kam er zu einem die Auftraggeber höchst enttäuschenden Ergebnis. Die Antwort auf die Frage nach 'dem Sinn von allem und überhaupt' sei 42! - Die Frage, so Deep Thought, war leider zu ungenau gestellt. Prüfe mit Hilfe der ord()-Funktion, welchen Gag der Autor Douglas Adams mit der Zahl 42 erzeugt hat – denke dabei auch an deine Kenntnisse über Datenbankabfragen mit SQL. 5 Die erweiterte Bildschirmausgabe 1) Schreibe mit sechs print()-Funktionen das „Haus des Nikolaus“ auf die Konsole. Nutze dabei die geeigneten Escape- und Steuerzeichen. 2) Erzeuge mit einer einzigen print()-Funktion deinen Stundenplan. Verwende dazu auch den Tabulator. Als kleine Hilfestellung: In der Idle kann die Zeile an einem Komma umgebrochen werden! /\ / \ ---|\/| |/\| ---- 3) Schreibe den folgenden Text in eine print()-Funktion. 'An einem lauen Sommerabend fuhr ein verwegener Bursche mit seinem feuerroten Rennwagen behäbig auf der ruhigen Landstraße auf die rotglänzend untergehende Sonne zu.' Brich dabei den Text durch an geeigneten Stellen innerhalb der print()-Funktion um. Verwende dazu einmal den +Operator und einmal die Trennung mit Komma. 6 Tastatureingabe 1) Schreibe die input()-Anweisung aus dem Wortschatz Tastatureingabe (Kapitel 2.5.3) auf die Konsole und übergib ihr einen beliebigen Wert. – Erkläre das Ergebnis mit deinem Wissen über Funktionen aus der 9.Klasse. 2) Teste die Zahlen-Eingaben aus dem Wortschatz Tastatureingabe und notiere im Heft, wie die Funktionen abgearbeitet werden. 3) Schreibe eine print()-Funktion mit drei input()-Funktionen als Parameter. Sie sollen nach dem Vornamen, dem Nachnamen und nach der Klasse fragen. 4) Ersetze im folgenden Text die Adjektive durch input()-Funktionen mit jeweils einer geeigneten Aufforderung zur Texteingabe und führe das Programm aus: 'An einem lauen Sommerabend fuhr ein verwegener Bursche mit seinem feuerroten Rennwagen behäbig auf der ruhigen Landstraße auf die rotglänzend untergehende Sonne zu.' 5) Schreibe eine Funktion, in der der Notendurchschnitt einer Arbeit mit beliebig vielen Schülern berechnet werden kann. Beachte: input() liefert Strings → Umwandlungsfunktion nutzen! 12 ooP mit Python Imperatives Programmieren 3 Imperatives Programmieren 3.1 Die Programm-Datei 3.1.1 Dateinamen.py Windows erkennt an der Datei-Endung, mit welchem Programm eine bestimmte Datei geöffnet werden soll (z.B: .doc → MS WORD). Die Datei-Endung für Python ist py. Diese Endung signalisert auch dem Idle-Editor, dass er Syntax-Highlighting für Python verwenden soll. Dateien sollten immer einen sprechenden Namen bekommen, der verrät, was das Programm tut. Leerzeichen und Sonderzeichen sind dabei zu vermeiden, schließlich ist ja nicht immer klar, unter welchen Betriebssystemen die Datei eingesetzt werden kann. Längere Dateinamen können aus mehreren Wörtern zusammengesetzt sein. Dann werden die Wortteile durch die sogenannte CameCaseSchreibweise unterschieden. Lexikon: camelCase und .py – die Konvention für Dateinamen printTest.py 3.1.2 sprechender Namen in camelCaseSchreibweise Die Dateiendung für Python-Programme ist .py Shebang Unter Linux muss eine Scriptdatei in der ersten Programmzeile selbst mitteilen, welche Konsole für die Bearbeitung des Programmes zuständig ist. Nach dem Rautenzeichen # (she für sharp) und dem Ausrufezeichen ! (bang), daher der Name Shebang, folgt der Pfad zum Programm. Im Allgemeinen beginnen Python-Programme deshalb immer mit dem Shebang. Windows ignoriert ihn. Deshalb können Pythonprogramme unverändert unter Linux und unter Windows zum Einsatz kommen. Lexikon: Shebang #! /usr/bin/env python 3.1.3 Shebang am Anfang eines Programm-Textes Doppelklick unter Windows Unter Windows können Python-Programme mit Doppelklick geöffnet werden, dann läuft das Programm in der Windows-Eingabeaufforderung. Textorientierte Programme schließen das Konsolenfenster aber, sobald das Programm beendet ist und die Ausgabe der Ergebnisse verschwindet. Das geschieht nicht, wenn wir den leeren input()-Befehl als Abschluss verwenden. Lexikon: input()-Abschluss input() Hält nach Ablauf des Programms das Fenster der Eingabeaufforderung offen 13 ooP mit Python 3.1.4 Imperatives Programmieren Der Kommentar Kurze Programme können mit einem Blick erfasst werden. Aber schon bei einfachsten Programmen kommen schnell ein paar hundert Zeilen zusammen, die auf mehrere DINA 4 Seiten passen. Wer diese Programme auch später noch verstehen will, benötigt einen geeigneten Kommentar, der die wichtigen Elemente erklärt. Die Technik des Kommentars kann auch beim Testen von Programmen verwendet werden. Teile des Programm-Codes werden auskommentiert und dann beim Programm-Test übersprungen. Die Idle bietet über das Menu sogar die Möglichkeit, gleich ganze Bereiche auszukommentieren: Format → Comment Out Region. Wortschatz: Der Kommentar # Hier folgt der Test print('Das ist nur eine Testausgabe') Der Kommentar wird durch das Rautenzeichen erzeugt ### Hier folgt der Test ##print('Das ist nur eine Testausgabe') Comment Out / Uncomment Der ausgewählte Bereich wird mit zwei zusätzlichen Rautenzeichen versehen. 3.2 Sequenz und Pseudo-Code 3.2.1 Sequentiell – imperativ – prozedural Beispiel: Sequenz Sequenz in Java System.out.println('erste Zeile'); System.out.println('zweite Zeile'); System.out.println(round(10.2345, 2); System.out.println(abs(-10)); Sequenz in Python print('erste Zeile') print('zweite Zeile') print(round(10.2345, 2) print(abs(-10)) Eine Abfolge mehrerer Anweisungen in einem Programm nennen wir Sequenz. Wir können diese Abfolge als Sequenzdiagramm schreiben. Dazu verwenden wir Pseudo-Code (scheinbarer Code), also vereinfachtem Klartext, den man in jede Programmiersprache übersetzen kann. Beispiel: Pseudo-Code Sequenz in Pseudo-Code Programmtext Bildschirmausgabe: '1+1= ' print('1+1= ') Berechne und gib auf dem Bildschirm aus print(1+1) Das Sequenzdiagramm macht deutlich, dass bei diesem Programm ein Befehl auf den anderen folgt. Diese Sequenz (Folge) von Befehlen nennt man vom Lateinischen her imperativ (befehlsorientiert) oder prozedural (fortschreitend). 14 ooP mit Python 3.2.2 Imperatives Programmieren Die Anweisungs-Zeile Die Sequenz wird immer als Folge von Programmzeilen geschrieben. Jede Zeile enthält eine Anweisung oder eine oder mehrere ineinander geschachtelter Funktionen. Jede in sich geschlossene Anweisung gehört in eine Zeile. In vielen Programmiersprachen muss jede vollständige Anweisung zusätzlich mit einem Semikolon ';' abgeschlossen werden. Das ist auch in Python möglich. Der Programm-Code müsste dann nicht für jede Anweisung umgebrochen werden. Das erschwert jedoch das Lesen von Programmen und gilt deshalb als schlechter Programmierstil. Beispiel: Anweisung in Java System.out.println('Text'); System.out.println('Noch ein Text'); Aufgaben zu Kapitel 3 1 Python-Idle-Editor 1) Übernimm die print()-Funktionen aus dem Wortschatz Text-Typen von Kapitel 2 in eine Programmdatei. Speichere sie unter dem Namen oopmp_3.py und führe das Programm mit F5 aus. Rufe das Programm dann unter Windows mit Doppelklick auf – beschreibe, das Problem, das dabei auftaucht. 2) Ergänze die Datei oopmp_3.py um die Zusatzinformationen, die im Wortschatz jeweils in der rechten Spalte stehen. Kommentiere die Zusatzinformationen aus. 3) Schreibe den folgenden Text in eine print()-Funktion. 'An einem lauen Sommerabend fuhr ein verwegener Bursche mit seinem feuerroten Rennwagen behäbig auf der ruhigen Landstraße auf die rotglänzend untergehende Sonne zu.' 4) Ersetze die Adjektive durch geeignete input()-Funktionen! 2 Shebang, Coding und input()-Abschluss 1) Ergänze das Programm um Shebang und Coding und um den input()-Abschluss. Rufe das Programm noch einmal mit F5 und unter Windows mit Doppelklick auf. 2) Sammle mit Hilfe der Sonderzeichentabelle von Windows oder OpenOffice verschiedene Sonderzeichen, setze sie in eine print()-Funktion und lasse sie auf dem Bildschirm ausgeben. 3) Lasse die print()-Funktion deinen Namen mit griechischen Buchstaben schreiben. Das Alphabet dazu findest du auf der Seite info-bei-frenkler.de. 3 Sequenz und Pseudo-Code 1) Erläutere den Zusammenhang zwischen Sequenzdiagramm und dem Programmtext 2) Schreibe den Pseudo-Code für ein Programm, das nacheinander nach deinem Vor- und Nachnamen und nach deiner Klasse fragt und das diese drei Werte nacheinander auf dem Bildschirm ausgibt. Wandle es für in ein Python-Programm um. 15 ooP mit Python Die einfache Variable 4 Die einfache Variable 4.1 Die Variable in der Mathematik Das Variablenkonzept der Informatik unterscheidet sich erheblich von dem der Mathematik. In der Mathematik repräsentiert die Variable jeden möglichen Wert, der an dieser Stelle eingesetzt werden kann. In der Informatik steht die Variable dagegen immer nur für einen einzigen konkreten Wert. Lexikon: Die Variable in der Mathematik a sei eine gerade Zahl zwischen -6 und +6 Welche Werte kann dann a/2 einnehmen? Ergebnismenge: -3, -2, -1, 1, 2, 3 Für den Fall a = 2 gilt das Ergebnis: 1 In der Mathematik bedeutet die Variable jeden beliebigen Wert aus eine bestimmten Definitionsmenge. Das = steht in der Mathematik für den Vergleich 4.2 Die Variable in der Informatik 4.2.1 Die Variable als Box Für die Informatik ist die Variable wie eine Box. Sie kann bestimmte Werte aufnehmen. Wir sagen, dass wir der Variable einen Wert zuweisen. Die einfache Variable kann immer nur einen einzigen Wert enthalten. Weist man ihr einen neuen Wert zu, verschwindet der alte Wert. Wie bekommt man eine Giraffe in den Kühlschrank? Kühlschrank auf – Giraffe rein – Kühlschrank zu! Wie bekommt man einen Elefanten in den Kühlschrank? Kühlschrank auf – Giraffe raus – Elefant rein – Kühlschrank zu! Zuweisung W ert Variable Variable faktor1 = 10 Lexikon: Die Variable in der Informatik a = 1 (Zuweisung – kein Vergleich!) Box ← Wert a |____| ← 1 In der Informatik ist die einfache Variable ein Speicher, der genau einen Wert aufnehmen kann. Das = ist kein Gleichheitszeichen, sondern ordnet den Wert auf der rechten Seite dem Variablen-Speicher auf der linken Seite zu (Pfeilrichtung). 16 ooP mit Python 4.2.2 Die einfache Variable Wertzuweisung Bei der Zuweisung eines Wertes zu einer Variablen steht der Wert rechts der Variablen. Wortschatz: Werte zuweisen und auslesen faktor1 = 10 _faktor2 = 25 a = input('gib einen Wert ein') b = 'Text' so nicht: print = 'schreiben' mult = faktor1 * _faktor2 print(mult) Regeln für die Variable Eine Variable besteht aus beliebigen Namen, der mit einem Buchstaben oder mit einem Unterstrich beginnt. Er darf nicht mit einer Zahl beginnen, kein Leerzeichen enthalten und keinen für die jeweilige Programmiersprache bereits festgelegten Bezeichner. Die in den Variablen eingelagerten Werte werden ausgelesen, wenn sie auf der rechten Seite einer Zuweisung stehen oder wenn sie in einer Funktion als Parameterwert verwendet werden. Manchmal möchte man eine Variablen nur anlegen (deklarieren), ohne ihr einen Wert zuzuweisen, dann setzt man den Wert None („Nichts“) ein. Aber: Taucht der Wert None unerwartet in einem Programm auf, liegt ein Programmierfehler vor. Lexikon: Der Nichts-Wert None a = None Geht nicht: print(None+1) Der Wert 'Nichts' Der Wert kann auch zugewiesen werden Er entspricht nicht dem Wert '0' (wie etwa in der Tabellenkalkulation). Kein Operator kann ihn verändern. Er muss überschrieben werden. Lexikon: Die Variable in Python und in Java a = 'Text' print(a) a = 1234 print(a) a = None Die Variable in Python (schwach getypt) Jede Variable kann jeden Wert aufnehmen. Einer Variablen, die einen Textwert enthält, kann auch ein Zahlenwert oder der Wert' Nichts' zugewiesen werden. String a = 'Text'; system.out.print(a); Integer b = 1234; system.out.print(b); a = null; Die Variable in Java (Stark getypt) Eine Variable kann nur Werte eines festgelegten Wertetyp aufnehmen. Mehrere Variablen gleichen Namens sind nicht erlaubt Der Wert 'Nichts' wird NALL ausgesprochen Lexikon: Variablennamen camelCaseSchreibweise varNeu ='Wert' attrEins = 'Wert' Leerzeichen sind „böse“ Zeichen. CamelCaseSchreibweise (wie Kamel-Höcker) lässt alle Leerzeichen und Umlaute weg. Wortanfänge im Wort werden groß geschrieben Diese Schreibweise verwenden wir für Variablen und später zur Deklaration der Attribute in den Klassen. 17 ooP mit Python 4.2.3 Die einfache Variable Ringtausch Ein einarmiger Roboter soll zwei Gegenstände tauschen. Er kann jedoch immer nur einen dieser Gegenstände halten und jeder Gegenstand darf sich nur an seinem Platz befinden oder am Arm des Roboters. Ohne Ausweichplatz geht das nicht. Ringtausch Das Gleiche gilt für zwei Fahrzeuge, die sich auf einer engen Straße, begegnen. Da muss eines der beiden Fahrzeuge bis zur nächsten Ausweichstelle zurücksetzen, damit beide aneinander vorbei kommen. Das Gleiche geschieht beim Ringtausch: Von zwei Variablen enthält jede einen eigenen Wert. Sollen die beiden Werte getauscht werden, wird eine dritte Variable als Ausweichplatz benötigt. Lexikon: Ringtausch a = b = tmp a = b = 'Text' 'anderer Text' = a b tmp Zum Ringtausch zweier Werte wird eine weitere Variable benötigt. Hier heißt sie tmp für temporär. Aufgaben zu Kapitel 4 1 Die Variable in der Mathematik 1) a sei eine beliebige Zahl zwischen -5 und +5: Welche Werte kann dann a 2 einnehmen? Zeichne den passenden Graph dazu. 2) Für welche Werte ist die folgende Funktion definiert: f(x) = 1/(3-x)? 2 Die Variable anlegen und auslesen 1) Lege für jedes Adjektiv des folgenden Textes eine Variable mit einem sprechenden Namen an. Schreibe den Text mit einer print() -Funktion auf den Bildschirm. Rufe dabei die Werte aus den Variablen im Text auf. 'An einem lauen Sommerabend fuhr ein verwegener Bursche mit seinem feuerroten Rennwagen behäbig auf der ruhigen Landstraße auf die rotglänzend untergehende Sonne zu.' 2) Versehe die Variablen aus Aufgabe 2a mit passenden input()-Anweisungen. 3) Erfinde einen anderen lustigen Text nach diesem Muster und lasse ihn von deinen MitschülerInnen ausfüllen. 3 Ringtausch 1) Programmiere den Ringtausch mit den Gegenständen 'Adler' auf der Variablen Platz_Adler und 'Maus' auf der Variablen Platz_Maus. 2) Organisiere den Tausch mit fünf Variablen (a,b,c,d,e) und ihren Werten (1,2,3,4,5). 18 ooP mit Python Die Sammelvariable 5 Die Sammelvariable 5.1 Warum noch ein Variablen-Typ? Um mehrere zusammengehörende Werte zu speichern, könnten wir für jeden Wert eine Variable anlegen. Damit handeln wir uns aber gleiche mehrere Probleme ein: Zum einen stünde uns nur eine festgelegte Anzahl von Speicherplätzen zur Verfügung. Zum Anderen müssten wir die zusammengehörenden Werte unter verschiedenen Namen aufrufen, weil jeder Wert in einer anderen Variable steckt. Leichter geht es, wenn wir zusammengehörende Werte in einer Sammelvariablen speichern. Beispiel: Eine Sammelvariable statt vieler Variablen anlegen varA = 1 varV = 2 varC = 3 } varSammel = [1,2,3] varSammel[2]= 'wert' Zuweisung 0 1 2 W ert varSammel varSammel 5.2 Informatiker zählen anders Wollen wir nicht die Liste ausgeben, sondern ein bestimmtes Element aus der Liste, müssen wir die Stelle angeben, an der sich das Element befindet. Dabei ist aber zu beachten, dass die Informatik mit dem Wert 0 zu zählen beginnt. So kennen wir 10 einstellige Werte von 0-9, der erste Wert ist die 0, der zehnte Wert ist die 9. Mit zwei Stellen bekommen wir 100 Werte (0-99) und mit drei Stellen 1000 Werte (0-999). Die folgende Liste enthält drei Werte, hat also die Länge 3 und besitzt eine nullte, eine erste und eine zweite Stelle: Länge Werte Stelle 3 'eins' 0 (Stelle Null) 'zwei' 1 (Stelle eins) 'drei' 2 (Stelle zwei) } Liste Wir sagen: Der Wert an der Stelle 0 ist 'eins'. Wortschatz: Einzelne Werte der Listen auslesen a = [1,2,3] b = (1,2,3) Die Liste auslesen Informatiker beginnen mit der 0 zu zählen: print(a[0]) Ergebnis: 1 print(b[1]) Ergebnis: 2 Wir sagen: 'print- a an der Stelle Null' 'print -b an der Stelle Eins' 19 ooP mit Python Die Sammelvariable 5.3 Array, ArrayList und Liste 5.3.1 Listentypen In vielen Programmiersprachen heißen diese Sammelvariablen Array oder ArrayList. Das klassische Array besitzt nur eine begrenzte Anzahl von frei verfügbaren Speicherplätzen. In Python unterscheiden wir Tupel und Liste. Die Liste entspricht der ArrayList in Java, sie kann wie das Tupel, beliebig viele Wert aufnehmen. Das Tupel ist nach seiner Erzeugung jedoch unveränderlich. Die Liste kann in jeder Hinsicht verändert werden. Zum dritten Listentyp, dem Dictionary, das dem Hash in Perl entspricht, finden Profis unter www.python-kurs.eu/dictionaries.php weitere Informationen. Lexikon: Array und ArrayList in Java und Python Java Python Gibt es nicht Integer a = new Integer[4]; c = (1,2,3,4) print(c) Das Tupel gibt es nicht d = 'String' print(d) List<int> a 5.3.2 = new ArrayList<int>(); Array (hier für 4 Werte) Das Tupel (unveränderlich) wird erzeugt und nicht verändert Beachte: Strings sind für Python ebenfalls Tupel Die Liste (beliebig viele Werte) entspricht der ArrayList in Java. Die Liste in Python ist jedoch nicht auf einen bestimmten Wertetyp festgelegt a = [] Punkt-Notation Der Punkt klebt zwei Elemente zusammen. Das Listen-Objekt a und die Methode append() werden also aneinandergehängt. Das bedeutet: Die Methode append() operiert auf der Liste a und fügt ihr einen Wert ein. Objekt . Methode . append('wert') liste=[] liste Lexikon: Punktnotation Java a.add(1); Python a.append(1) a.append('Name') 20 Die Funktion append() fügt der Liste einen Wert hinzu ooP mit Python 5.3.3 Die Sammelvariable Listenumwandlung In Python können Listen problemlos in Tupel verwandelt werden und umgekehrt. Lexikon: Listen umwandeln zahlListe = [1,2,3] zahlTupel = tuple(zahlListe) xx = tuple([2,3,4]) textListe = list('String') print(zahlListe,zahlTupel,xx,textListe) Umwandlungsfunktionen Listen lassen sich in Tupel umwandeln und umgekehrt. In Python sind Strings Tupel. Also lassen auch sie sich in eine Liste verwandeln. 5.4 Der Listendurchlauf 5.4.1 Anweisung und Anweisungs-Block Zu einer einzigen Anweisung können mehrere anschließende Anweisungsschritte gehören. Wir sagen: Die Anweisung erzeugt einen Block von Anweisungen. Dem Laufzeitsystem muss dieser Block bekannt gemacht werden. In den meisten Programmiersprachen geschieht das durch geschweifte Klammern. In Python reicht es, einen Doppelpunkt zu setzen und dann die folgenden Anweisungen um einen Tabulator einzurücken. Die Idle erzeugt den Block nach dem Doppelpunkt automatisch. Lexikon: Der Block Anweisung: erste Anweisung im Block zweite Anweisung im Block Der Block macht deutlich, dass die kommende Folge von Anweisungen zu einleitenden Anweisung gehört. Der Listendurchlauf mit for ist eine solche Anweisung, die einen Block erzwingt. Wortschatz: Listendurchlauf mit for liste = [1,2,3] for e in liste: print(e) Ausgabe: 1 2 3 for e in (1,2): print(e, end='x') Ausgabe 1x2x Listendurchlauf mit for Das for-Statement gibt den Auftrag, durch eine Liste oder einen Tupel zu laufen Beim ersten Durchlauf wird das erste Element genommen, vorläufig in der Variablen e gespeichert und im Block verarbeitet. Beim zweiten Durchlauf ist das zweite Element dran usw. In diesem Fall wird der Wert der Variablen e mit der print()-Funktion ausgegeben. Sind die Folge-Anweisungen für einen Block noch unbekannt, muss in Python der Platz für den Block durch die leere Anweisung pass reserviert werden. Lexikon: Das pass-Statement als Block-Reservierer for e in (1,2,3): pass Das leere pass-Statement reserviert den Block 21 ooP mit Python 5.4.2 Die Sammelvariable Der Listendurchlauf mit for Um eine Liste zu durchlaufen, verwenden wir die Wiederholung mit for. Das for-Statement (for e in liste:) enthält • • • • den Wiederholungsaufruf for (pro) eine Variable mit beliebigen Namen (e oder Element ...) (Beim Listendurchlauf ist die Variable element oder e für 'Element der Liste' üblich) den Zeiger in (aus) und den Namen der Liste (Liste) Die Wiederholung holt pro Durchlauf ein Element aus der Liste, speichert dieses Element in der Variablen e und stellt dieses Element aus der Variablen e dem Programmablauf zur Verfügung, der im Block der Wiederholung notiert ist. 5.4.3 Der Wiederholung mit fester Anzahl Soll ein Programmabschnitt mehrfach durchlaufen werden, wird ein Iterator (Läufer) verwendet. Die Python-Funktion range(ende) ersetzt die Liste und liefert pro Durchlauf einen um +1 erhöhten Wert. Die Variable nennen wir üblicherweise i (für Iterator). Ist i als Variable bereits vergeben, nennen wir sie dem Alphabet folgend j, k usw. Wortschatz: Der Iterator range() # range(anfang,schranke,schritt) # range(anfang,schranke) # range(schranke) a=[1,2,3,4,5,6] for i in range(0, 4, 2): print(a[i]) for i in range(3, 5): print(a[i]) Die range()-Funktion kann mit einem, zwei oder drei Parametern aufgerufen werden. Sie wirft für jeden Listendurchlauf einen von 'anfang ' aufsteigenden Wert aus. Das Zählen endet unterhalb des als schranke übergebenen Wertes. Sind anfang und schritt nicht angegeben, werden die Standardwerte 0 für anfang und 1 für schritt verwendet for i in range(2): print(a[i]) Die Variable i nimmt bei jedem Durchlauf den nächsten Wert vom Iterator range() entgegen # range(anfang > schranke,-schritt) for i in range(3,-1,-1): print(a[i]) Um eine Liste rückwärts einzulesen, muss der Anfangswert größer sein als die Schranke. Die Schrittlänge wird als negativer Wert gesetzt. Die Iterator-Funktion kann auch verwendet werden, um die Werte der Liste und deren Stelle innerhalb der Liste auszugeben. Dazu wird mit der len()-Funktion die Länge der Liste ausgelesen und dann dem Iterator übergeben: for i in range(len(liste)). Lexikon: Länge der Liste liste = [2,4] print(len(liste)) Ergebnis: 2 #Die Schranke kann auch durch #len(liste) erzeugt werden for i in range(len(a)): print('- liste['+ i +']:',a[i]) Die len()-Funktion kann die Länge einer Liste einlesen Sie wird hier für das Auslesen der Liste verwenden. - liste[0]: 2 - liste[1]: 4 22 ooP mit Python 5.5 Die Sammelvariable Listen von Listen Listen können beliebige Werte verwalten und deshalb können sie wiederum Listen oder Listen-von-Listen enthalten. Solche Listen von Listen nennen wir mehrdimensionale Listen. Mit zweidimensionalen Listen können wir Tabellen darstellen. Wortschatz: Listen von Listen – innerer Listendurchlauf kopf = [' ','A','B'] a= ['1','x',2] b=['2','y',4] tabelle =[kopf,a,b] Mehrdimensionale Liste for e in tabelle: for i in range(len(e)): print(e[i], end=' | ') print() Listen von Listen verwerten In den Listendurchlauf durch die Liste 'tabelle' ist ein innerer Listendurchlauf eingebettet. Er durchläuft zusätzlich die in der Liste 'tabelle' eingebetteten Listen 'kopf','a' und 'b' Die Liste 'tabelle' enthält die Listen 'kopf','a' und 'b' 5.6 String und Liste 5.6.1 String-Listen in Strings umwandeln Strings sind für Python unveränderliche Tupel und können deshalb in veränderliche Listen umgewandelt werden. Der umgekehrte Weg ist etwas schwieriger. Dabei kommt die Text-Methode 'text'.join(liste) zum Einsatz. Sie klebt jedes Element einer Liste von Strings an den vorangestellten Text. Besteht der angegebene String aus dem leeren Text, werden nur die in der Liste vorhandenen Textelemente zusammengefügt. Lexikon: String und Liste wortliste = list('String') textliste = ['ich','1','und', ' ','du'] # 'text'.join(liste) text = ''.join(textliste) print(text) String als Liste Der String als unveränderliche Liste von Zeichen. kann in eine veränderliche Liste umgewandelt werden. Listen können am Komma umgebrochen werden String- oder Textwerte aus einer Liste können zu einem neuen String zusammengefügt werden, ohne dabei Speicherprobleme zu erzeugen # Ergebnis: 'ich1und du' 5.6.2 Buchstaben als Ziffern verwenden Für das Dezimalsystem haben wir zehn Ziffernzeichen von 0 bis 9, mit denen alle natürlichen und alle rationalen Zahlen eindeutig beschrieben werden können. In der Informatik verwenden wir aber oft das Hexadezimalsystem, das mit sechzehn Ziffern arbeitet. Die dezimale 10 wird als A, die dezimale 15 mit dem Buchstaben F dargestellt. Mit diesen Zeichen lässt sich aber schlecht rechnen. Statt dessen packt man die Ziffern '0','1' bis 'E','F' in eine Liste und rechnet mit deren Index-Werten: liste.index('F') → 15. 23 ooP mit Python 5.7 Die Sammelvariable Methoden eines Listenobjekts Listen sind Objekte, bei denen wir Werte einfügen, entfernen oder ändern können. Wir können die Elemente, die in dem Listen-Objekt eingelagert sind, sortieren, durchzählen oder umkehren. Wir können herausfinden, an welcher Stelle ein bestimmter Wert steckt oder den Wert an einer bestimmten Stelle ausgeben lassen. Als Objekte verwenden die Listen bestimmte Methoden. Sie werden mit der Punkt-Notation mit dem Namen der Liste verbunden, auf der sie operieren sollen Wortschatz: Listenmethoden Die Funktion ... … und ihre Aufgabe a = [1,2,3] a = [] a = ['x','c','b','x', 1, [1,2,3]] Legt eine Liste mit drei Werten an Überschreibt die Liste mit einer leeren Liste Überschreibt die Liste mit sechs verschiedenen Werten. Der 6.Wert a[5] ist eine Liste mit drei Werten! a.append('y') Hängt einen neuen Wert an das Ende des Liste # Liste.count(Wert) print(a.count('x')) # Ergebnis: 2 Zählt wie oft der gesuchte Wert in der Liste steckt # Liste.index(Wert) print(a.index('x')) # Ergebnis: 0 Gibt die Stelle an, an der der gesuchte Wert zum ersten Mal zu finden ist – hier an der nullten Stelle! # Liste.reverse() a.reverse() print(a) Kehrt die Reihenfolge der Liste um #Liste.sort() a = [3,2,1] a.sort() print(a) # das Folgende gibt eine Fehlermeldung x = [1,'zwei',3] x.sort() Sortiert die Liste vom kleinsten zum größten Wert Vorsicht: Die alte Reihenfolge geht verloren! # Liste.remove(Liste['Stelle']) a.remove(a[3]) a.remove('x') #oder: a.remove(a[a.index('x')]) Entfernt das Element an einer bestimmten Stelle # Liste.insert(Stelle,Wert) a.insert(0,'z') print(a) Fügt in die Liste an der angegebenen Stelle den angegebenen neuen Wert ein. # Liste.pop(Stelle) print(a.pop(3)) # Ergebnis: 'd' print(a) Holt den Wert an einer bestimmten Stelle aus der Liste und entfernt ihn aus der Liste. Gemischte Werte werden nicht sortiert! Soll ein bestimmtes Element entfernt werden, wird entweder dessen Stelle, dessen Inhalt oder dessen IndexWert genannt. 24 ooP mit Python Die Sammelvariable Aufgaben zu Kapitel 5 1 Listen Teste die Beispiele aus dem Wortschatz Listenmethoden (S.24) mit der Idle 2 Tupel und Liste 1) Speichere deinen Vornamen in einer Variable. Wandle den Vornamen in einen Tupel und in eine Liste um und speichere den Tupel und die Liste in unterschiedlichen Variablen mit sprechendem Namen. 2) Printe jede der drei Variablen aus Aufgabe 2a mit Hilfe des Listendurchlaufs aus. Dein Vorname soll zuerst dreimal untereinander ausgegeben werden und dann dreimal in einer Zeile hintereinander. 3) Printe für alle drei Variablen aus Aufgabe 2a nur die ersten und die letzten Buchstaben deines Vornamens aus. 4) Schreibe das Programm mit der input()-Funktion so um, dass ein beliebiger langer Name eingegeben werden kann. Wie greifst du auf den letzten Buchstaben eines Namens zu, wenn du seine Länge nicht kennst? 3 Listen von Listen 1) Printe alle Elemente der Liste liste1 = [1,2,3,4,5] in einer einzigen Zeile aus. 2) Teste und erkläre, weshalb der gleiche Versuch bei Liste2 ein unbefriedigendes Ergebnis bringt: liste2 = [1,2,[3,4],5] 3) Printe mit Hilfe eines inneren Listendurchlaufs alle Werte der folgende geschachtelten Liste einzeln untereinander auf den Bildschirm: liste = [[1,2],[3,4],[5,6]] 4) Teste die folgende geschachtelt Liste z = ['-','1','2'] a = ['A','x','o'] b = ['B','y','w'] q = [a,b] print(q[0][0],q[1][0],'\n', q[0][1],q[1][1],'\n', q[0][2],q[1][2],sep='') - A B 1 x y 2 o w 5) Ändere Liste q in q=[z,a,b]. Passe den print()-Aufruf aus der vorhergehenden Aufgabe so an, dass in der ersten Spalte die Zeilennummern aus Liste z auftauchen. 4 Listenfunktionen 1) Rufe zur Liste a=[1,2,3] die Funktion print(a.remove(a[1])) auf. Rufe danach zwei Mal die Funktion print(a.pop(0)) auf. Erkläre jeweils die Ausgaben. 2) Berechne mit Hilfe der zahlenliste = ['0','1','2','3','4','5','6', '7','8','9','A','B','C','D','E','F'] die Zahl 2365. Erstelle eine Lösung auch mit einer einzigen Wiederholung mit fester Anzahl. 25 ooP mit Python 5 Die Sammelvariable Ringtausch Gegeben ist die Liste a=[1,2,3] 1) Tausche die erste mit der letzten Stelle mit Hilfe eines Ringtausches. 2) Erzeuge das gleiche Ergebnis durch eine geschickte Anwendung der Listenmethoden append(element) und pop(stelle) in einer einzigen Anweisungszeile. 6 Federmäppchen 1) Erstelle eine Liste federmaeppchen, die Bezeichnungen verschiedener Gegenstände aus deinem Federmäppchen enthält. 2) Lasse mit Hilfe der verschiedenen Möglichkeiten des Listendurchlaufes alle Gegenstände deines Federmäppchens ausgeben. Überlege, wie du alle Gegenstände auf einer Zeile ausgeben kannst. 3) Gib dem Nutzer des Programms den Auftrag, einen Gegenstand aus dem Federmäppchen zu holen. Das Programm schreibt danach auf die Konsole, welcher Gegenstand entfernt wurde und an welcher Stelle er sich in der Liste befand. 4) Verändere das Programm so, dass die Gegenstände im Federmäppchen nach dem Listendurchlauf (Aufgabe 6b) und vor dem Nutzerzugriff (Aufgabe 6c) alphabetisch sortiert werden. Wird dann immer noch der richtige Gegenstand entfernt? - Begründung! 7 Klamotten aufräumen Beim Aufräumen sortierst du deine Klamotten (Jeans1, braGeuneShorts, KlassenfahrtTShirt, weißesHemd, blauesHemd, SportShorts, SchulTShirt, JeansGrün, karriertesHemd, FanTShirt) in verschiedene Kisten (T-Shirts, Hemden/Blusen, Hosen, Shorts) und stellst dann alle Kisten in den Schrank. 1) Programmiere dieses Beispiel als geschachtelte Liste und gib alle Klamotten der Reihe nach als Bildschirm-Print aus. 2) Anschließend fällt dir auf, dass du die neue Jeans3 vergessen hast. Füge sie in die richtige Kiste ein. 3) Dann legst du eine Kiste Sportsachen an, nimmst die Sportsachen aus den anderen Kisten, und legst sie in die neue Kiste. 26 ooP mit Python Die Variable im Arbeitsspeicher 6 Die Variable im Arbeitsspeicher 6.1 Die einfache Variable Bei der Deklaration einer Variable wird im Arbeitsspeicher Platz für diese Variable reserviert Bei der Wertzuweisung wird der angegebe Wert auf dem Speicherplatz der Variable abgelegt. Beim Aufruf der Variable wird der Wert von diesem Speicher ausgelesen. 6.2 Die Sammelvariable Bei der Deklaration einer Sammelvariable, wird ebenfalls ein Platz reserviert. Dort liegt jedoch ein Hinweis auf den Anfang einer Reihe von Speicherplätzen. Bei der Wertzuweisung werden die neuen Werte in dieser Reihe von Speicherplätzen abgelegt. Beim Auslesen folgt das Programm dem Hinweis auf die Speicherplätze. Beachte: Die erste Stelle in der Sammelvariable wird als nullte Stelle gezählt! 27 ooP mit Python Die Variable im Arbeitsspeicher 6.3 Unterschiedliches Verhalten der Variablentypen 6.3.1 Call by Value Mit varB = 6 wurde an der Speicherstelle 04 eine neue Variable angelegt. Durch varB = varA bekommt varB den Wert von varA zugewiesen: Er wird aus varB nach varA kopiert (call by value). Die beiden Werte existieren also unabhängig voneinander. Bekommt varA einen neuen Wert zugewiesen, ändert sich der Wert in varB nicht. 6.3.2 Call by Reference Mit varYY = [6,7,8]wurde eine weitere Variable an der Speicherstelle 07 angelegt. Sie enthält eine Referenz auf die Speicherstelle 15. Mit varXX = vaYY wird der Variablen varXX der Hinweis auf die Speicherplätze von varYY übergeben (call by Referenz). Damit gibt es eine „neue Tür“ zu den Werten, die auf den Speicherplätzen 15-17 liegen, währdend die Werte an den Speicherplätzen 10–14 verweist sind. Ändere ich varXX[0], dann greift auch varYY[0] auf diesen geänderten Wert zu. Die verweisten Speicherplätze werden durch die Speicherverwaltung zum Überschreiben freigegeben. Aber Vorsicht: Wie lange diese Werte noch existieren, ist unbekannt! Sie könnten noch versehentlich ausgelesen werden. Deshalb lässt Python wie viele andere Programmiersysteme keinen direkten Zugriff auf den Arbeitsspeicher zu. 6.3.3 Deep Copy Merke: Will ich die Werte aus einer Liste in die andere tatsächlich kopieren, muss ich eine leere Liste anlegen und die Werte aus der anderen Liste in die neue Liste kopieren. Für Profis: Python stellt dafür ein eigenes Modul zur Verfügung (siehe Kap. 10.1 Modul – import): http://www.python-kurs.eu/deep_copy.php 28 ooP mit Python 6.4 Die Variable im Arbeitsspeicher Identität und Gleichheit von Werten Die Berechnung von 2/2 ist für die Mathematik einfach, das Ergebnis ist die natürliche Zahl 1. Python erzeugt bei Bruchrechnungen jedoch immer Floats, also Kommazahlen, deshalb ist das Ergebnis von 2/2 in Python 1.0. Weisen wir das Ergebnis von 2/2 den beiden Variablen a und b zu, so enthalten sie beide den gleichen Wert. Sie liegen aber nicht an der gleichen Speicherstelle; die Variablen a und b sind also gleich (Werte), aber nicht identisch (Speicher). Lexikon: Vergleich auf Gleichheit und Identität >>> a = 2/2 >>> b = 2/2 >>> a==b True >>> a is b False Die beiden Variablen enthalten den gleichen Wert aber sie liegen nicht an der gleichen Speicherstelle == prüft auf Gleichheit der Werte is prüft auf die Identität der Speicherstelle Vorsicht: Python legt einfache Werte wie ganze Zahlen als Objekt an. Die Variablen mit gleichen ganzen Zahlen referenzieren dann den gleichen Speicherplatz Aufgaben zu Kapitel 6 1 Die Variable im Arbeitsspeicher 1) Teste die Wertzuweisung und Wertveränderungen der einfachen Variablen varA und varB: Lege varA mit dem Wert 10 an, lege varB mit dem Wert 6 an. Weise der Variablen varA den Wert von varB zu und teste beide Werte durch ausprinten. Ändere den Wert einer der beiden Variablen und teste das Ergebnis durch erneutes ausprinten. 2) Teste die Wertzuweisungen und Wertveränderungen der Sammelvariablen varXX und varYY: Lege varXX mit den Werten 3,7,4,2,11 an, weise varXX der Sammelvariablen varYY zu und prüfe die beiden Sammelvariablen durch ausprinten. Ändere den Wert varXX[2] auf 5 und printe varYY aus und erkläre das Ergebnis. 3) Lege eine leer Sammelvariable varZZ an und kopiere mit Hilfe des Listendurchlaufes die Werte aus varXX in varZZ. Teste alle drei Variablen durch ausprinten. Ändere dann die erste Stelle von varXX und VarZZ. Teste wieder durch ausprinten. Erkläre das Ergebnis. 4) Lege eine Sammelvariable buechertasche für deine Büchertasche an und fülle sie mit 'Gegenständen' (Strings). Erlaube einem Nutzer des Programms, den Inhalt der Büchertasche mit Hilfe der input()-Funktion zu ändern. 5) Ein Raum besitzt zwei Türen, tuere1 und tuere2, anders kann das Zimmer nicht betreten werden. In diesem Zimmer befinden sich ein Tisch, vier Stühle und ein Regal in dem ein Fernseher und ein DVD-Player stehen (jeweils als String). Programmiere diesen Raum mit den geeigneten Variablen. Begründe deine Lösung für das Regal mit dem Fernseher und dem DVD-Player in einem Programm-Kommentar. 29 ooP mit Python 7 Kontrollstrukturen Kontrollstrukturen Wenn ein Programm auf verschiedene Eingaben unterschiedlich reagieren soll, benötigen wir Kontrollstrukturen wie die Wiederholung mit while und mit for oder die Verzweigung mit if, if-else und if-elif-else. Die Verzweigung mit if-else kennen wir schon aus der Tabellenkalkulation als wenn()-Funktion: wenn(A1=1;“eins“;“nicht eins“) if(A1==1): “eins“; else: “nicht eins“ Die aus anderen Programmiersprachen bekannte Vereinfachung der Mehrfachverzweigung mit Switch und Case, die nur mit Zahlen oder Chars arbeitet, ist in Python nicht implementiert. 7.1 Wahrheitswerte (boolsche Werte) Wahrheitswerte kennen wir ebenfalls aus der Tabellenkalkulation. Wir benötigen sie, um bei Verzweigungen und Wiederholungen den richtigen Weg zu finden. Die beiden möglichen Werte Wahr und Falsch können z.B. als 0 bzw. 1 oder als true bzw. false notiert werden. In Python werden die Wahrheitswerte groß geschrieben: True, False. Für den Vergleich von Werten stellt Python die üblichen Vergleichsoperatoren zur Verfügung. Enthält die Wahrheitsprüfung statt eines Vergleich einen leeren Wert oder den Wert 0, wird False erzeugt; True wird erzeugt, wenn irgend ein Wert ungleich 0 vorhanden ist. Wortschatz: Vergleichsoperatoren == Das einfach Gleichheitszeichen '=' wird für die Zuweisung verwendet. Verglichen wird durch das doppelte '==' is != prüft auf Identät der Objekte Ungleich >, >=, <, <= größer, größer-gleich, kleiner, kleiner-gleich not('Wert') not(0) Die not()-Funktion verwandelt jeden Wahrheitsterm in sein Gegenteil True and True 1==1 and 4/2 == 8/4 Die and-Verknüpfung verlangt, dass auf beiden der Wert True enthalten ist oder erzeugt wird, wenn das Gesamtergebnis True liefern soll False or True 1==2 or 4/2 == 8/4 (), [], {} 'irgendeinwert', ("Wert",0) Bei der or-Verknüpfung reicht es, wenn einer von beiden Seiten den Wert True enthält oder erzeugt drei Beispiele für leere Werte (leere Listen!). Sie stehen den Wert False zwei Beispiele für beliebige Werte, die für den Wert True stehen 30 ooP mit Python Kontrollstrukturen 7.2 Die Wiederholung 7.2.1 Die bedingte Wiederholung Der Fahrer, der in den Kreisel einfährt, verlässt den Kreisel erst dann, wenn er das Signal bekommt: 'ausfahren!' Wenn er Pech hat, kommt das Signal nie und er steckt in einer Endlosschleife! Wir können diesen Ablauf als Struktogramm schreiben: solange nicht(ausfahren!) Wiederholung fahre im Kreis Wortschatz: Die bedingte Wiederholung mit while # 1 while True: print('findet das kein Ende?') print('immer noch nicht!') # 2 while 1 == 2: print('das liest keiner!') # 3 while 1: print('Endlosschleife') break # und doch nicht # 4 antwort = 'nein' while antwort != 'ja': antwort = input('sag ja! ') print('machs nochmal, Sam!') # 5 while input('sag ja: ') != 'ja': print('machs nochmal, Sam!') Die Wiederholung mit while fordert eine Wahheitsprüfung und einen Programmblock. Das Programm wird solange abgearbeitet, bis die Wahrheitsprüfung den Wert False erzeugt. Sind die Wahrheitswerte festgeschraubt, hat man eine Endlosschleife oder einen Programmabschnitt, der nie ausgeführt wird Die Wiederholung mit while sollte deshalb immer so konstruiert werden, dass sie auch vernünftig abgearbeitet werden kann Falls eine Wiederholung auf unendlich gestellt wurde, kann sie mit dem break-Statement abgebrochen werden Die beiden Wiederholung # 4 und # 5 bewirken zwar das Gleiche, aber die Wiederholung # 5 kommt aber ohne zusätzliche Variable aus. Eine bedingte Wiederholung kann alle Programmelemente enthalten, die wir bisher kennen gelernt haben, auch weitere Wiederholungen. Wortschatz: Die geschachtelte Wiederholung 1 while(input('sag ja') != 'ja'): 2 x = 'x' 3 while(x=='x'): 4 x = input('schreibe kein x') 5 for i in range(5): 6 print(i) Wiederholung mit internen Wiederholungen Sooft die äußere Wiederholung (Zeile1) die Eingabe 'ja' belommt, wird zuerst die innere Wiederholung mit while (Zeilen 2-4) solange durchgeführt, bis kein 'x' eingegeben wird, danach die Wiederholung mit for (Zeilen 5 und 6). 31 ooP mit Python 7.2.2 Kontrollstrukturen Wiederholung mit Zähler Mit einem ordentlich eingerichteten Zähler, kann man die einfache Wiederholung in eine Zählschleife umwandeln, die im Normalfall sicher endet. Wortschatz: Die zählende Wiederholung mit while Die Zählschleife benötigt drei Angaben: - Initialisierung: Zähler mit Anfangswert - Endbedingung: Wahheitsprüfung - Inkrement / Dekrement: Der Anfangswert wird hochgezählt oder abgesenkt # aufwärts a = 0 # Initialisierung des Zählers while a<10: # Endbedingung a = a+1 # Zähler = Inkrement # abwärts a = 10 # Initialisierung des Zählers while a>0: # Endbedingung a = a-1 # Zähler = Dekrement print('mich gibt’s 10 Mal') 7.2.3 Die Wahrheitsprüfung fragt, ob der anvisierte Wert schon erreicht wurde; wenn ja, wird die Schleife abgebrochen Die Wiederholung mit fester Anzahl (einfaches for) Das Wiederholung mit Zählen kommt in allen Problemen so häufig vor, dass dafür eine eigene Wiederholungs-Form entworfen wurde. Sie wird häufig als For-Schleife bezeichnet. In Python wird nur die erweiterte Wiederholung mit for verwendet. for(Initialisierung,Endbedingung,Hochzähler) {Block} Hier ein Beispiel in Java for(int i = 0;i < 10; i++){ System.out.println('hallo');} 7.2.4 Die zählende Wiederholung mit for packt die Zählvariable mit der Endbedingung und der Initialisierung in eine Klammer. Dann folgt der Block. Inkrement und Dekrement Das Java-Beispiel für die Wiederholung mit fester Anzahl verwendet eine in vielen Programmiersprachen vorhandene Kurzschreibweise: x++ ist gleichbedeutend mit x = x+1. Diese Erhöhung eines Zahlenwertes um den Wert 1 heißt Inkrement. Das Dekrement (x--) senkt einen Zahlenwert um den Wert 1: x = x-1. Python verwendet statt des klassische Inkrement und Dekrement die vereinfachte Zuweisung. Lexikon: Die vereinfachte Zuweisung Standard a a a a = = = = a a a a + / + Kurzschreibweise 1 1 2 2 oder oder oder oder a a a a += -= /= *= ++a / a++ // --a / a-- 1 1 2 1 Selbstzuweisung einer Variablen Soll eine Variable erhöht werden, muss sie zuerst auf der rechten Seite ausgelesen werden. Dann muss ihr ein passender Wert hinzugefügt werden. Zum Abschluss ersetzt der neue Wert den eben ausgelesen alten Wert. In anderen Programmsprachen gibt es das einfache Inkrement und Dekrement. Steht das Inkrement oder das Dekrement vor der Variablen, wird der Wert der Variablen zuerst verändert und dann eingelesen. Sonst wir die Variable zuerst eingelesen und dann verändert. 32 ooP mit Python 7.2.5 Kontrollstrukturen Erweiterte For-Schleife (foreach) Die erweiterte For-Schleife besitzt keinen Zähler, sondern setzt einen Iterator voraus, etwa eine Liste. Oft wird sie auch foreach-Schleife genannt. Python verwendet die Iterator-Funktion range() als Zähler, um die einfache Wiederholung mit for zu ersetzen. Beispiel: Die Zeile n = int(input('gib eine ganze Zahl ein')) Viele Zeilen mit der erweiterten For-Schleife können viele Zeilen untereinander erzeugt werden. for i in range(n): print('x', end='') 7.2.6 Ganzzahl-Teilung und Modulo-Rechnung Die normale Division erzeugt in der Mathematik ganzahlige Werte oder Brüche: 15/5 → 3 oder 15/7 → 2,142... Manchmal interessieren uns aber nur die ganzzahligen Werte. Wenn etwa 15 Bonbons gleichmäßig auf 5 oder auf 7 Kinder aufgeteilt werden sollen. Der Rest ist unwichtig. 15 Ganzzahlteilung 5 → 5 Rest 0 15 Ganzzahlteilung 7 → 2 Rest 1 In anderen Fällen interressiert uns nur der Rest: Wieviele von 15 Bonbons wanderen bei 5 bzw. bei 7 Kindern zum Schluss in die Resteschachtel? 15 modulo 5 → 5 Rest 0 15 modulo 7 → 2 Rest 1 Lexikon: Ganzzahl-Teilung und Modulo-Rechnung print(15/5) print(15/7) print(15//5) print(15//7) print(15%5) print(15%7) 7.2.7 • Die einfache Teilung erzeugt in Python immer einen Float-Wert • Die Ganzahl-Teilung erzeugt in Python immer einen int-Wert • Python verwendet für die Modulo-Rechnung das Prozent-Zeichen Multiplikation und Divison als Wiederholung Die Multiplikation und die Division sind eigentlich nichts anderes, als eine wiederholte Addition bzw. eine wiederholte Subtraktion. Die Addition verwendet den Zähler, um wiederholt zu addieren. Die Subtraktion verwendet den Zähler, um zu prüfen, wie oft eine Wert von einem anderen abgezogen werden kann. Beispiel: Division dividend = 11 divisor = 2 ganzzahl = 0 while dividend >= divisor: dividend = dividend-divisor ganzzahl = ganzzahl + 1 Die Division ist eine wiederholte Subtraktion. Vorsicht – es kann überraschende Ergebnisse geben: Den einen Ausgabetyp nennen wir Modulo-Rechnung (11%2) , den andern Ganzzahl-Teilung (11//2) 33 ooP mit Python 7.3 Die Verzweigung 7.3.1 Die einfache Verzweigung Kontrollstrukturen Der Fahrer möchte nach Coburg. Eigentlich ist noch genug Benzin im Tank. Wenn der Benzinpreis jedoch günstig ist, wird er tanken – dann, aber nur dann wird er zum Tanken abzweigen. Beispiel: Verzweigung Verzweigung Die Abzweigung wird nur dann betreten, wenn die Wahrheitsprüfung wahr ergibt. Sequenz if benzinPreis == 'günstig': tanken() Sequenz 7.3.2 Die Alternative Das Ziel ist wieder Coburg. Der Tank des Autos ist fast leer. Der Fahrer muss also tanken. Er weiß jedoch, dass auf der Stecke noch eine weitere Tankstelle folgt, bei der er zufällig die Preise kennt. Er wird also nur dann zum Tanken abzweigen, wenn er bei der ersten Tankstelle das Benzin günstiger bekommt, als bei der zweiten. Beispiel: Alternative Eine der beiden Verzweigung wird auf jeden Fall genommen. Eine andere Möglichkeit, z.B. stehen zu bleiben, ist nicht vorgesehen. Sequenz if preisHier < preisDort: tanken() else: weiterfahren() Sequenz Wir können die beiden Abläufe auch als Struktogramm schreiben. Für die einfache Verzweigung wird der Nein-Zweig nicht ausgefüllt. preisHier < preisDort Benzin ist billig ja ja tanken() tanken() 7.3.3 nein weiterfahren() Kombination von Wahrheitswerten Als Fahrradfahrer biegt man natürlich nicht zum Tanken ab und auch dann nicht, wenn der Tank beim Auto voll ist. Für solche Fälle können Wahheitsprüfungen mit and bzw. mit or verbunden werden. Beispiel: if and / or benzinPreis == 'günstig' and fahrzeug != 'Fahrrad': tanken() if tankfuellung == 'leer' or benzinPreis == guenstig: tanken() 34 Beide Bedingungen müssen erfüllt sein Eine von beiden Bedingungen muss erfüllt sein ooP mit Python 7.3.4 Kontrollstrukturen Mehrfachverzweigung und Kombination von Wahheitswerten Ein Autofahrer kommt von Neustadt und möchte nach Neustadt zurückfahren. Im Kreisel hat er vier Möglichkeiten zur Auswahl Beispiel: Mehrfachverzweigung Sequenz ziel = 'Neustadt' if ziel == 'Coburg': nimmAusfahrt(1) elif ziel == 'Sonnefeld': nimmAusfahrt(2) elif ziel == 'Sonneberg': nimmAusfahrt(3) else: nimmAusfahrt(4) Sequenz „Ich will nach Neustadt!“ Falls das gewünschte Ziel bei den ersten drei Ausfahrten nicht gefunden wird, muss der Autofahrer bei der vierten Abzweigung wieder heimfahren. nach nach nach Coburg Sonnefeld Sonneberg 1.Ausfahrt 2.Ausfahrt 3.Ausfahrt sonst 4.Ausfahrt Ein Problem taucht aber auf, wenn der Fahrer nicht nach Coburg will, sondern nach Rödental. Auch da muss er die erste Ausfahrt nehmen. Das geht nur, wenn wir beide Ziele in der ersten Abfrage angeben und mit or verknüpfen. Mehrfachverzweigung Wortschatz: if – elif – else / and / or if wahrheitsprüfung: pass if True: print('ich bin abgezweigt') if True: print('Der Text kommt immer') else: print('Der Text kommt nie') if 1 == 2: print('Der Text kommt nie') elif 1 > 2: print('kommt auch nicht') elif a <= b: print('kommt drauf an') else: print('Auffangstation') if ziel=='Rödental' or ziel=='Coburg': print('nimm die erste Abfahrt') if ziel=='Rödental' and fahrzeug=='Rad': print('nimm den Radweg nach Coburg!') Die Verzweigung wird immer durch den if-Zweig eröffnet. Die leere Anweisung zeigt den Block an Diese einfache Verzweigung wird immer betreten Der Else-Zweig ohne Prüfung ist immer die Auffangstation. Er kann nicht ohne if-Zweig existieren. Der elif-Zweig - kann beliebig oft eingesetzt werden. - fordert eine Wahrheitsprüfung - verlangt den eröffnenden if-Zweig - und den abschließenden else-Zweig elif ist in anderen Programmiersprachen der else-if Bei or reicht es, wenn ein ein einziger Wert wahr ist Bei and müssen beide Werte wahr sein 35 ooP mit Python 7.4 Kontrollstrukturen Geschachtelte Kontrollstrukturen Durch die Kontrollstrukturen kann ein Programm eine dynamische Struktur entwickeln, kein Programmablauf gleicht mehr dem anderen. Wiederholungen und Verzweigung können beliebig oft in einander geschachtelt und beliebig oft mit Sequenzen verbunden werden. Die Möglichkeit mit der Tastatureingabe beliebige Werte einzusetzen, erzeugt einen völlig frei manipulierbaren Programmablauf. Beispiel: Rechteck und Dreieck n = int(input('gib eine ganze Zahl ein')) for i in range(n): for j in range(n): print('x', end='') print() Das Rechteck wird durch eine Reihe von Reihen erzeugt Die Variable j benötigen wir, weil die Variable i schon verwendet wird n = int(input('gib eine ganze Zahl ein')) for i in range(n): for j in range(n-i): print('x', end='') print() Das abfallende Dreieck ist wie ein Rechteck Ihm wird jedoch pro Durchlauf ein Element abgezogen . Das erreichen wir, indem wir das von 0 an wachsende i vom Anfangswert n abziehen. Das steigende Dreieck addiert den steigenden zum Anfangswert n n = int(input('gib eine ganze Zahl ein')) for i in range(n): for j in range(1+i): print('x', end='') print() Wert von Aufgaben zu Kapitel 7 1 Wiederholung in Java Übersetze die einfache Wiederholung aus Java (Kapitel 7.2.3) in ein Python-Programm. 2 Einfache Wiederholung Schreibe ein Ratespiel für Windows. Wenn der Spieler das Programm mit Doppelklick öffnet, wird er nach einer Zahl gefragt. Nur wenn er die richtige Zahl eingibt, endet das Programm. 3 Wiederholung oder Verzweigung Schreibe ein Programm mit zahl=int(input('Zahl')), das mit der Wiederholung while zahl>0 ab dieser Zahl aufsteigend alle Zahlen ausgibt. 1) Kläre: Welcher Bedingung muss erfüllt sein, damit diese Aufgabe kein Problem erzeugt? 2) Ersetze die Wiederholung mit while True und dann durch die Verzweigung mit if zahl>0: und break. Kläre den Unterschied zu Aufgabe 3a. 3) Kläre, ob die gleichen Effekte auch bei der Wiederholung mit for entstehen können. 36 i ooP mit Python Kontrollstrukturen Die Wiederholung mit Zähler und mit fester Anzahl 1) Baue ein Spiel mit Zahlen oder Wörtern, das nach einer bestimmten Anzahl von Runden automatisch abgebrochen wird. Es gibt verschiedene Möglichkeiten! 2) Ergänze die Division aus Kapitel Kapitel 7.2.7 Multiplikation und Divison als Wiederholung) um eine geeignete print()-Funktion und teste sie mit unterschiedlichen Dividenden und Divisoren. Überlege, wie man eine Division mit Nachkommastellen erstellen könnte. 3) Schreibe eine Multiplikation mit Hilfe der Wiederholung mit for, die nur mit der Addition arbeitet. 4 Verzweigung Bestimme den Verzweigungstyp der folgenden Aussagen: 1) 'Wenn im Kino ein guter Film läuft, gehe ich ins Kino, sonst gehe ich spazieren' 2) 'Ich ehe spazieren. Wenn der Bäcker offen hat, bringe ich ein Brot mit.' 3) 'Wenn Hans kommt, gehen wir alle miteinander essen, wenn nicht, können wir beide (wenn du willst) ins Kino gehen oder etwas anderes unternehmen. Sonst bleibe ich zuhause.' 4) Erkläre mit eigenen Worten anhand der Aufgaben 3a-c, weshalb wir die einfache Verzweigung von der Alternative unterscheiden. 5) Erläutere die unterschiedliche Wirkung der beiden Programmfragmente: e1) e2) x = 'Test' while input('test:')!='test': print('kein Test') print(x) 5 x = 'Test' if input('test: ')!='test': print('kein Test') print(x) Die Mehrfachverzweigung 1) Erweitere das Programm aus Kapitel 7.3.4 Mehrfachverzweigung und Kombination von Wahheitswerten so, dass der Fahrer nach Coburg fahren muss, wenn es am Kreisel kein Schild 'nach Muenchen' gibt. 2) Überlege und begründe: Ist es möglich, dass der Fahrer bei der Mehrfachverzweigung nie wieder aus dem Kreisel herauskommt? 6 Modulo-Rechnung 1) Überlege, mit welche Berechnung jede Zahl darauf geprüft werden kann, ob sie gerade ist. Schreibe ein Programm, das jede mit int(input()) eingegebene Zahl auf gerade / ungerade prüft und je nach Ergebniss 'ist gerade' oder 'ist ungerade' ausgibt. 2) Eine Ampel schaltet von rot auf rot-gelb, auf grün, auf gelb, auf rot. Die vier Möglichkeiten sind mit 0 bis 3 durchnummeriert. Ein interner Zähler zählt ohne Ende von 0 aufwärts. Mit welcher Teilung kannst du dafür sorgen, dass er nach dem Wert 3 wieder den Wert 0 ausgibt, egal wie weit er bereits gezählt hat. Schreibe das Programm. 37 ooP mit Python Einfache Algorithmen 8 Einfache Algorithmen 8.1 Algorithmus Die Bezeichnung Algorithmus für eine bestimmte Gruppe von Rechenvorschriften ist von Mohammed alChwarizmi abgeleitet, dem Namen eines iranische Wissenschaftler aus dem 9.Jahrhundert. In der lateinischen Übersetzung seines Mathematik-Lehrbuchs Rechnen mit indischen Ziffern wurde sein Name mit Algorismi wiedergegeben. Im Mittelalter glaubte man, er sei ein griechischer Meister der Zahlen (gr. arithmos) gewesen mit dem Namen Algus. So entstand der Begriff Algorithmus. Abbildung 1: Denkmal für al-Chwarizmi in Chiwa (Usbekistan) Für die Informatik sind die Algorithmen wichtig: Alles, was als Algorithmus beschrieben werden kann, kann auch als Programm notiert werden und dann (prinzipiell) mit einen Rechner berechnet werden. Ein Algorithmus lässt sich mit vier Merkmalen beschreiben: • • • • Er ist eine Verarbeitungsvorschrift (ausführbar) Er ist als Programmtext in sich abgeschlossen (endlich) Er erreicht sein Ziel in einer endlichen Anzahl von Schritten (terminiert) Er führt bei gleichen Bedingungen immer zum gleichen Ergebnis (determiniert) 8.2 Beispiele 8.2.1 Der größte gemeinsame Teiler (euklidischer Algorithmus) In einer Mathematikaufgabe kommen manchmal seltsame Brüche vor, z.B.: 323 247 - 133 95 + 456 152 * 133 56 =? Sie schauen auf den ersten Blick sehr unangenehm aus - wenn man nur den richtigen Teiler wüsste! Dafür gibt es einen uralten Algorithmus. Die älteste Beschreibung dafür stammt von dem griechischen Mathematiker Euklid. Die folgende Beschreibung lässt sich leicht in ein Programm umwandeln: Nimm zwei Zahlen. Solange beide Zahlen ungleich sind, ziehe die kleinere von der größeren ab und ersetze die größere durch das Ergebnis. Sind beide Werte gleich, ist der größte gemeinsame Teiler der beiden Zahlen gefunden. 38 ooP mit Python Einfache Algorithmen 8.2.2 Bubble Sort Das Märchen vom Aschenputtel erzählt schon kleinen Kindern von der eher unangenehmen Aufgaben des Sortierens. Glücklich, wer fleißige Helfer findet. Zum Glück brauchen wir keine Tauben, um beliebige Werte zu sortieren. Es gibt viele Sortier-Algorithmen. Manche arbeiten besonders schnell, andere sind leichter zu verstehen. Ein langsamer, aber gut beschreibbarer Sortieralgorithmus ist Bubble Sort. Er lässt die Werte Schritt Abbildung 2: Aschenputtel ruft die Tauben für Schritt wie Luftblasen im Glas aufsteigen, bis sie in (Ludwig Richter) der richtigen Reihenfolge liegen. 1. Nimm den ersten Wert aus eine Reihe von Werten. Vergleiche ihn mit seinem Nachfolger. Stehen sie nicht in der richtigen Reihenfolge, sollen beide Werte ihre Plätze tauschen. 2. Mache das Gleiche mit dem zweiten Wert bis zum vorletzten Wert in dieser Reihe (Beachte: Dabei kann der ständig getauschte erste Wert immer wieder dabei sein!). 3. Lasse die Schrittfolge 1 bis 2 dann mit dem zweiten, danach mit dem dritten usw. bis zum vorletzten Wert beginnen. 4. Zum Abschluss stehen alle Werte sicher in der richtigen Reihenfolge Aufgaben zu Kapitel 8 1 ggt 1) Wandle die Beschreibung des ggt in Pseudocode um und programmiere den Algotithmus mit Python. 2 Bubble Sort 1) Spiele mit deinen Mitschülern sortieren: nach Alter, Schuhgröße oder was euch gerade einfällt. Kläre, weshalb ihr wesentliche schneller sotieren könnt, als der Bubblesort-Algorithmus. 2) Spiele den Bubblesort-Algorithmus mit verdeckten Karten. Dabei dürfen gleichzeitig nur zwei nebeneinander liegende Karten aufgedeckt sein. Kläre, weshalb diese Spielweise eher der Arbeit eines Computers entspricht. 3) Wandle die Beschreibung des Bublbe Sort in Pseudocode um und programmiere ihn mit Python. Verwende dazu eine veränderliche Liste. 39 ooP mit Python Strukturiertes Programmieren 9 Strukturiertes Programmieren 9.1 Blackbox-Prinzip Funktionen haben wir bereits in der Tabellenkalkulation verwendet. Nach dem Blackbox-Prinzip haben wir ihre interne Arbeit aber nicht betrachtet. Nachdem wir die Prinzipien des imperativen Programmierens kennen, können wir ab sofort selbst Funktionen schreiben, indem wir einfache Sequenzen oder Algorithmen in Funktionen verwandeln. Wir geben der Funktion einen Namen und ergänzen ihn um eine Parameterliste. Das ist der Funktionskopf. Dann fügen wir die Sequenz bzw. den Algorithmus unter dem Funktionskopf als Block ein. Ab sofort kann dieses Programm mit einem einzigen Funktionsaufruf zum Laufen gebracht werden. def funktion(beliebige,Menge,an,Parametern): Funktionskopf Programm Block: Funktionskörper funktion(pro,Parameter,ein,Wert) Funktionsaufruf Funktionen helfen uns, doppelten Code und damit typische Fehlerquellen zu vermeiden. Die Dreiecke im Beispiel unten (vgl. Kap. 7.4 Geschachtelte Kontrollstrukturen S.36) können nun beliebig oft mit unterschiedlichen Argumenten aufgerufen werden. Die Programmstruktur ändert sich nicht mehr, wohl aber die Ausgabe. Im Beispiel-Programm Dreieck ersetzt jeder Aufruf der 11-zeiligen Funktion dreieckschreiben() ein Programm, das aus vier Zeilen besteht. Ein Programm mit vier Funktionsaufrufen benötigt also 15 Code-Zeilen und damit bereits eine Zeile weniger als ein Programm, das ohne Funktionen das Gleiche erreichen soll Beispiel: Dreieck # Funktion def dreieckSchreiben(groesse,zeichen,richtung=1): if richtung >= 0: for i in range(groesse): for j in range(groesse-i): print(zeichen, end='') print() else: for i in range(groesse): for j in range(1+i): print(zeichen, end='') print() # Aufruf dreieckSchreiben(3,'z',-1) dreieckSchreiben(3,'#') 40 Definition der Funktion mit drei Parametern, der dritte Parameter ist vorbelegt. Das (auf der Spitze stehende) Dreieck wird standardmäßig ausgeführt Das (auf der Basis stehende) Dreieck wird ausgeführt, wenn das dritte Argument (richtung) negativ ist. ooP mit Python 9.2 Strukturiertes Programmieren Funktion ohne Rückgabewert (Prozedur) Argument def potenz(zahl): x = zahl**zahl print(x) Das Argument wird verarbeitet potenz(2) Aufruf der Funktion Haben wir ein prozedurales Programm oder einen Programmteil in eine Funktion gepackt, die vereinfacht aufrufen können, sprechen wir auch von einer Prozedur. 9.2.1 Die verdeckte Variable Eine Prozedur empfängt Werte von außerhalb über die Parameterliste und kann sie verändern. Sobald die Prozedur beendet wird, verschwinden auch die geänderten Werte: Die Variable innerhalb der Prozedur ist also für den Rest des Programms verschattet. Außerhalb der Prozedur varA = 10 def prozedur(varA): varA = varA+20 print(varA) prozedur(varA) print(varA) Beispiel: Was innerhalb der Prozedur geschieht, außerhalb nicht sichtbar und nicht wirksam ist Außerhalb der Prozedur Verschattung # Färben ← Parameterliste def faerben(auto): vor dem Färben: schwarz print('vor dem Färben',auto) auto = 'weiss' print('nach dem Färben', farbe) nach dem Färben: weiss auto='rot' print('vor Prozeduraufruf', auto) faerben(auto) print('nach Prozeduraufruf', auto) vor dem Aufruf schwarz Funktionsaufruf nach dem Aufruf schwarz Innerhalb der Prozedur wird der Wert verändert und neu aufgerufen. Außerhalb der Prozedur bleibt der Wert unverändert Funktion ohne Rückgabewert (1): Nur der kopierte Wert wird bearbeitet (2 / 3). Danach wird der Wert vergessen. Das Programm arbeitet mit dem unveränderten Wert weiter (4). 41 ooP mit Python Strukturiertes Programmieren 9.3 Funktion mit Rückgabewert 9.3.1 Das return-statement Wollen wir, dass die geänderten Werte auch im weiteren Programmablauf gelten sollen, müssen wir einen Ausgang zur Verfügung stellen: das return-Statement. Sobald das return-Statement erreicht wird, wird die Arbeit der Funktion abgebrochen. Der Wert, der zum return-Statement gehört, wird an die aufrufende Stelle zurückgegeben. Wir können Funktionen also als Werterzeuger verwenden und deshalb auf der rechten Seite einer Zuweisung einsetzen. Beispiel: Funktion # Färben def faerben(farbe): print('vor dem Färben',farbe) farbe = 'weiß' print('nach dem Färben', farbe) return farbe ← Eingang: farbe vor dem färben neue Farbe wird zugewiesen nach dem färben: weiß Ergebnis ausgeben vor Modulaufruf: schwarz farbe = 'schwarz' print('vor dem Modulaufruf', farbe) Ergebnis zuweisen farbe = faerben('weiß') print('nach dem Modulaufruf', farbe) nach Modulaufruf: weiß 9.3.2 return-Statement Der Parameter ist die Türe, über die Werte aufgenommen werden Das return-Statement schickt den Wert aus tank an die aufrufende Funktion Eine Zuweisung holt den neu erzeugten Wert der Farbe in die alte Variable Vergleich zur Tabellenkalkulation Die Funktion mit Rückgabewert entspricht der in der Tabellenkalkulation verwendeten Funktion. Dort wird die Funktion auf der Eingabeebene eingesetzt. Das '=' markiert in der Tabellenkalkulation, dass der erzeugte Wert an die Ausgabeebene übergeben wird. Dieses Verhalten entspricht der einfachen Zuweisung. Argument def potenz(zahl): x = zahl**zahl return x Das Argument wird verarbeitet } Der Rückgabewert ersetzt den Aufruf der Funktion variable = potenz(2) Aufruf der Funktion 42 ooP mit Python Beispiel: Strukturiertes Programmieren Funktionen ohne Rückgabewert def testProdzedur1(): print('Prozedur ohne Parameter') Funktionskopf mit leerer Parameterliste Der Funktionskörper bzw. Funktionsbblock enthält die auszuführenden Anweisungen def nameSchreiben(name, info): print(info, name) Funktion mit Parameter, der im Block verwendet wird # Prozeduraufrufe testProzedur1() nameSchreiben('erster','Test') Der Aufruf der Funktion bzw. Prozedur geschieht durch den Aufruf des Funktionsnamens Eine Funktion, die einen Parameter verlangt, muss auch mit einem Argument versorgt werden. Wortschatz: Funktionen Funktion ohne Rückgabewert man kann auch sagen: Funktion mit leerem Rückgabewert def prozedur(parameter): <Programm-Block> Ausgabe durch die Anweisung im Programm-Block print(prozedur(meinPar)) Ausgabe: None def funktion(parameter): <Programm-Block> return wert Ausgabe des return-Wertes Funktion mit Rückgabewert Beachte: Der return-Wert darf auch eine Liste sein print(funktion(meinPar)) Ausgabe: wert Die Funktion mit Rückgabewert ist ein Wert-Erzeuger. Der von ihr ausgegebene Wert kann weiterverarbeitet werden. 9.3.3 Ausblick: Funktionen und Methoden Funktionen ohne Rückgabewert und Funktionen mit Rückgabewert tauchen bei den Methoden in der objektorientierten Programmierung wieder auf: Methoden ohne Rückgabewert bekommen dann als setMethoden die Aufgabe Werte zu speichern, Methoden mit Rückgabewert werden dann als getMethode zur Ausgabe von Werten verwendet. 9.3.4 Benannte Parameter Bei den Parametern handelt es sich um Variablen, die solange gelten, wie die Funktion arbeitet. Eigentlich müssen sie genau in der Reihenfolge befüllt werden, wie sie in der Funktion deklariert sind. Werden die Parameter allerdings mit ihrem Namen aufgerufen, muss die Reihenfolge nicht mehr eingehalten werden Lexikon: Benannte Parameter def drucken(text1, text2) : print(text1,text2) Die beiden Parameter sind in ihrer Reihenfolge festgelegt und werden vom print()-Befehl ausgewertet. drucken(text2='zweiter Text', text1='erster Text') Weil die Parameter benannt sind, kann die Reihenfolge umgekehrt werden 43 ooP mit Python 9.3.5 Strukturiertes Programmieren Überladene Parameter Jedem Parameter einer Funktion muss beim Aufruf der Funktion auch ein Argument übergeben werden. Wird jedoch ein Paramter mit einem Wert vorbelegt ( par = 'Wert'), dann arbeitet die Funktion mit dem vorgegeben Wert, solange diesem Parameter beim Aufruf der Funktion kein Argument zugewiesen wurde. Lexikon: Überladene Parameter def drucken(a, b='nix') : print(a,b) Der überladene Parameter muss immer zum Schluss deklariert werden drucken('x') drucken('y','da steht doch was') Die Funktion drucken kann mit einem oder mit zwei Parametern aufgerufen werden 9.3.6 Listen als Parameter Manche Funktionen erwarten Listen als Parameter. Übergibt der Nutzer jedoch nur einen einfachen Wert, verweigert die Funktion ihren Dienst und zwingt das Programm zum Abbruch. Um dieses Problem zu umgehen, gibt es für Python eine besondere Form des Parameters. Sie stellt aus allen Werten, die ihr übergeben werden, eine unveränderliche Liste zusammen. Diese Form des Parameters wird mit einem Stern markiert. Wortschatz: Listen als Parameter def listenFunktion1(listPar): for e in listPar: print(e,end=',') return 'fertig' # Aufruf: listenFunktion1([2,3,4,5]) # Ergebnis: 2,3,4,5 Diese Funktion will hier eine Liste abarbeiten. Problem: Wurde keine Liste, sondern eine Zahl übergeben, stürzt die Funktion ab. def listenFunktion2(par,*listPar,pr): print(par) print(pr) return listPar # Aufruf print(listenFunktion2(1,2,3,4,5,pr=6)) # Ergebnis: 1 6 (2, 3, 4, 5) Der Listenparameter wird mit einem * markiert. Ihm können beliebig viele Werte zugewiesen werden. def listenFunktion3(*listPar): listPar = list(listPar) listPar.reverse() print(listPar) # Aufruf listenFunktion3(2,3,4,5) # Ergebnis [5, 4, 3, 2] Folgt auf den Listenparameter ein weiterer Parameter, muss er bei der Übergabe der Argumente ausdrücklich als benannter Parameter aufgerufen werden, sonst kann ihm kein Wert zugewiesen werden. Sollen die Werte aus dem Listen-Parameter weiter bearbeitet werden, muss die unveränderliche Liste mit Hilfe der list()-Funktion in eine veränderliche Liste umgewandelt werden. 44 ooP mit Python Strukturiertes Programmieren 9.4 Für Profis: Funktionen der Tabellenkalkulation 9.4.1 Einfache Verschlüsselung Die einfache Caesar-Verschlüsselung ersetzt jedes Zeichen des Alphabets durch ein um einen bestimmten Wert versetztes anderes Zeichen des Alphabets. So wird aus dem A durch die Funktion caesar(A,3) der Buchstabe D, aus W würde wiederum A. Um dieses Verschlüsselung zu programmieren, könnten wir die Zeichen des Alphabets in eine Liste alphabet packen. Auf das Zeichen A würden wir normalerweise mit alphabet[0+Verschiebewert] zugreifen. Um bei dem Zeichen W (also dem Zeichen alphabet[22]) wieder auf das A (also alphabet[0]) zu kommen, muss man den Verschiebewert mit Modulo 26 (für die 26 Zeichen des Alphabets) teilen. Alternativ könnte man auf die ASCII-Werte zugreifen: print(chr(ord('A')+3)). Wird jedoch ord(Zeichen)+Verschiebewert größer als 90 (ord(90)=> Z), müsste der Wert 26 abgezogen werden. Übrigens: In der Tabellenkalkulation ist die Caesar-Verschlüsselung als rot(13) zu finden. Sie rotiert das Alphabet um den Wert 13. 9.4.2 Uhrzeit, Datum, Geld und Kommazahlen Unsere Uhrzeit richtet sich ja nicht nach dem bei uns gebräuchlichen Dezimalsystem. Die Sekunden und Minuten erzeugen erst beim Wert 60 den Übergang zur neuen Minute bzw. zur neuen Stunde. Bei den Stunden geschieht der Übergang zum neuen Tag bereits beim Wert 24. Der Monatsübergang ist abhängig von der Länge des jeweiligen Monats, im Februar sogar davon, ob gerade Schaltjahr ist oder nicht. Eine Funktion neueUhrzeitAusgeben(jetzt,dauer) müsste also bei den Parametern jetzt und dauer eine Liste mit den Argumenten jahr, monat, tag, stunde, minute, sekunde erwarten. Die Berechnung beginnt bei den Sekunden. Falls die Addition der Sekunden der Wert 59 übersteigt, wird der Minutenwert um den Wert 1 gehoben und das Sekundenergebnis um 60 gesenkt. Entsprechend werden dann die Minuten, Stunden, Tage, Monate und Jahre berechnet und dann als Liste ausgegeben. Das gleiche Prinzip kann vereinfacht für jede Währung angewendet werden. Bei der Funktion neueGeldmengeAusgeben(alterWert,aenderung) werden dann die Euro- und Cent-Beträge getrennt behandelt. Mit der Funktion ganzzahlUndRestDivision(dividend,divisor) die eine Liste [ganzzahl,rest] ausgibt, können wir Kommazahlen bis zu eine bestimmten Länge nach dem Komma berechnen. Ist der Rest größer als 0, wird dieser Rest mit dem Faktor 10 multipliziert und der Funktion wieder übergeben. Das ganzzahlige Ergebnis wird dann mit 100AnzahlDerVersuche dividiert und zum Gesamtergebnis addiert. 45 ooP mit Python 9.5 Strukturiertes Programmieren Für Profis: Ausnahmebehandlung Laufzeitfehler sind nie zu vermeiden, deshalb bietet jede Programmiersprache die Möglichkeit der Fehlerbehandlung an. Wenn ein Python-Programm abstürzt, gibt es eine Fehlermeldung aus. Diese Fehlermeldung kann man abfangen und das Programm so weiterlaufen lassen, als sei kein Fehler aufgetreten. Genaueres finden Interessierte im Netz: http://www.python-kurs.eu/ausnahmebehandlung.php Aufgaben zu Kapitel 9 1 Funktionen ohne Rückgabewert 1) Eine Ampel bekommt vier Werte übergeben (rot, rot-gelb, gelb, grün). Sie schaltet danach die Ampel. - Verwende einmal vier Parameter und einmal einen einzigen Listenparameter. 2) Eine Ampel erwartet einen Zahlenparameter (2 bzw. 4). Danach erzeugt sie eine Fußgängerampel mit den Werten rot und grün bzw. eine Ampel für den Autoverkehr. 3) Lege zwei Funktionen Sommerabend1 und Sommerabend2 an, die den folgenden Text bearbeiten: An einem lauen Sommerabend fuhr ein verwegener Bursche mit seinem feuerroten Rennwagen behäbig auf der ruhigen Landstraße auf die rotglänzend untergehende Sonne zu. Die Funktion Sommerabend1 verlangt die Übergabe von sechs Argumenten, die dann als Adjektiv-Variablen verwendet werden. Die Funktion Sommerabend2 verlangt die Übergabe einer Liste mit beliebig vielen Adjektiven, die dann als Adjektiv-Variablen verwendet werden. 2 Mit oder ohne Rückgabewert? 1) Entscheide - Welche der folgenden Aufgaben würdest du als Funktion mit Rückgabewert entwerfen, welche als Funktion ohne Rückgabewert? Begründe deine Entscheidung. Reinigung der Wäsche, Ware ausliefern, eine Nachricht schreiben, Informationen auf dem Bildschirm ausgeben, telefonieren, Kleidung färben, Einkaufen gehen 2) Schreibe zwei Funktionen einkaufen1 und einkaufen2, die erste mit Rückgabewert, die zweite ohne Rückgabewert. Übergib beiden Funktionen eine Einkaufsliste. Die Funktionen wählen zufällig viele Produkte aus (Kapitel 10.2.1 Zufallswerte). Das Ergebnis soll auf den Bildschirm ausgegeben werden. 3 Algorithmus-Funktionen 1) Packe den ggT (Aufgaben zu Kapitel 8) in eine Funktion mit dem Funktionskopf ggT_berechnen(wert_1,wert_2). Sie schreibt das Ergebnis auf den Bildschirm. 2) Packe den Bubblesort-Algorithmus (Aufgaben zu Kapitel 8) in eine Funktion bubbleSort(liste). Sie erwartet eine unsortierte Liste als Parameter und gibt eine sortierte Liste an die aufrufende Stelle zurück. 46 ooP mit Python Modulares Programmieren 10 Modulares Programmieren 10.1 Modul – import Die Beispielprogramme, mit denen wir bisher gearbeitet haben, hatten nur ganz wenige Zeilen an Programm-Code. Die freie Bürosoftware LibreOffice dagegen besteht aus mehreren Millionen Codezeilen. Um so große Programme pflegen zu können, werden auf verschiedene Dateien (Module) aufgeteilt. So besteht etwa LibreOffice aus mehreren tausend Modulen. Auch in Python können wir unsere Programme in Module zerlegen und als Programmteile anderen Programmen zur Verfügung stellen. Das Modul muss nur noch durch eine entsprechende Anweisung importiert werden: import modul. Mehrere zu importierende Module trennen wir mit Komma voreinander: import modul1, modul2. Beispiel: Programm importieren Datei: ichLassePrinten.py Datei: ichPrinte.py print('Das kommt raus') import ichLassePrinten Import → Der Aufruf ichPrinte.py erzeugt die Ausgabe: Das kommt raus Wir können unsere eigenen Programme in Module zerlegen. Aber es gibt auch fertige Module, die wir importieren können. So können wir unsere Python-Programme um interessante Funktionen erweitern. Viele dieser Module sind für Python schon vorbereitet. Eine vollständige (englische) Informationen zu diesen Modulen ist im Web zu finden: http://docs.python.org/3/ → Library Referenz Die Python-IDLE führt über den Menü-Eintrag help → Python Docs (F1) ebenfalls auf diese Seite. 10.2 Lexikon wichtiger Python-Module 10.2.1 Zufallswerte import random Das Modul Zufallszahlen stellt verschiedene Funktionen zur Verfügung random.randint(2,11) random.choice([1,2,3,'a','b','c']) random.shuffle([1,2,3,'a','b','c']) random.random() - erzeugt eine zufällige ganze Zahl von 2 bis 11 - wählt aus einer vorgegebenen Menge eine zufälligen Wert - schüttelt die Werte in einer Liste durcheinander - gibt eine Float zwischen 0.0 und 1.0 aus 47 ooP mit Python 10.2.2 Zugriff auf das Betriebssystem (platform, os)* import platform platform.system() Ergebnis: Linux, Windows oder Darwin (für den Mac) import os os.system('cmd') unter Windows os.system('clr') unter Windows os.system('mkdir testOrdner') os.system('shutdown -r -t 0') 10.2.3 Modulares Programmieren Das Betriebssystem erkennen abhängig vom erkannten Betriebssystem können bestimmte Befehle ausgeführt werden, die nur auf diesem Betriebssystem zur Verfügung stehen Die Betriebssystem-Funktionen - öffnet die Befehlseingabe - löscht die Einträge auf der Konsole - legt einen Ordner an schaltet unter Windows den Rechner aus -t 0 steht für: nach 0 Sekunden Zugriff auf das Laufzeitsystem (sys)* import sys datei = open('dateiname', 'w') datei = open('dateiname', 'r') datei = open('dateiname', 'a') Das Laufzeitsystem ist unter anderem für das Anlegen von Dateien zuständig legt eine neue Datei unter dem Namen an öffnet eine Datei nur zum lesen öffnet eine Datei, um Daten anzuhängen datei = opend('datei','r') inhalt= datei.readlines() datei.close() eine geöffnete Datei wird zeilenweise ausgelesen und in der Variablen inhalt als Liste gespeichert Danach wird die Datei wieder geschlossen datei = opend('datei','w') for e in inhalt: datei.write(str(e)) datei.close() Eine Datei wird neue angelegt oder überschrieben. Die Elemente aus der Variablen inhalt werden in einen String umgewandelt und zeilenweise in die Datei geschrieben. 10.2.4 Das Zeitsystem (time)* time.localtime() Zugriff auf die Systemzeit des Rechners erzeugt einen Tupel mit Informationen über die regionale Zeit, die auf dem Rechner eingestellt ist. print(time.localtime()[0]) Schreibt das Jahr auf den Bildschirm time.localtime()[1] Monat time.localtime()[2] Tag time.localtime()[3] Stunde time.localtime()[4] Minute time.localtime()[5] Sekunde time.localtime()[6] Wochentag time.localtime()[7] Tag im Jahr time.localtime()[8] ist Sommerzeit (nein → 0, ja ->1) – nur, wenn sie beim Rechner korrekt eingestellt ist import time sec = 1 time.sleep(sec) Lässt den Prozess warten (hier eine Sekunde) 48 ooP mit Python Modulares Programmieren Aufgaben zu Kapitel 10 1 Module verwenden 1) Lege ein Programm mit dem folgenden Text an: An einem lauen Sommerabend fuhr ein verwegener Bursche mit seinem feuerroten Rennwagen behäbig auf der ruhigen Landstraße auf die rotglänzend untergehende Sonne zu. Lege eine Liste mit Adjektiven an und ersetze die markierten Adjektive im Text durch zufällige ausgewählte Adjektive aus der Adjektiv-Liste. Rufe das Programm mehrfach auf und erkläre die Unterschiede. 2) Programmiere ein Spiel, bei dem zufällig erzeugte Zahlen erraten werden sollen. Ist der Wert erraten, wird der Rechner nach so vielen Sekunden heruntergefahren, wie Versuche nötig waren, um den Wert zu erraten. 3) Erstelle ein Zufallspasswort. Verwende eine Liste für Vokale, eine Liste für Konsonanten und eine Liste für Ziffern (nicht Zahlen! - warum?). Das Passwort mit 6 Buchstaben wird aus den Listen zusammengestellt. Sorge dafür, dass auch die Reihenfolge der Buchstaben zufällig ist. Füge dann die Zeichen aus der Liste zu einem String zusammen. 4) Programmiere: Eine Ampel schaltet von rot auf rot-gelb, auf grün, auf gelb, auf rot. Die vier Lichtmöglichkeiten sind mit 0 bis 3 durchnummeriert. Ein interner Zähler zählt mit modulo-3 und zeigt nach je einer Sekunde den neuen Ampelwert. 5) Datei-Bombe: Erzeuge eine Endlosschleife, in der du eine Datei immer wieder speicherst. Du kannst z.B. den Dateinamen als Zähler verwenden. Aber große Vorsicht: Das darfst du wirklich nur dann tun, wenn du sicher weißt, wie du den Rechner danach wieder retten kannst! 49 ooP mit Python Klassen und ihre Objekte 11 Klassen und ihre Objekte 11.1 Programmier-Prinzipien 11.1.1 Maschinenabhängig Programmieren wird vom Maschinencode aufwärts immer einfacher und zugleich immer komplexer. Der Assembler vereinfacht den Maschinencode durch halbwegs merkbare (mnemnonische) Befehle. Programmme in Assembler- und Maschinencode können nur auf dem Prozessortyp eingesetzt werden, für den sie geschrieben wurden. 11.1.2 Problemorientiert Imperatives und strukturiertes Programmieren löst das Programm von der Maschine. Jedes Programm, jede Problemlösung, kann prinzipiell auf allen Rechnern laufen. Das strukturierte Programmieren vereinfacht die Arbeit, indem Teile des Programmcodes zur Wiederverwendung in Funktionen ausgelagert werden. 11.1.3 Objektorientiert Die Objektorientierung setzt auf dem Prinzip des Strukturierens auf, arbeitet aber nicht problemorientiert; denn mit der Verwendung einer Klasse wird gleich eine ganze Gruppe gleichartiger Teilprobleme lösbar. Eine komplexe Aufgabe wird durch das Zusammenspiel vieler Objekte bearbeitet. objektorientiertes Programmieren Löst in einem Programm eine Klasse von Problemen Strukturiertes Programmieren wiederverwenden von Programm-Code Zuweisungen Sprünge Lesbar - Die Sprünge werden zu Verzweigungen und Wiederholungen Zuweisungen, Verzweigungen und Wiederholungen werden ausgelagert in Module und Funktionen Für jede Teilaufgabe wird ein Objekt mit eigenen Werten (Attribute) erzeugt Objekte kommunizieren über Methoden miteinander (Funktionen <=> Methoden) 50 System Maschinencode Nullen und Einsen an einen Prozessor gebunden Problem Assembler halbwegs lesbar Maschine Imperatives Programmieren nicht an einen Prozessor gebunden ooP mit Python 11.1.4 • • • • • Klassen und ihre Objekte Vorteile der Objektorientierung Ein Aufgabe wird in viele Teilaufgaben zerlegt. Deshalb können verschiedene Programmierer unabhängig voneinander an einem Projekt arbeiten – Prinzip des verteilten Arbeitens. Schlecht programmierte Klassen können ohne Aufwand durch neu programmierte Klassen ersetzt werden, sofern diese Klassen die klar definierten Schnittstellen verwenden. Wie eine Klasse intern arbeitet spielt keine Rolle – Prinzip der Datenkapselung. Fertige Programme können ohne genauere Kenntnis ihrer Programmierung in unterschiedlichen Zusammenhängen zu unterschiedlichen Zwecken verwendet werden – Prinzip der Wiederverwendung (Programm-Bibliothek) . Allgemeine Aufgaben werden durch allgemein gehaltenen Klassen gelöst. Sie werden zur Lösung konkreterer Probleme durch Ergänzungsklassen erweitert – Prinzip der Vererbung. Die Dynamik der Objekte und die Kommunikation zwischen den Objekten macht die Simulation komplexer Systeme möglich. 11.2 Klassen und Objekte 11.2.1 Reales Objekt und Programm-Objekt Wer auf einen VW-Golf mit dem Kennzeichen AB-CD 1234 seinen Führerschein gemacht hat, kann auch einen VW-Golf mit dem Kennzeichen BA-DC 2143 fahren oder einen Renault mit dem Kennzeichen CO-DE 526, einen VW-Käfer, einen Mercedes oder einen Rolls-Royce. Wenn also reale Objekte Strukturen und Abläufe haben, die einander sehr ähnlich sind, fassen wir sie zur einer Klasse zusammen. In der Informatik betrachten wir die Aufgabe in der umgekehrten Richtung. Die informatische Klasse PKW erzeugt beliebig viele VW-Golf-, Käfer-, Mercedes-, Renault- oder Rolls-Royce-Objekte und legt sie im Arbeitsspeicher ab. Mit diesen Objekten können dann unterschiedliche Simulationen durchgeführt werden 11.2.2 Objekte handeln nach innen und nach außen Objekte können als handelnde Subjekte wie als empfangende Objekte beschrieben werden. Wenn sie von einer Klasse erzeugt und einer Variablen zugewiesen werden, bekommen sie deshalb immer ein Nomen als Variablennamen. Objekte können mit den Methoden, die ihnen ihre Klasse zur Verfügung stellt, Handlungen durchführen. Grammatikalisch betrachtet sind Methoden also Verben. Deshalb bekommen Methoden immer eine Verbform als Bezeichner. Bei den Attributen handelt es sich immer um die Eigenschaften eines Objektes, sie beschreiben, in welchem Zustand sich ein Objekt gerade befindet. Soll ein Attribut Objekte speichern, bekommt es als Bezeichner ein Nomen, andernfalls ein Adjektiv oder ein Adverb oder was sonst gerade passt. 51 ooP mit Python Klassen und ihre Objekte 11.3 Mit Objekten arbeiten: Liste und Turtle 11.3.1 Listen als Objekte Listen haben wir bereits als Objekte mit ihren Methoden kennengelernt (Kap. 5.7 Methoden eines Listenobjekts). Allerdings haben wir Listenobjekte nur durch eine Aufzählung erzeugt, indem wir eine bestimmte Menge an Werten als Liste einer Variablen zugewiesen haben: b = [1,2,3]. Das konnte auch die leere Menge sein: a = []. Diese Listen können wir objektorientiert erzeugen, indem wir die Klasse list aufrufen und debei die Werte als Parameter übergeben: a = list([1,2,3] oder a = list(). 11.3.2 Die Turtle Bevor wir selbst Klassen schreiben, können wir eine Gruppe von Klassen verwenden, die uns von der Python-Bibliothek zur Verfügung gestellt wird, wie etwa die Turtle. Die Idee der Turtle-Graphik stammt aus der Programmiersprache Logo, die Seymour Papert in den 1960er Jahren als kindgerechte Anfängersprache entwickelt hat. Die Turtle, also eine Schildkröte, zieht eine Spur hinter sich her, die auf den Bildschirm gezeichnet wird. Auf diese Weise ist es möglich, mathemathische Funktionen mit geringem Aufwand graphisch darzustellen. Gregor Lingl hat die Idee für Python umgesetzt und das Python-Modul Turtle entwickelt. Hilfreiches dazu ist in seinem Buch Python für Kids zu finden. Wird nur die Standard-Turtle auf der Konsole ausgeführt, können die unten aufgelisteten Befehle ohne Bezg zu einem Objekt aufgerufen werden. Andernfalls muss ein Objekt erzeugt und einer Variablen zugewiesen werden. Beispiel: Spirale >>>from turtle import* Import des Turtle-Moduls >>>spirale = Turtle() >>>punkt = Turtle() Die Variablen spirale und punkt bekommen je ein neu erzeugtes TurtleObjekt zugewiesen >>>punkt.shape('circle') Das Punkt-Objekt wird als Punkt (circle) gezeichnet >>>punkt.write('Hi, ich bin da (der punkt)', font=('Times New Roman',10)) >>>for i in range(52): spirale.circle(10+i,45) Erschließe den Rest des Programms! Schreibe es auf die Konsole und lass es laufen. Die folgende Befehlsreferenz hilft dir zu verstehen, was dabei passiert. >>>spirale.write('Aber ich bin jetzt hier', '(die spirale)',font=('Arial',10)) Auf der Konsole kannst, wie in den letzten beiden Befehlen auch mit einem nicht-benannten Objekt der StandardTurtle arbeiten. >>>pencolor('red') >>>forward(100) 52 ooP mit Python Beispiel: Klassen und ihre Objekte Von der Linie zum Dreieck, Rechteck und Kreis # Dreieck / Rechteck # farbiges Rechteck # zwei Rechtecke from turtle import* from turtle import* from turtle import* # main-Bereich # main-Bereich def linie = Turtle() for i in range(3): linie.forward(100) linie.left(120) bildschirm = Screen() bildschirm.title('Titel') line = Turtle() line.begin_fill() line.color((0,1,0),'red4') #line.color('green','red4') #line.pencolor('red1') line.pensize(4) for i in range(4): line.forward(100) line.right(90) line.end_fill() linie.right(90) linie.up() linie.forward(50) linie.down() for i in range(4): linie.forward(100) linie.left(90) maleRechteck(n, linienFarbTupel, fuellFarbTupel, hoehe,seite) : n.penup() n.goto(hoehe,seite) n.pendown() begin_fill() n.color( linienFarbTupel, fuellFarbTupel) n.pensize(4) for i in range(4): n.forward(100) n.right(90) end_fill() # main-Bereich punkt = Turtle() tester = Turtle() maleRechteck(punkt, (1,0,0),(0,0,1),200,150) maleRechteck(tester, (0,0,0), (0,1,1), 20,15) Lexikon: Die Python-Turtle Turtle-Aktionen t = Turtle() Erzeugt eine Turtle, die in der Variablen t gespeichert ist t.forward(40) die Turtle t zeichnet 40 Pixel vorwärts t.back(30) die Turtle t bewegt sich zeichnend rückwärts t.goto(100,200) t geht eine Linie zeichnend zum Punkt (100|200) t.penup() Stift hoch: Die Turtle t bewegt sich ohne zu zeichnen t.pendown() Stift ab: Die Turtle t zeichnet wieder t.pensize(3) setzt die Linienbreite der Turtle t auf 3 Pixel t.circle(30) t zeichnet einen Kreis mit dem Radius 30 Pixel t.circle(-20,90) t zeichnet einen rechtsdrehenden Kreis mit einem Radius von 20 Pixel und einem Winkel von 90° t.write('Hallo Welt',font=('Arial', 16)) t schreibt in Schriftart Arial und Schriftgröße 16 t.dot(3,'red') t zeichnet einen Punkt mit dem Durchmesser 3 Pixel und der Farbe rot an der aktuellen Position t.right(90) t die Turtle dreht sich um 90° weiter nach rechts t.left(60) die Turtle t dreht sich um 60° weiter nach links t.setheading(270) 0 → Ost / 90 → Nord / 180 → West setzt die Richtung der Turtle t auf 270° (Süd), unabhängig von der vorher eingestellten Richtung 53 ooP mit Python Klassen und ihre Objekte Turtle-Farben t.color('red','yellow') die Linienfarbe ist rot, die Hintergrundfarbe ist gelb Die Farben lassen sich auch durch einen Tupel von drei Zahlwerten für rot, grün und blau erzeugen. Gültig sind die Werte 0 und 1, sowie alle Kommawerte dazwischen: color((1,0,0),(1,1,0)) ist gleichbedeutend zu color('red','yellow'). Kommawerte führen zu abgetönten Farben t.fillcolor('blue') Setzt die Hintergrundfarbe wird auf blau t.pencolor((0,0,1)) Setzt die Stiftfarbe auf Blau end_fill() Beendet die Füll-Aktion begin_fill() Leitet bei füllbaren Formen die Füll-Aktion ein Turtle-Formen t.shape('turtle') legt das Aussehen der Turtle fest ('arrow', 'turtle', 'circle', 'square', 'triangle', 'classic') t.hideturtle() Turtle wird unsichtbar t.showturtle() Turtle wird sichtbar stempel=[] stempel.append(t.stamp()) stempelt den Umriss der Turtle an der aktuellen Position mit stamp() und speichert die Stempelnummer in stempel t.clearstamp(stempel[0]) Löscht den Stempel an stempel[0] t.clearstamps() t.clearstamps(zahl) #positiveZahl t.clearstamps(zahl) #negativeZahl lösche alle, die ersten, bzw. die letzten der Stempel. Wenn die Klammer leer ist, werden alle gelöscht. Wenn zahl > 0 werden die ersten zahl Stempel, andernfalls die letzten zahl Stempel gelöscht Turtle-Positionen t.position() gibt die (x|y)-Koordinaten der Turtle zurück t.xcor() gibt die x-Koordinate der Turtle als Float zurück t.ycor() gibt die y-Koordinate der Turtle als Float zurück t.heading() gibt den Winkel der Turtle zurück t.distance(x,y) gibt den Abstand der Turtle zum Punkt (x|y) zurück Grafikbildschirm f = Screen() Weist das Grafikfenster der Variablen 'f' zu f.title("meine Turtle-Graphik") Titelzeile im Grafikfenster 'f' f.setup(width=400, height=300, startx=0, starty=0) Das Grafikfenster 'f' wird auf die angegebenen Werte gesetzt f.bye() schließt das Grafikfenster 'f' t.clear() f.clear() löscht die Zeichnung der Turtle t löscht alles, was dem Grafikfenst 'f' gehört f.clearscreen() löscht den Grafikbildschirm des Fenster 'f' f.reset() Löscht den Bildschirm,setzt die Turtle wieder an den Anfang und setzt alle Variablen auf die Anfangs-Werte 54 ooP mit Python Klassen und ihre Objekte Turtle-Steuerung t.speed(wert) Setzt die Geschwindigkeit der Turtle. Mögliche Werte: 0 → Die Turtle springt zum Zielpunkt 1 – 10 (=max) → von langsam bis schnell tracer(False) … Befehlsfolge tracer(True) Die Aktionen der Befehlsfolge werden unter Verzicht auf die Turtle-Spur auf den Bildschirm geschrieben. Standardmäßig steht der Wert auf tracer(True). Wird tracer(False) gesetzt, muss am Ende der Wert auf tracer(True) zurückgesetzt werden. Turtle-Ereignisse t.onclick(meineFunktion,btn=1) Bei Klick mit der linken Maustaste wird die angegebene Funktion ausgeführt. Die mittlere Maustaste hat die Nummer 2, die rechte Maustaste die Nummer 3. t.listen() Setzt den Fokus auf das Graphikfenster t.onkeypress(meineFunktion,key='e') Die Funktion meineFunktion wird bei Drücken der Taste 'e' aufgerufen. Diese Funktion setzt voraus, dass zuvor t.listen() aufgerufen wurde. mainloop() Ruft die Ereignisschleife auf. Er muss in einem Programm mit Ereignisaufrufen immer als letzte Anweisung notiert werden. Aufgaben zu Kapitel 11 Die Turtle testen 1) Teste die Beispiele zur Turtle 2) Erzeuge eine Turtle kreis als Kreis und gib seine Koordinaten mit print() aus. 3) Erzeuge eine nicht sichtbare Turtle nix, die trotzdem das Haus des Nikolaus schreibt 4) Erzeuge eine nicht sichtbare Turtle stern, die einen Stern mit sechs gelben Strahlen schreibt, die im gleichen Winkel auseinander liegen und der in der Mitte einen roten Punkt hat 5) Schreibe die rechtwinkligen Dreiecke a,b,c,d mit unterschiedlichen Linien und Füllfarben und füge sie mit der Spitze zusammen. 6) Gestalte eine Landschaft mit Bergen, Wiesen, Äckern, Häusern – deiner Fantasie sind keine Grenzen gesetzt – Mache dir die Aufgabe leichter, indem du für die einzelnen Elemente je eine Funktion schreibst 7) Erweitere die Landschaft mit Elementen, die sich bewegen. Verwende dazu deine Kenntnisse über die Kontrollstrukturen 8) Für Matheprofis: Lasse von der Turtle die Regel a 2+b2=c2 zeichnen. Importiere dazu zusätzlich das Modul math, es stellt die Methoden math.sqrt(x), math.sin(x) zur Verfügung; math.hypot(x,y) berechnet die Hypotenuse direkt. Mit math.degrees(math.asin(sin(x))) bekommst du den passenden Winkel für die Funktionen left(winkel) und right(winkel) 55 ooP mit Python Selbst erstellte Klassen und ihre Objekte 12 Selbst erstellte Klassen und ihre Objekte 12.1 Die einfache Klasse 12.1.1 Klasse, Konstruktor und Objekt Klassen erzeugen Objekte, die jeweils einen Gegenstand, ein Lebewesen oder eine Idee repräsentieren. Zuständig für das Erzeugen ist der Konstruktor. Er initialisiert die von der Klasse zu erzeugenden Objekte, das heißt, er belegt ihre Attribute mit Anfangswerten und weist den Objekten den Speicherplatz zu. Die von der Klasse erzeugten Objekte können wiederum auf die in der Klasse deklarierten Methoden zugreifen. Die einfachste Klasse ist die leere Klasse ohne Attribute und Methoden. Ihre Objekte können nichts und enthalten keine Werte, sie reservieren aber Arbeitsspeicher. Sie repräsentieren gewissermaßen einen beliebigen Gegenstand. Dieses scheinbar sinnlose Gebilde erweist sich später im Rahmen der Vererbung (Kap. 12.2 Vererbung) als durchaus nützlich. Wortschatz: Klassen deklarieren – Objekte erzeugen Java class Test { Test(){} } Python class Test: def __init__(self): pass Klassenkopf Konstruktor hier mit leerem Block In Java heißt der Konstruktor wie die Klasse. Als Methode führt er eine Parameterliste. In Python heißt er __init__(self) Im Parameter self steckt der Speicherplatz des Objektes Für die leere Klasse braucht man den Konstruktor nicht zu notieren: class TestLeer{ } class TestLeer: pass leere Klasse Ein Objekt wird erzeugt, indem man die Klasse (eigentlich den Konstruktor der Klasse) mit einer Parameterliste aufruft. Dabei müssen so viele Argumente übergeben werden, wie es der Konstruktor der Klasse in seiner Parameterliste verlangt. Beim Aufruf der leeren Klasse bleibt die Parameterliste leer: meinTest = Test() Ein Objekt der Klasse Test wird erzeugt der Variablen meinTest zugewiesen. Java ist stark getypt. Deshalb darf die Variable meinTest nur Objekte der Klasse Test() aufnehmen Test meinTest = new Test(); 56 ooP mit Python 12.1.2 Selbst erstellte Klassen und ihre Objekte Das Objekt Objekte sind reservierte Bereiche im Arbeitsspeicher. Zugriff auf das Objekt hat nur, wer dessen Speicherplatz kennt. Dafür gibt es mehrere Möglichkeiten: a) Das neu erzeugte Objekt wurde einer Variablen zugewiesen. Der Name des Objektes ist dann der Variablenname; wir verwenden dafür immer ein Nomen (Subjekt bzw. Objekt im Satz!) Soll das Objekt auch unter einem anderen Namen bekannt sein, wird die Referenz der Objektvariablen einer anderen Variablen zugewiesen (zweiterName = objektName). b) Ein anonymes Objekt wird keiner Variablen zugewiesen, sondern unmittelbar nach seiner Erzeugung verwendet und dann wieder verworfen. Sobald der Müllsammler (Garbage Collector) auf ein solches Objekt stößt, wirft er es weg – das heißt: Er markiert dessen Speicherplatz als freigegeben. c) Jedes Python-Objekt kann mit der Variablen self1 auf seinen eigenen Speicherplatz zugreifen. Diese Variable entspricht dem Pronomen ich bzw. selbst. Wortschatz: Der Zugriff auf das Objekt meinTest = Test() print(meinTest) Ergebnis: <__main__.Test object at 0xb62b54ac> Die Variable meinTest weist auf den Speicherplatz des Objektes. Sie enthält also eine Referenz auf das gespeicherte Objekt print(Test()) Ergebnis: <__main__.Test object at 0xb62b56ec> Die print()-Funktion verarbeitet ein anonymes Objekt neuerName = meinTest Das Objekt meinTest bekommt einen weiteren Namen 12.1.3 Methoden und Funktionen Methoden stellen die Handlungsmöglichkeiten der Objekte dar. In ihrem Aufbau und in ihren Aufgaben ähneln sie den Funktionen der strukturierten Programmierung. Sie besitzen ebenfalls eine Parameterliste und können Werte verarbeiten bzw. Werte ausgeben. Beispiel: Klasse mit einfachsten Methoden class Test2: def __init__(self): pass Eine einfache Klasse Es besitzt kein Attribut, denn der Block des Konstruktors ist leer def getSpeicherplatz(self): return self Die erste Methode gibt den Speicherplatz des Objektes zurück def speicherplatzAufBildschirm(self): print(self) Die zweite Methode schreibt den Speicherplatz auf den Bildschirm def schreibWas(self,irgendwas): print('Ausgabe: ',irgendwas) Die dritte Methode schreibt das übergebene Argument auf den Bildschirm 1 In allen anderen objektorientierten Programmiersprache heißt diese Variable this 57 ooP mit Python 12.1.4 Selbst erstellte Klassen und ihre Objekte Methoden geben Werte aus Methoden haben die gleiche Struktur wie Funktionen und können auch wie Funktionen einen bestimmten Algorithmus kapseln und einen entsprechenden Wert zurückgeben. So gibt es funktionale Objekte, deren Methoden Standardwerte berechnen, Zufallswerte erzeugen, Sortierfunktionen ausüben oder den ggT zur Verfügung stellen. In der Hauptsache jedoch bilden Methoden die Schnittstelle eines Objektes nach außen. Objekte kommunizieren über diese Methoden. Ein Objekt verwendet seine getMethoden (Methoden mit Rückgabewert), wenn es von einem anderen Objekt gefragt wird, in welchem Zustand es sich Objekt befindet. Wortschatz: getMethoden geben Auskunft class Test3: def __init__(self): Diese getMethode verlangt die Übergabe eines pass def getAnderenSpeicher(self, andObj): Objektes und fragt das andere Objekt nach dessen Speicherplatz. return andObj.getSpeicher() def getSpeicherplatz(self): return self Das andere Objekt antwortet, indem es seine eigene Methode getSpeicherplatz() aufrufen lässt. def quadrat(zahl): return zahl*zahl Diese Methode gibt das Quadrat zu einer Zahl zurück ta = Test3() tb = Test3() print(ta.getAnderenSpeicher(tb)) 12.1.5 Der letzte print-Befehl kann so übersetzt werden: Das Objekt ta gibt den Speicher des Objektes tb aus print( Subjekt . Prädikat ( Objekt ) ) Objekte initialisieren - Attribute Ein Objekt speichert in den Attributen Werte. Diese Werte stellen seinen Zustand dar. Als Werte können Zahlen, Texte, Listenobjekte oder Objekte gespeichert werden. Die Struktur der Attribute wird in der Klasse festgelegt. Wortschatz: Objekte initialisieren Java Python In Java muss ein Attribut deklariert werden, bevor es vom Konstruktor initialisiert wird class Test { String name //Deklaration Test(String name){ this.name=name;} } class Test: def __init__(self,name): self.name = name Test tstr= new Test('Ich') tstr = Test('Ich') 58 Python erledigt das in einem Aufwasch im Konstruktor Sieht der Konstruktor weitere Parameter vor, müssen beim Erzeugen des Objekts passende Argumente übergeben werden. ooP mit Python 12.1.6 Selbst erstellte Klassen und ihre Objekte Geheimnisprinzip Ein weiterer Unterschied der objektorientierten Programmierung zur strukturierten Programmierung ist das durchgehende Geheimnisprinzip. Wir kennen es im Ansatz schon von den Funktionen he (Kap. 9.2.1 Die verdeckte Variable). Für die Kommunikation von Objekten wurde dieses Prinzip jedoch erweitert. Reale wie informatische Objekte besitzen private Eigenschaften auf die kein fremdes Objekt direkt zugreifen darf. Seltener gibt es öffentliche Eigenschaften, deren Werte von jedem anderen verändert werden darf. Die meisten objektorientierten Sprachen markieren diesen Unterschied mit den Modifikatoren private und public. In Python sind alle Attribute standardmäßig auf public eingestellt, privat-Attribute werden mit dem doppelten Unterstrich markiert. Beispiel: Kasse und Geldbeutel Das Kassen-Objekt bzw. die Kassererin sollte keinen direkten Zugriff auf das Attribut Geldmenge im Geldbeutel-Objekt des Käufers haben; es wird auf private gesetzt. Der Geldbeutel stellt der Kasse nur die Methode bezahlen(preis) als Schnittstelle zur Verfügung. Wie die Klasse Geldbeutel das Bezahlen umsetzt, geht die Kasse nichts an. Für die Kasse ist nur der returnWert der Geldbeutel-Methode bezahlen(preis)wichtig: Gibt er (passendes) Bargeld heraus, einen Gutschein oder eine Karte? Genauso darf das Geldbeutel-Objekt bzw. darf der Kunde keinen direkten Zugriff auf das Attribut bargeldbestand in der Kasse haben; es wird ebenfalls auf private gesetzt. Auch die Klasse Kasse stellt dafür die Methode bezahlen(preis) zur Verfügung. Wie die Klasse Kasse intern mit den verschiedenen Bezahlmöglichkeiten umgeht, geht wiederum den Geldbeutel nichts an. Wortschatz: Die Modifikatoren private und public Java public class Test { private int zahl public Test(int zahl){ this.zahl=zahl; } Python Java verwendet die Modifikatoren public def __init__(self,zahl): und private class Test: self.__zahl = zahl public int getZahl(){ return this.zahl } def getZahlself): return self.__zahl public void setZahl(int zahl){ this.zahl = zahl } def setZahl(self,zahl): self.__zahl = zahl Python verwendet den doppelten Unterstrich als private-Modifikator } # Hauptprogramm tester = Test(1) info = tester.getZahl() 59 nur Objekte der gleichen Klassse dürfen auf das mit als private gesetzte Attribut zugreifen. ooP mit Python 12.1.7 Selbst erstellte Klassen und ihre Objekte Methoden, die Werte setzen Die Attributwerte eines Objektes werden beim Erzeugen des Objekte mit den Werten vorbelegt, die dem Konstruktor bekannt sind. Sei es, dass sie als Argumente übergeben wurden, sei es, dass sie im Konstruktior fest verankert sind. Nachdem sich aber der Zustand eines Objektes in den Attributwerten ausdrückt, müssen diese Attributwerte auch verändert werden können, wenn das Objekt in einen neuen Zustand wechseln soll. Dazu dienen die setMethoden. Zu jedem Attribut gehört mindestens eine setMethode. Normalerweise benötigt sie einen Parameter, der den neuen Wert in Empfang nimmt. In der setMethode kann aber auch ein Algorithmus angelegt sein, der den alten oder den neu übergebenen Attributwert nach bestimmten Regeln bzw. unter unterschiedlichen Bedingungen unterschiedlich verändert. Eventuell kann der Algorithmus auch mehrere Argumente verlangen, dann bekommt die setMethode entsprechend viele Parameter. Soll die Methode ein anderes Objekt veranlassen, seinen Zustand zu verändern, muss die Referenz auf dieses Objekt als Argument übergeben werden. Dann ruft die setMethode das andere Objekt auf und weist es an, seinerseits eine bestimmte setMethode anzuwenden. Auch dabei können Argumente übergeben werden. Wortschatz: setMethoden speichern Werte Class Test: def __init__(self,zahl): self.__zahl = zahl def setZahl(self,neueZahl): self.__zahl = neueZahl def andererSetZahl(self,anderer,neueZahl): anderer.setZahl(neueZahl) def plusEins(self): if self.__zahl<10: self.__zahl += 1 def andererPlusEins(self,anderer): anderer.plusEins() # Hauptprogramm testA = Test(1) testB = Test(1) testA.setZahl(3) testB.plusEins() testB.andererPlusEins(TestA) testA.andererSetZahl(TestB,10) 60 ooP mit Python 12.1.8 Selbst erstellte Klassen und ihre Objekte Klassen- und Objektdiagramm Das Erzeugen von Objekten durch eine Klasse lässt sich als Diagramm zeichnen. Im Objektdiagramm werden nur die Attribute notiert, nicht die Methoden der Klasse. Leuchte emL: Leuchte emL = Leuchte() int licht licht = 0 anAusSchalten() Lok emma: Lok emma = Lok('EMMA',emL) str name int geschwindigkeit Leuchte leuchte name = 'EMMA' geschwindigkeit = 0 leuchte = emL int fahren(int geschw) lichtSchalten() 12.1.9 _1414 = Lok('1414') ... Kommunikation von Objekten - Sequenzdiagramm Zunächst empfängt Lok _1414 vom Bahnhof mit grünem Signal die Erlaubnis auszufahren. Lok _1414 fährt daraufhin mit Geschwindigkeit 10 los und verlässt den Bereich des Bahnhofs Anschließend bekommt Lok Emma vom Bahnhof mit grünem Signal die Erlaubnis einzufahren. Sie tut das mit Geschwindigkeit 10. Sie fährt bis zum Signal am Ende des Bahnhofs und wartet dort wieder auf ein grü nes Signal. Außerdem gibt sie ihrer Leuchte den Befehl zu schalten, was die Leuchte auch tut und zurückmel det, dass sie aus ist. Dieser Ablauf lässt sich als Sequenzdiagramm zeichnen. Die breiten senkrechten Linien stehen für die Aktivitäts- oder Lebenslinie eines Objektes. Die durchgezogenen Pfeile stehen für eine Methode, die gestrichelten Pfeile für die Rückkehr der Methode. Solange die Methode nicht zum Ausgangs-Objekt zurückgekehrt ist, ist das andere Objekt aktiv. nec: Bahnhof emma: Lok emL: Leuchte _1414: Lok signal(grün) fahren(10) signal(grün) signalFragen() fahren(10) rot fahren(0) lichtSchalten() aus 61 anAusSchalten() ooP mit Python 12.1.10 Selbst erstellte Klassen und ihre Objekte Zustand und Zustandsübergang Ändert ein Objekt mit Hilfe einer Methode seinen Zustand, sprechen wir von einem Zustandsübergang. Für jedes Objekt gibt es eine begrenzte Mengen an Zustandsübergängen. Sie sind durch die in der Klasse deklarierten Methoden beschrieben. Diese Zustandsübergänge können als Grafik dargestellt werden. Beispiel: Zustandsübergänge des Signals und der Lok Signal schalten Signal: rot stillle Signal: grün gen aus n lege l l i t s Lok Geschwindigkeit: 0 Licht: aus fahren: 10 fahren: 0 schalten Geschwindigkeit: 0 Licht: an Geschwindigkeit:10 Licht: aus schalten fahren: 10 fahren: 0 Geschwindigkeit: 10 Licht: an Das Signal benötigt nur eine einzige Methode schalten() für die Lichtsignaländerung. Allerdings gelten für jeden Zustandsübergang andere Regeln. Die Regeln sind von dem Zustand abhängig, in dem sich das Signal gerade befindet. Es gibt genau einen definierten Anfangszustand (schwarzer Punkt), aus dem heraus das Signal in den Zustand rot geschaltet wird. Der (etwas künstliche) Zustand aus wird über die Aktion still-legen() erreicht. Damit hört das Signal endgültig auf zu existieren Diese Aktion ist aus jedem Zustand heraus möglich. Als Endzustand ist er mit einem doppelten Ring versehen. Aus ihm kommt das Signal nicht mehr in einen aktiven Zustand zurück. Die Lok besitzt die Methoden fahren(wert) und schalten(). Sie können vier unterschiedliche Zustände erzeugen. Für die Lok ist kein Endzustand definiert. Bei einem geänderten Modell mit den Methoden einfahren() und ausfahren() könnte sie aus Sicht des Bahnhofs durch ausfahren() in den Endzustand geraten. 62 ooP mit Python 12.1.11 Selbst erstellte Klassen und ihre Objekte has_a-Beziehung Sind Objekte in den Attributen gespeichert, handelt es sich um ein zusammengesetztes Objekte, wie etwa Emma, die Duplolok. Wir sprechen von einer einer has_a-Beziehung. So besitzt die Lok Emma als zusammengesetztes Objekt ein Fahrgestell, eine Führerhaus, einen Schlot, einen Kessel und eine Schürze. Das Führerhaus und das Fahrgestell sind wiederum zusammengesetzte Objekte. Die has_a-Beziehung können wir graphisch als Aggregat darstellen. Die als Attribut abhängigen Objekte werden mit einer Raute markiert. Von den abhängigen Objekten können wieder Objekte abhängen. Beispiel: Emma, die Duplolok class Fahrgestell: def __init__(self,farbe): self.farbe = farbe Deklaration der Klasse Fahrgestell class Fuehrerhaus: def __init__(self,farbe): self.farbe = farbe ... class Duplolok: def __init__(self,name): self.name = name self.fahrgestell = Fahrgestell("blau") self.fuehrerhaus = Fuehrerhaus("rot") emma = Duplolok('Emma') Deklaration der Klasse Fuehrerhaus Deklaration der Klasse Duplolok Das Objekt emma vom Typ Duplolok mit dem Attribut Namen und dem Attributwert 'Emma', enthält ein Objekt der Klasse Fahrgestell und ein Objekt der Klasse Führerhaus. Das Objekt emma wird initialisiert Aggregat Die Duplolok besitzt ein Fahrgestell und ein Führerhaus. Das Führerhaus besitzt wiederum zwei Elemente. 63 ooP mit Python Selbst erstellte Klassen und ihre Objekte 12.2 Vererbung 12.2.1 Die Flexibilisierung bei der Programmierung Bisher haben wir Objekte betrachtet, die genau eine Funktion erfüllen. Damit sind sie nicht viel leistungsfähiger als Funktionen. Bei der Vererbung dagegen kann die objektorientierte Programmierung ihre volle Stärke ausspielen. Teilaufgaben, die in mehreren Klassen die gleiche Rolle spielen, können in Schnittstellen-Klassen ausverlagert werden. Notfalls werden deren Methoden wieder angepasst, dann sprechen wir von Polymorphie. Einzelnen Klassen können mit Hilfe der Spezialisierung allgemeinere Aufgaben übernehmen. Manchmal muss nicht Zusammengehöriges zusammengefasst, also generalisiert werden. In allen Fällen müssen wir aber in der Lage sein, festzustellen, zu welcher Klasse oder zu welcher Klassen-Hierarchie ein bestimmtes Objekt gehört, weil davon wieder unterschiedliche Aktionen abhängen. 12.2.2 Typ-Prüfung Manchmal sollen in einem Listen-Attribut nur Objekte einer bestimmten Klasse (eines bestimmten Typs) eingelagert werden: So ist das Federmäppchen etwa kein Platz für Messer und Gabel. Die Methode, mit der Dinge ins Federmäppchen aufgenommen werden, muss also erkennen, ob das tatsächlich tatsächlich z.B. ein Stift ist, der ins Federmäppchen darf: Sie muss also den Typ prüfen. Beispiel: Typprüfung Die Methode type() fragt ein Objekt, zu welcher Klasse es gehört >>> print(type(blauerKuli)) <class '__main__.Stift'> >>> class Federmaeppchen: def __init__(self): self.inhalt = [] def aufnehmen(self,stift): if isinstance(stift,type(Stift())): self.inhalt.append(stift) else: print("Das ist kein Stift!") >>> >>> >>> Das f = Federmaeppchen() f.aufnehmen(blauerKuli) f.aufnehmen ("Textobjekt") ist keine Stift! Die Methode isinstance() prüft, ob ein Objekt zu einer bestimmten Klasse gehört und gibt dann True bzw. False aus. Der Versuch, einen Text einzufügen, statt eines Stift-Objektes, wird abgelehnt 64 ooP mit Python 12.2.3 Selbst erstellte Klassen und ihre Objekte Spezialisieren Um ein Federmäppchen zu füllen, können wir die Klassen Bleistift und Kugelschreiber entwerfen oder Buntstifte, Filzstifte, Füller und viele andere Stifttypen. Nun sind Buntstifte aber keine Bleistifte. Sie haben zwar eine fest eingebaute Mine und werden durch das Spitzen immer kürzer. Allerdings machen sie beim Radieren Probleme. Sinnvollerweise beschreiben wir deshalb die Buntstifte und Bleistifte als Sonderfall der Klasse Holzstift. Sie besitzt das Attribut Mine und die Methode spitzen(), die auf das Attribut Mine kürzend zugreift. Die Klasse Buntstift verwendet (wir sagen: sie erbt) alle Eigenschaften und Methoden der Klasse Holzstift und ergänzt sie um das Attribut Farbe und um die entsprechende getMethode. Die Klasse Bleistift, erbt ebenfalls von der Klasse Holzstift, ergänzt sie aber um das Attribut Haerte und um die besondere Methode radieren(). Spezialisierung Spezialisiert Holzstift int laenge int getLaenge() spitzen() erbt von erbt von Beispiel: Buntstift(Holzstift) str farbe Bleistift(Holzstift) int haerte str getFarbe() int getHaerte() radieren() Spezialisieren class Holzstift: def __init__(self,laenge): self.__laenge = laenge def getLaenge(self): return self.__laenge def spitzen(self): if self.__laenge > 2: self.__laenge-=1 print("neue Laenge: ",self.__laenge) else: print("Der Stift ist am Ende") class Bleistift(Holzstift): def __init__(self,laenge,haerte): Holzstift.__init__(self,laenge) self.__haerte = haerte def getHaerte(self): return self.__hearte Zur Klasse Holzstift gehören - das Attribut laenge - die zur laenge gehörende getMethode - und die die Methode spitzen(). Die Klasse Bleistift erbt die Eigenschaften und Fähigkeiten der Klasse Holzstift und erweitert sie mit ihren eigenen Attributen und Methoden. b = Bleistift(10,2) b.getLaenge() 65 ooP mit Python 12.2.4 Selbst erstellte Klassen und ihre Objekte Generalisieren (is_a-Beziehung) Stark getypte Sprachen wie Java machen bei der Organisation eines Schlampermäppchens Probleme. Buntstift- und Bleistift-Objekte können sich kein gemeinsames Sammelattribut teilen, weil sie zu verschiedenen Klasse gehören. Das Gleiche gilt für Spitzer, Geld, die Brille und was sonst ins Mäppchen passen sollte. Um dieses Problem zu umgehen, erstellen wir eine Klasse Mäppcheninhalt. Alle Stifte-Klassen erweitertern wir um die Klasse allgemeinere Klasse Stift. Alle Klassen dieser Elemente, die ins Federmäppchen gehören, erweitern wir um die Klasse Mäppcheninhalt. Dies Oberklassen darf dafür sogar vollkommen leer sein. Sie stellt ja nur eine Rollen dar, mit der z.B. das Recht ver bunden ist, ins Federmäppchen zu dürfen. Generalisiert Diesen Trick nennen wir Generalisieren: Viele Klassen werden mit einer Oberklasse durch Vererbung verbunden. So erben die Stift-, Lineal- und Spitzerklassen von der Klasse Mäppcheninhalt alle Attribute und Methoden. Wenn die Objekte der erbenden Klassen bei der Typ-Prüfung gefragt werden, gelten sie als Mäppcheninhalt und dürfen ins Federmäppchen. Die Generalisierung wird graphisch durch einen Pfeil dargestellt, der von der erbenden Klasse zur vererbenden Klasse führt. Beispiel: Generalisieren class MaeppchenInhalt: pass Die leere Klasse hilft den Stiften und dem Spitzer, ins Federmäppchen aufgenommen zu werden. class Spitzer(MaeppchenInhalt): def __init__(self): pass Die vererbende Klasse wird in Klammern an den Klassenkopf gehängt. class Stift(MaeppchenInhalt): def __init__(self,farbe): self.farbe = farbe def schreiben(self): pass class Bleistift(Stift): def __init__(self,laenge): self.laenge=laenge b = Bleistift(10) if isinstance(b,type(MaeppchenInhalt())): print('darf ins Maeppchen') ab sofort sind Objekte der Klasse Spitzer und Stift auch Objekte der Klasse MaeppchenInhalt. Objekte der Klasse Bleistift sind Objekte der Klasse MaeppchenInhalt und der Klasse Stift. Als Objekte der Klasse Stift besitzen sie auch die Methode schreiben Die Zugehörigkeit zu einer Oberklasse wird durch die Typ-Prüfung bestätigt 66 ooP mit Python 12.2.5 Selbst erstellte Klassen und ihre Objekte Polymorphie Manchmal passt eine geerbte Methode nicht so ganz zu der erbenden Klasse. Solche Methoden sollte man anpassen können. Deklariert nun eine Unterklasse eine Methode, der Oberklasse um, sagen wir, die Methode der Oberklasse wird überschrieben. Ein Zugriff auf die Methode der Oberklasse ist dann nicht mehr unmittelbar möglich und muss deshalb extra freigegeben werden. Dazu dient der super-Aufruf. Er führt von der überschreibenden Methode der Unterklasse zur überschriebenen Methode der Oberklasse: self.methode() super(NameUnterklasse,self).methode() Nachdem aber die Unterklasse nicht weiß, in welcher der (möglicherweise vielen) Oberklassen die entsprechende Methode deklariert ist, ruft sie super!; dann gibt sie ihren eigenen Klassen-Namen und den Speicherplatz des Objektes an, von dem aus die Oberklasse gebeten wird, ihren Beitrag zu leisten. So kann der Super-Aufruf nach einem möglicherweise langen Weg durch die Oberklassen wieder an die richtige Stelle zurückkehren. Beispiel: Polymorphie – Mensakasse, Automat und Kassierer class Mensakasse: def __init__(self,geld): self.__geld = geld def kassieren(self,geld): self.__geld = self.__geld+geld class Geldautomat(Mensakasse): def __init__(self,geld) Mensakasse.__init__(self,geld) pass def scheineKassieren(self,*scheine) for schein in scheine: self.kassieren(schein.getGeld()) def muenzeKassieren(self,*muenzen): for muenze in muenzen: self.kassieren(muenze.getGeld()) class Kassierer(Mensakasse); def __init__(self,geld) Mensakasse.__init__(self,geld) pass def kassieren(self,muenzen,scheine) geld = 0 for muenze in muenzen: geld = geld+muenze.getgeld() for schein in scheine: geld = geld+schein.getgeld() super(kassierer,self).kassieren(geld) derKassierer = Kassierer(100) derKassierer.kassieren((50,20),(100,20,5,10)) 67 Zur Klasse Mensakasse gehört das Attribut self.__geld, in dem die übergebene Geldmenge als einfache Zahl (Variable geld) gespeichert ist. Sie stellt den folgenden Klassen das Attribut self.__geld und die Methode kassieren zur Verfügung. Der Geldautomat hat einen Eingabeschlitz für Scheine und einen Eingabeschlitz für Münzen, deshalb braucht er zwei Methoden. Die beiden Methoden des Geldautomaten verwenden die gemeinsame Methode kassieren Der Kassierer dagegen kann Münzen und Scheine intutiv richtig auszählen, deshalb nimmt er Münzen und Scheine gemeinsam an. Die Klasse Kassierer hat die Methode kassieren mit einer neuen Parameterliste überschrieben. Deshalb muss sie die Methode der Oberklasse extra aufrufen. Das Kassierer-Objekt tut nach außen so, als gebe es nur eine Methodde kassieren ooP mit Python Selbst erstellte Klassen und ihre Objekte Wortschatz: Vererbung # type(objekt) print(type('Text')) # isinstance(objekt,Klasse) print(isinstance('Tex',str)) Typprüfung prüft, zu welcher Klasse ein Objekt gehört fragt, ob ein bestimmtes Objekt zu einer bestimmten Klasse oder Klassenhierarchie gehört gibt True oder False aus class X: pass class Y(x) pass Erben Die Klasse x ist die Oberklasse der Klasse y Die Klasse y erbt von der Klasse x alle Attribute und Methoden class A: def __init__(self,attr): self.__attr = attr Attribute der Oberklasse Die vererbende Klasse verlangt ein Argument, wenn sie ein Objekt erzeugen soll, deshalb muss an der ersten Stelle im Konstruktor der Unterklasse der Konstruktor der Oberklasse aufgerufen werden. class B(a): def __init__(self,attr): a.__init__(self,attr) pass class Dora: def __init__(self): pass def methode(self): print('ich da oben') class Emil(Dora) def __init__(self): pass def methode(self): print('ich da unten') super(Dora,self).methode() e=Emil() e.methode() 12.2.6 Der super-Aufruf Die Oberklasse besitzt eine Methode, die den gleichen Namen trägt, wie die Methode der Unterklasse (die Methode der Oberklasse wurde überschrieben) Sollen die die Methode der Unterklasse und auch die der Oberklasse aufgerufen werden, muss die Unterklasse den Super-Aufruf verwenden. super: gehe zur Oberklasse (Unterklasse,self): Die Unterklasse und das Aufrufende Objekt werden genannt .methode(): jetzt erst wird die Methode gerufen Schnittstellen Nicht alle Gegenstände, die wir zum Schreiben verwenden, sind ursprünglich zum Schreiben gedacht. So kann eine Taschenlampe mit einer zusätzlichen Funktion Schreiben ausgestattet sein oder ein Lineal mit der Funktion Radieren. Eine Spardose kann mit einem Spitzer verbunden sein, ein Handy mit einem Foto ausgestattet, eine Brille um Googlefunktionen erweitert werden. Bei solchen Funktionserweiterungen spielt die objektorientierte Programmierung ihre Stärken aus. Wird so eine Funktion in eine eigene Klasse ausverlagert, kann sie von beliebig vielen anderen Klassen eingebaut werden. Solche Klassen für ausgelagerte Methoden bezeichnen wir als Schnittstelle. In vielen objektorientierten Sprachen können die Methoden einer Schnittstelle abstrakt formuliert werden, so dass sie beim konkreten Einbau in eine andere Klasse erst noch überschrieben werden müssen. Die Schnittstelle hat damit die Aufgabe übernommen, dafür zu sorgen, dass Methoden, die gleiche Funktionalität bieten, in allen Klassen auch die gleichen Namen tragen. Das erleichtert den Programmierern die Arbeit und den Nutzern die Verwendung der Klassen. 68 ooP mit Python Selbst erstellte Klassen und ihre Objekte Aufgaben zu Kapitel 12 1 Geheimnisprinzip In vielen Städten gibt es öffentliche Bücherschränke: Jeder darf ein Buch für alle Nutzer hineinstellen und jeder darf sich ein Buch entnehmen, wenn er es lesen will. Universitätsbibliotheken dagegen geben ihre Bücher nur auf Bestellung an der Theke heraus und nur an angemeldete Nutzer Erstelle für beide Arten von Bücherverleih eine Klasse mit den geeigneten Attributen. 2 Klassen und Objekte 1) Die Klassen Lok und Leuchte sind in den Klassen- und Objektkarten der Kapitel 12.1.8 (Klassen- und Objektdiagramm) und 12.1.9 (Kommunikation von Objekten - Sequenzdiagramm) schon beschrieben – es fehlt aber noch der Bahnhof: Zeichne die Klassen- und Objektkarten zum Bahnhof und programmiere das Beispiel. 2) Das Programmbeispiel Emma ist noch nicht fertig. Ergänze die fehlenden Klassen mit den benötigten Attributen. Außerdem fehlen noch die Methoden, die die Farbe der Objekte verändern können. Ergänze sie und erzeuge mehrere Duplolok-Objekte mit unterschiedlichen Farbattributen. 3) Erstelle zwei Büchertaschen-Klassen. Die kann ein einziges Schlampermäppchen mit den Stiften aufnehmen und maximal vier beliebige Bücher. Die andere kann ein Schlampermäppchen und beliebig viele Bücher aufnehmen. Kläre worin sich die beiden Klassen unterscheiden müssen und welche Elemente in beiden Klassen gleich sein können. Notiere class Array: deine Idee als Klassendiagramm und prodef __init__(self,arrayMax): self.arrayMax = arrayMax grammiere es in Python. Verwende dabei self.zaehler = -1 die Typprüfung aus Kap. 12.2.2 Typself.liste = [] Prüfung. def getLen(self): return zaehler 4) Für Fortgeschrittene: Ergänze die rechts abgedruckt Klasse Array um die Methoden der Klasse list. Sie greifen alle auf das Attribut self.liste zu. Bei fehlerhaften Eingaben (Eingabe < 0 oder Eingabe > zaehler) geben sie eine Fehlermeldung auf der Konsole aus. Andernfalls setzen sie brav um, was die Liste zu tun hat. 3 def append(self,inhalt): if self.zaehler<arrayMax: self.zaehler+=1 self.liste.append(inhalt) else: print('Array ist voll') def pop(self,stelle): pass Generalisieren und Spezialisieren 1) Teste die Beispiele zur Generalisierung und zur Spezialisierung 2) Zur Oberklasse Fahrzeug gehören Wasserfahrzeuge, Autos (mit PKW und LKW), Motorräder, Traktoren. Überlege, welche Attribute und dazugehörende Methoden in welche der Ebenen verteilt werden sollten und notiere das Klassendiagramm mit Ober- und Unterklassen. 3) Kläre, ob Flugzeuge auch zu der Klassen Fahrzeuge gehören sollte. Notiere die entsprechenden Argumente pro und contra. Finde eine sinnvolle Lösungsmöglichkeit. 69 ooP mit Python Probleme objektorientiert lösen 13 Probleme objektorientiert lösen 13.1 Projektplanung Programme und damit auch Klassen stellen einen abstrahierenden Ausschnitt der Wirklichkeit dar. Bei der Planung ist also zu überlegen, welche Elemente der Wirklichkeit abgebildet werden sollen und in welchen Klassen und mit welchen Methoden sie modelliert werden sollen. Deshalb benötigen Programmierprojekte immer eine gute Planung. Dabei werden die benötigten Klassen und Objekte skizziert, sowie deren Kommunikationswege und wie sich die Zustände im System entwickeln sollen oder dürfen. Gute Projektplanung geschieht also immer zuerst auf dem Papier. Dort werden neben der Systemskizze auch die Kommunikationsschnittstellen beschrieben, also die Methoden mit ihren Parametern bzw. mit ihren Rückgabewerten (Methodenkopf!). Wenn alle diese Voraussetzungen schriftlich festgehalten sind, wird ausgemacht, in welcher Programmiersprache des Projekt umgesetzt wird und welcher Programmierer welchen Ausschnitt entwickelt. Waren die Absprachen gut, müsste das auch das Gesamtprojekt gut laufen, wenn jeder Programmer mit seiner Arbeit fertig ist 13.2 Mögliche Projekte Die folgenden Aufgaben sind Beispiele. Deshalb könnt ihr euch auch eigene Aufgabe ausdenken oder die Aufgaben verändern. Als objektorientierte ProgramiererInnen zerlegt ihr diese Aufgaben dann in Teilaufgaben und bearbeitet sie auf das Team verteilt. 1 Schule, Schüler, Lehrer und Eltern Entwicklt das Projekt Schule, Schüler, Lehrer (Kapitel 13.3) weiter: Bezieht die Eltern mit ein und ordnet jedem Schüler auf geeignete Weise Eltern zu. Ergänzt die Klasse Schulklasse um Schulaufgaben und Stegreifaufgaben und überlegt, wie ihr Noten und Schülerobjekte zusammenbringen könnt. 2 Hafenmodellierung Ein Hafen ist mit dem Meer, einem Binnensee, einem Kanal und einem Fluss verbunden. Auf allen diesen Wasserstraßen können beliebig viele Wasserfahrzeuge unterwegs sein. Der Hafen besitzt ein Kontrollzentrum, dort werden verschiedene Listen geführt über Schiffe, die aus den vier Wasserstraßen in den Hafen einfahren wollen und die aus dem Hafen herausgefahren sind. Es gibt verschiedene Schiffstypen: Containerschiffe, Öltanker, Lastkähne, Kreuzfahrtschiffe, Personenfähren und Autofähren. Güterschiffe docken am Lastkai an, Passagierschiffe am Personenkai. Öltanker dürfen nur durch den Hafen zur nächsten Wasserstraße fahren. Die Kais werden als Liste modelliert, weil viele Schiffe anlegen dürfen. Die Hafendurchfahrt ist immer nur für ein Schiff offen. 70 ooP mit Python 3 Probleme objektorientiert lösen Ampelanlage Auf einer Straßenkreuzung fahren auf vier Straßen zufällig viele unterschiedliche Fahrzeuge ein. Sie dürfen nur weiterfahren, wenn ihre Strecke auf Grün gestellt ist. Wenn die die Warteliste an einer Ampel deutliche länger wird, als die der anderen, beginnen die PKW-Fahrer zu hupen. Dann wird dort die Ampelphase verkürzt. Die Kreuzung kann als Turtle-Graphik dargestellt werden. 4 Mastermind Erkundigt Euch, wie Mastermind gespielt wird und programmiert es selbst. Achtet darauf, dass die Spielsteine unterschiedlichen Rollen haben. Setzt die Turtle ein, um die Oberfläche zeichnen. 5 Turtle-Graphik erweitern Erweitert die Turtle mit Spezial-Turtles, die jeweils einen anderen Arbeitsstil haben. Entwickelt daraus ein Spiel für die MitschülerInnen. 13.3 1 Die Schule, ihre Schüler und Lehrer Die Klasse und ihre Objekte Klasse Schueler 1 class Schueler: 2 def __init__(self,name): 3 pass 4 def duSchreibstDich(self): 5 print(self) 6 def derAndereSchreibtSich(self,anderer): 7 anderer.duSchreibstDich() 8 9 maier = Schueler() 10 schulz = Schueler() 11 1) Erläutere den Zusammenhang der Zeile 9 mit den Zeilen 1-3. Verwende dabei die korrekten Fachausdrücke! 2) Schueler maier trägt den Spitznamen grossM. Sorge dafür, dass das Objekt maier auch unter diesem Namen erreicht wird. Entscheide begründet, welche der freien Zeilen du verwendest. 3) Schueler maier schreibt seinen Speicherplatz auf den Bildschirm und fordert danach den Schueler schulz auf, das Gleiche zu tun. - Notiere beide Aufrufe mit Hilfe der passenden Methoden der angegebenen Klasse Schueler! 4) Eine Python-Methode unterscheidet sich deutlich von einer Python-Funktion. - Erkläre daran die Rolle einer Methode in der objektorientierten Programmierung (ooP). 71 ooP mit Python 2 Probleme objektorientiert lösen Die Klasse und ihre Attribute Klasse Schueler mit einem Attribut 1 class Schueler: 2 def __init__(self,name): 3 self.name = name 4 5 maier = Schueler("maier") 1) Erstelle für das Attribut self.name eine Set- und eine GetMethode. 2) Erzeuge ein Schülerobjekt schulz und erfrage den dort gespeicherten Namen. 3) Stelle die Klasse Schueler und das Schülerobjekt schulz als Klassen- und als Objektdiagramm (Kapitel 12.1.8) dar. 4) Erweitere die Klasse Schueler um die Attribute vorname, gebDat und Klasse, sowie den dazugehörenden Methoden. 5) Ändere den gespeicherten Namen und erfrage ihn erneut. - Kläre , warum es sinnvoller ist, eine Schüler- oder Klassenliste anzulegen, als für jedes Schülerobjekt eine eigene Variable zu verwenden. 6) Erstelle eine Methode anrede(), die den Schüler abhängig vom Alter (Grenze 18 Jahre) korrekt anredet: liebe / leber Vorname bzw. liebe / leber Vorname Nachname. 3 Die Klasse und ihre Listenattribute Klasse Lehrer Ein Lehrer hat - einen Vornamen - einen Namen - ein Geburtsdatum - ein Geschlecht (m/w) - einen Dienstgrad (Ref = Referendar / StR = Studienrat / OStR = Oberstudienrat / StD = Studiendirektor / OStD = Oberstudiendirektor) + ein oder mehrere Fächer 1) Erstelle eine Klasse Lehrer, die die passenden Attribute besitzt. Das Attribut Fach soll vom Typ Liste sein. Überlege, mit welchen Parametern du den Konstruktor ausstatten musst, um alle (!) Attribute korrekt füllen zu können. Schreibe die Klasse mit ihrem Konstruktor und der Initialisierung der Variablen. 2) Schreibe zu den Attributen Vorname, Name und Dienstgrad je eine Get- und eine SetMethode 3) Erzeuge zwei Objekte: Oberstudienrat Christian Schmidt: evangelische Religion, Mathematik (m, 10.12.1970) Studienrätin Hadice Demirci: Deutsch, Englisch, islamische Religion (w, 3.4.1983) 4) Erstelle eine Methode anrede(), die Geschlecht, Dienstgrad und Name korrekt ausgibt; also: Herr OStR C.Schmid bzw. Frau StRin H.Demirci. 5) Entwickle für das Attribut Fach eine SetMethode, mit der du ein Fach ergänzen kannst, eine SetMethode, mit der du ein Fach löschen kannst und eine SetMethode, mit der du ein falsch eingetragenes Fach ändern kannst 72 ooP mit Python 4 Probleme objektorientiert lösen Objekte verwalten Objekte (has-a-Beziehung / is-a-Beziehung) Klasse schulklasse Die Klasse Schulklasse besitzt nur ein Listen-Attribut schuelerDerKlasse Das Attribut schuelerDerKlasse nimmt nur Objekte der Klasse Schuler an (Typprüfung – Kapitel 12.2.2) Klasse schule Die Klasse Schule besitzt die Listen-Attribute lehrer und schulklassen 1) Kläre, welches Attribut bei der Klasse Schueler ab sofort entfallen kann. 2) Entwirf die Klasse Schulklasse mit den Methoden setAlleSchueler(*schueler), setEinenSchueler(schueler), getAlleSchueler(). 3) Schreibe die Klasse Schule mit den dazugehörenden Attributen und Methoden (setAlleKlassen(*Klasse), setEineKlasse(klasse), getAlleKlassen()). 4) Ergänze eine getMethode , die die Daten eines einzelnen Schülers aus der Klasse 10 erfragen kann, wenn dessen Name bekannt ist. 5) Erzeuge ein Schulobjekt unsereSchule, das im Attribut schulklassen ein Klassenobjekt klasse10 besitzt. Trage einige Schülerobjekte in die Klasse ein und teste die Ausgaben. 5 Das Geheimnisprinzip class Offen: def __init__(self,name): self.name = name def setName(self,name): self.name = name def getName(self): print(self.name) def setAnderenNamen(self,obj,name): obj.setName(name) class Geheim: def __init__(self,name): self.__name = name def setName(self,name): self.__name = name def getName(self): print(self.__name) def setAnderenNamen(self,obj,name): obj.setName(name) 1) Erzeuge ein Objekt aenderlich = Offen(“Max Änderlich“) und zwei Geheim-Objekte: ichAendere = Geheim(“Klaus Ender“) und werdeGeaendert = Geheim(“Karl Wechsel“). 2) Teste die beiden folgenden Befehle und rufe dann die dazugehörende getMethode auf. aenderlich.name = "Auch ein Name" werdeGeaendert.name = "Auch ein Name" Erkläre die beiden unterschiedlichen Ergebnisse! 3) Teste die beiden folgenden Befehle: ichAendere.setAnderenNamen(aenderlich,“Kannst Nix“) ichAendere.setAnderenNamen(werdeGeaendert,“Kannst Nix“) Kläre, wie solche unerwünschten Veränderungen verhindert werden könnten 4) Stelle den Ablauf von Aufgabe 5c als Zustandsübergangsdiagramm (Kapitel 12.1.10) und als Sequenzdiagramm (Kapitel 12.1.9) dar. 73 ooP mit Python 6 Probleme objektorientiert lösen Generalisieren und Erben 1) Vergleiche die Klasse Schueler mit der Klasse Lehrer: Welche Gemeinsamkeiten haben sie und worin sind diese Gemeinsamkeiten begründet? 2) Schreibe eine Klasse Person, die die Gemeinsamkeiten von Schülern und Lehrern vereinigt und lasse die Klassen Schüler und Lehrer von der Klasse Person erben. Passe dazu den Konstruktor und die Methoden an. Stelle die Beziehung als Diagramm dar (Kapitel 12.2). In einem Rundschreiben sollen Eltern, Schüler und Lehrer informiert werden. Sie sollen dabei korrekt angesprochen werden: Eltern mit „Herr/Frau Nachname“, Schüler mit „lieber/liebe Vorname“ und Lehrer mit „Herr/Frau Dienstgrad Nachname“. 3) Ergänze die Klasse Person um das Attribut self.__geschlecht und entwirf eine Schnittstelle Anrede, die die passende Methode zur Verfügung stellt. 4) Kläre, in welchen Klassen du die Methoden dieser Schnittstelle in welcher Weise überschreiben muss und setze sie für die (neuen) Klassen Eltern, Schüler und Lehrer um. 74 ooP mit Python Beispiele für eine Hausaufgabe BEISPIELE FÜR EINE HAUSAUFGABE Die Hausaufgabe wird mit Python bearbeitet Für Dateiname gilt immer (!) folgender Aufbau: oopmp[Kapitel][BerabeiterName][BearbeiterVorname] (oopmp steht für objektorientiert Programmieren mit Python) Beispiel für Aufgabe 2a in Kapitel 2: oomp2.py #2a print('Martin Frenkler', ...) Der Quelltext aus der Programmdatei und die Ausgabe auf der Konsolewerden in die Textverarbeitung kopiert, zum Korrigieren ausgedruckt und in der nächsten Stunde vorgelegt. Idle-Programm Name, Vorname Hausaufgabe vom [Datum] oopmp2 Python 3.2.1 (default, Jul 18 2011, 16:24:40) [GCC] on linux2 Type "copyright", "credits" or "license()" for more information. >>> print("Martin Frenkler", "Bergstr. 10", "95465 Neustadt bei Coburg") Martin Frenkler Bergstr. 10 95465 Neustadt bei Coburg >>> Programm mit Datei und Konsolenausgabe Name, Vorname Hausaufgabe vom [Datum] oopmp2.py #2a print("Martin Frenkler", "Bergstr. 10", "95465 Neustadt bei Coburg") Python 3.2.1 (default, Jul 18 2011, 16:24:40) [GCC] on linux2 Type "copyright", "credits" or "license()" for more information. >>> ================================ RESTART ================================ >>> Martin Frenkler Bergstr. 10 95465 Neustadt bei Coburg >>> 75