TU Bergakademie Freiberg Institut für Informatik Modul „Einführung in die Informatik“ Poolübung 4. Pool-Übung zum Modul „Einführung in die Informatik“ - Aufgaben Thema: Programmieren in Python, Teil 2 (Funktionen, Typen Liste und Dictionary, geschachtelte Schleifen) 0) Vorbereitende Übungen zur 4. Poolübung im interaktiven Modus von Python (VOR der Übung durchzuarbeiten) siehe Anhang A, B und C ----------------------------------------------------------------------------------------------------------------------------Beachten Sie bei der Öffnung der Python-IDLE unbedingt Poolübung 2, Abschnitt 1), Absatz 1 ! 1) Bestimmung des Wertes eines Maximums dreier Zahlen mit einer Funktion (vgl. Struktogramme, Aufg. 3.b und 3.Poolübung, Aufg. 2b) (mit IDLE) Achtung: In dieser Aufgabe ist NICHT die Python-Standardfunktion max( ) zu benutzen! Schreiben Sie ein Python-Programm (mit Funktion) für die Bestimmung des maximalen Wertes dreier beliebiger Zahlen. Im Hauptprogramm sollen die drei beliebigen Zahlen eingelesen und das Resultat ausgegeben werden. In einer gesonderten Funktion ist der maximale Wert der drei übergebenen Zahlen zu bestimmen und das Ergebnis an das aufrufende Hauptprogramm zurückzugeben. In der Funktion ist nicht mit globalen Variablen zu arbeiten. Frage dazu: Warum ist es sinnvoll, Hauptprogramm und Funktion in dieser Weise einzuteilen? (Vergleichen Sie dazu mit Standardfunktionen wie sqrt(x), abs(x) usw.) Hinweis zur Lösung: Öffnen Sie dazu das Python-Programm, das in der 2. Poolübung als Lösung von Aufgabe 2.b) erhalten wurde (es liegt als max3z.py im Poolübungsverzeichnis), und ändern Sie dieses Programm zur Lösung der Aufgabe. ----------------------------------------------------------------------------------------------------------------------------- 2) Wert eines Maximums von n bel. Zahlen (mit zwei Funktionen) (mit IDLE) (vgl. Aufgabenkomplex Struktogramme, Aufg. 9) Es soll der Wert eines Maximums von n beliebigen (ganzen oder reellen) Zahlen ermittelt werden. Die ganzzahlige Anzahl n; n>=2; sei dem Nutzer bekannt. Falls n falsch eingegeben wird (hier soll der Einfachheit halber darunter nur verstanden werden, dass ein Wert kleiner als 2 eingegeben wird), ist die Eingabe zu wiederholen (mehrfache fehlerhafte Eingaben sind dabei nicht auszuschließen). Zu verwendendes Datenmodell: Die Zahlen sollen in eine Liste eingelesen werden ( z.B. mit den Komponenten: x[1], x[2], ..., x[n] ). Zu verwendende Steuerstruktur: Zählschleife. Die Eingabe der n beliebigen Zahlen soll in einer gesonderten Funktion erfolgen. In einer zweiten gesonderten Funktion ist die Berechnung des Maximums vorzunehmen. In den Funktionen ist nicht mit globalen Variablen zu arbeiten. Im Hauptprogramm (als Testrahmen zu schreiben, siehe dazu Anhang A) sollen die Anzahl n eingelesen, die beiden Funktionen aufgerufen und der maximale Wert als Resultat ausgegeben werden. Fragen dazu: - Was bezweckt ein Testrahmen? Erklären Sie die Kopfzeile eines Testrahmens. - Warum ist es sinnvoll, Testrahmen und Funktionen in dieser Weise einzuteilen? -----------------Testen Sie die Korrektheit Ihres Programms z.B. mit folgenden Zahlenwerten: - für n: -1; 1; 3; 5 - für die Liste: (3.5, -22.6, 0); (2.55, 5, -7.53, 3.7, 2.0) 1 1011 3) Arbeit mit dem Datentyp Dictionary in Python: Ein „Wörterbuch“ mit Ländern und Hauptstädten Dictionary (siehe auch Vorlesungsskript ): - Kollektion von Schlüssel-Wert-Paaren (key-value-pairs), d.h. Abbildung von Schlüsseln auf Werte - Zugriff auf Elemente der Kollektion über Schlüssel (und nicht über Indizes wie bei Listen) Im unvollständigen Python-Startfile Y:\lehre\Modul_Einf_in_die_Informatik_WS1112_Jung\ Pooluebungen\Pooluebung_4\HauptstadtVonLandStartfile.py ist bereits eine Minidatenbank mit LandHauptstadt-Paaren aus Südamerika enthalten. Öffnen Sie dieses Startfile von der IDLE aus. - Ergänzen Sie dieses Startfile zu einem vollständigen Programm, das Folgendes ausführt: -- Es soll zunächst auf den Bildschirm ausgegeben werden: Hauptstadt von: -- Danach ist von Tastatur ein Land einzugeben. -- Als Resultat ist vom Programm nun aus der Minidatenbank die entsprechende Hauptstadt auszugeben. -- Wenn das Land nicht in der Minidatenbank enthalten ist, ist "nicht enthalten" auszugeben und anschließend nach dem nächsten Land zu fragen -- Die Abfrage "Hauptstadt von: " ist solange zu wiederholen, bis (als „Land“) Ende (in irgendeiner Schreibweise!) eingegeben wird (die Zeichenkette "Ende" ist also Endeerkennungszeichen im Sinne der Struktogrammaufgabe 15; das Endeerkennungszeichen ist vom gleichen Typ wie der Schlüssel). ------------ *Zusatz (Hausaufgabe): Und wie immer - experimentieren Sie mit Ihrem Programm, z.B.: - Ergänzen Sie die Minidatenbank durch weitere südamerikanische Länder - Bisher besteht das Programm nur aus einem Hauptprogramm. Wählen Sie eine andere Struktur: Realisieren Sie jetzt die Ein- und Ausgabe in einem Hauptprogramm und die Auswahl der Hauptstadt des eingelesenen Landes in einer Funktion. ----------------------------------------------------------------------------------------------------------------------------- 4*) Doppelsumme (als Prototyp für verschachtelte Schleifen) (vgl. Struktogramme, Aufg. 12) (falls keine Zeit mehr: Hausaufgabe) Während die Summe als Prototyp einer (einfachen) Schleife angesehen werden kann, ist die Doppelsumme ein Prototyp für eine doppelte Schleife. In beiden Fällen bietet sich die Zählschleife an. Schreiben Sie ein Python-Skript zur Berechnung des Wertes der Doppelsumme n i doppsum = ∑∑ (i + j ) 2 i = 2 j =1 Im Hauptprogramm (als Testrahmen zu schreiben, siehe Anhang A) ist die ganze Zahl n; n>=2; einzulesen (aus Zeitgründen hier ohne Eingabefehlerbehandlung) und der Resultatwert auszugeben. In einer gesonderten Funktion ist der Wert der Doppelsumme zu berechnen. In der Funktion ist nicht mit globalen Variablen zu arbeiten. a) b) Zu verwenden ist die Abweisschleife. Zu verwenden ist die Zählschleife. (Der Quelltext aus a) ist dabei zu modifizieren.) Programmtest: Führen Sie unbedingt einen Test auf logische Fehler aus. Berechnen Sie zunächst den Wert der Doppelsumme z.B. für n=3 auf dem Papier, und testen Sie dann das Programm für diese Eingabe. ----------------------------------------------------------------------------------------------------------------------------- 5) Eventuell weitere Hausaufgaben bis zur nächsten Poolübung Alle Aufgaben, die in der Übung nicht geschafft wurden, sind als Hausaufgaben zu bearbeiten. 2 1011 Anhänge Die drei Anhänge sind - wie stets - VOR der Übung durchzuarbeiten (während der Übung ist dafür keine Zeit vorgesehen) Anhang A: Wichtige generelle Hinweise zu Python-Skripten (siehe dazu auch Vorlesung): (1) Umlaute und ß in Quelltexten Python verwendet den US-ASCII-Zeichensatz, der keine Umlaute, kein ß usw. kennt. Wenn man solche Zeichen in Zeichenketten und Kommentaren (aber nicht in Bezeichnern!) verwenden will, dann fügt man als erste Quelltextzeile ein, dass stattdessen die ASCII-Codepage 1252 (Latin 1) verwendet werden soll: # -*- coding: cp1252 -*und schon kann man Umlaute und ß verwenden. (Dieser spezielle Kommentar wird also von Python ausgewertet.) Wenn man diese Einfügung vergisst, weist der Interpreter in einem „I/O Warning“Fenster darauf hin und schlägt die oben angegebene Zeile vor. Klickt man dann auf „Edit my file“, so setzt der Interpreter diese Zeile ein. (Dieser Weg ist zu empfehlen.) (2) Namenskonventionen in Python-Quelltexten Namen (Bezeichner) von Variablen, Funktionen usw. sollten möglichst selbstdokumentierend sein und stets mit Kleinbuchstaben beginnen. Bei angehängten Worten wird der erste Buchstabe groß geschrieben. Unterstriche „_“ werden in Namen in der Regel nicht verwendet. Beispiel: Eine Funktion zur Berechnung des geometrischen Mittelwerts würde man etwa geometrischerMittelwert(..) oder besser kürzer geomMittel(..) nennen. (3) Anweisungen über mehrere Quelltextzeilen Umfangreichere Anweisungen können länger als eine Quelltextzeile sein. Hier trennt man die Teilzeilen mit einem Backslashzeichen \. Dieses Backslash wird dann durch die nächste Quelltextzeile ersetzt. Beispiel: print "Das ist eine \ zweizeilige Ausgabeanweisung" Auf dem Bildschirm wird dann ausgegeben: Das ist eine zweizeilige Ausgabeanweisung (4) Blockeinrückungen Die Python-IDLE unterstützt den Nutzer dabei und rückt Anweisungsblöcke von Schleifen, Selektionen, … automatisch ein (standardmäßig um je 4 Zeichen). Nach dem Ende eines Blocks muss der Nutzer allerdings (z.B. durch zweimaliges ENTER oder mit der Backspace-Taste) wieder auf die benötigte Einrückungsebene zurückgehen. (5) print-Anweisung mit bzw. ohne automatischem Zeilenvorschub Nach der Abarbeitung einer print-Anweisung in einem Python-Programm wird automatisch ein Zeilenvorschub ausgeführt, der durch ein Komma am Ende der print-Anweisung unterdrückt werden kann. Beispiele dafür: print "Reelle Zahl = " #Automatischer Zeilenvorschub #Kein Zeilenwechsel print "Reelle Zahl = ", 3 1011 (6) Zur Einrückung (engl.: indentation) von Blöcken In einer Einrückung dürfen nicht Tabulatorsprünge und Leerzeichen kombiniert werden (also: entweder Tabulatorsprünge oder Leerzeichen). Ansonsten meldet der Interpreter einen Fehler. (7) Testrahmen: Hauptprogramm in Form eines Testrahmens mit Kopfzeile der Form if __name__ == '__main__': (Der Name __name__ und die Zeichenkette '__main__' beginnen und enden jeweils mit zwei aufeinanderfolgenden Unterstrichen.) Vom Nutzer geschriebene Funktionen speichert man oft in ein Verzeichnis für nutzereigene Module (z.B. unter der Bezeichnung meinModul.py), die man dann in andere Programme importieren und dort verwenden kann. Andererseits sollte man eigene Funktionen durch ein Hauptprogramm in Form eines sog. Testrahmens auf Richtigkeit testen. Python erlaubt nun die folgenden beiden Abarbeitungsmöglichkeiten eines solchen Skripts mit Testrahmen: (1) wenn das Modul direkt als Skript gestartet wird (z.B. von der IDLE über Run/Run Module), dann wird __name__ vom System die Zeichenkette '__main__' zugewiesen, die Bedingung __name__ == '__main__' (dann also: '__main__' == '__main__') erhält dadurch den Wert True und der (im True-Zweig der Selektion stehende!) Testrahmen wird folglich abgearbeitet. (2) wenn andererseits das Modul in ein anderes Python-Programm importiert wird, so wird __name__ vom System der Modulname zugewiesen (im obigen Beispiel 'meinModul'), die Bedingung __name__ == '__main__' erhält dadurch den Wert False und der (im True-Zweig der Selektion stehende) Testrahmen wird nicht abgearbeitet (sondern nur nach Aufruf die Funktion). Denn: wenn man von einem anderen Programm aus eine Funktion aus meinModul.py nutzen will und dieses Modul deshalb importiert, soll ja nicht das Hauptprogramm aus diesem Modul abgearbeitet werden, sondern nur die aufgerufene Funktion. (Bemerkung: Wenn in einem Python-Skript (Quelltext) Funktionen enthalten sind, könnten wir prinzipiell die oben genannte Kopfzeile stets über das Hauptprogramm (Testrahmen) schreiben. Aus Zeitgründen werden wir in der Übung diese Kopfzeile allerdings nur in ausgewählten Beispielen verwenden.) (8) Docstring Ein sog. Docstring in dreifachen Anführungszeichen unterhalb eines Funktionskopfes dient zur Dokumentierung einer Funktion und kann im interaktiven Modus mit dem Kommando help(<function name>) angezeigt werden. ----------------------------------------------------------------------------------------------------------------------------- Anhang B: Vorbereitende interaktive Übung zu Aufgabe 2 Anhängen von Listenelementen an eine Liste mit der Methode append (naechstesListenelement) sowie Löschen von Listenelementen Der Aufruf der Methode append (...) aus der vordef. Klasse list wird an den Listennamen (z.B.: x) mit einem Punkt als Trennzeichen angehängt (vgl. Skript Informatik07-Python-1.pdf, S. 8): x.append (naechstesListenelement) >>> x=[] # Liste als leere Liste definieren (Anfangswertzuweisung) >>> x.append(input("Naechstes Listenelement eingeben: ")) Naechstes Listenelement eingeben: 50 4 1011 >>> print x [50] >>> x.append(input("Naechstes Listenelement eingeben: ")) Naechstes Listenelement eingeben: -33 >>> print x [50, -33] >>> del x[0] # Loeschen des ersten Listenelements x[0] aus der Liste >>> print x [-33] ----------------------------------------------------------------------------------------------------------------------------- Anhang C: Übungen im interaktiven Modus zur Aufgabe 3 (Datentyp Dictionary) # Ein kleines Telefonbuch als Dictionary (Ausgaben durch Eingabe der Anweisungen im interaktiven Modus selbst erzeugen) >>>televerz={"Peter":"(03731) 434733","Katja":"(45223) 784412",\ "Max":"(55433) 2356"} #Zuweisung eines Dictionary >>>type (televerz) #Ausgabe des Typs des Objekts, auf das televerz verweist >>>televerz #Ausgabe des Dictionary (in dieser Form nur im interaktiven Modus moeglich) >>>print televerz #unformatierte Ausgabe mit print >>>televerz["Katja"] #Zugriff auf Telefonnummer (=Wert) über Schluessel (=Name); #dabei entspricht der Schluessel bei Dictionaries dem Index bei Listen >>>televerz["Max"] >>>print "%s\n%s\n%s" %(televerz["Peter"],televerz["Katja"],televerz["Max"]) >>>televerz["Vera"] >>>print #formatierte Ausgabe mit print; wieder Schluessel statt Index = "(03733) 344555" #Eingabe eines neuen Paares durch Zuweisung televerz >>>televerz["Paul"]=raw_input("Telefonnr. von Paul mit Vorwahl: ") #Eingabe eines neuen Paares von Tastatur >>>televerz["Anja"]=raw_input("Telefonnr. von Anja mit Vorwahl: ") >>>print televerz >>>del televerz["Peter"] #Loeschen des Eintrags mit dem Schluessel "Peter" >>>print televerz >>>"Katja" in televerz #gibt True zurueck, falls Key "Katja" enthalten, sonst False >>>woerterbuch={} #Zuweisung eines leeren Dictionary als Anfangswert >>>print woerterbuch #Und noch eine kurze Uebung zu Strings: >>>str="Hallo" >>>strGross=str.upper() #Umwandlung des String in nur Grossbuchstaben >>>print strGross HALLO >>>strKlein=str.lower() #Umwandlung des String in nur Kleinbuchstaben >>>print strKlein hallo ----------------------------------------------------------------------------------------------------------------------------5 1011