148
Imperative Programmierung - mit Python Klaus Becker 2012

Imperative Programmierung - mit Python

  • Upload
    jarvis

  • View
    52

  • Download
    0

Embed Size (px)

DESCRIPTION

Imperative Programmierung - mit Python. Klaus Becker 2012. Imperative Programmierung. Teil 0. Vorbemerkungen zu Python. Entwicklungsgeschichte. - PowerPoint PPT Presentation

Citation preview

Page 1: Imperative Programmierung  - mit Python

Imperative Programmierung -

mit Python

Klaus Becker

2012

Page 2: Imperative Programmierung  - mit Python

2 Imperative Programmierung

Page 3: Imperative Programmierung  - mit Python

3 Teil 0

Vorbemerkungen zu Python

Page 4: Imperative Programmierung  - mit Python

4 Entwicklungsgeschichte

Die Sprache wurde Anfang der 1990er Jahre von Guido van Rossum am Centrum voor Wiskunde en Informatica (Zentrum für Mathematik und Informatik) in Amsterdam als Nachfolger für die Programmier-Lehrsprache ABC entwickelt, ursprünglich für das verteilte Betriebssystem Amoeba. Alle bisherigen Implementierungen der Sprache übersetzen den Text eines Python-Programms transparent in einen Zwischencode, der dann von einem Interpreter ausgeführt wird.

Der Name geht nicht etwa (wie das Logo vermuten ließe) auf die gleichnamige Schlangengattung Pythons zurück, sondern bezog sich ursprünglich auf die englische Komikertruppe Monty Python. In der Dokumentation finden sich daher auch einige Anspielungen auf Sketche aus dem Flying Circus. Trotzdem etablierte sich die Assoziation zur Schlange, was sich u. a. in der Programmiersprache Cobra sowie dem Python Toolkit „Boa“ äußert.Quelle: Wikipedia

Page 5: Imperative Programmierung  - mit Python

5 Python - Ziele

Python wurde mit dem Ziel entworfen, möglichst einfach und übersichtlich zu sein. Dies soll durch zwei Maßnahmen erreicht werden: Zum einen kommt die Sprache mit relativ wenigen Schlüsselwörtern aus, zum anderen ist die Syntax reduziert und auf Übersichtlichkeit optimiert. Dies führt dazu, dass Python eine Sprache ist, in der man schnell, einfach und leicht programmieren kann. Sie ist daher besonders dort geeignet, wo Übersichtlichkeit und Lesbarkeit des Codes eine herausragende Rolle spielen – z. B. in der Teamarbeit, bei Beschäftigung mit dem Quelltext nach längeren Pausen oder bei Programmieranfängern.

Durch die Möglichkeit, auch Programme anderer Sprachen als Modul einzubetten, werden viele Nischen in der Programmierung abgedeckt. Bei Bedarf lassen sich so beispielsweise zeitkritische Teile durch maschinennah in C programmierte Routinen ersetzen, oder Python kann als Skriptsprache eines anderen Programms dienen (Beispiele: OpenOffice.org, Blender, Maya, PyMOL, SPSS und GIMP).Quelle: Wikipedia

Page 6: Imperative Programmierung  - mit Python

6 Python - Ziele

Python ist eine Multiparadigmensprache. Das heißt, es zwingt den Programmierer nicht zu einem einzigen bestimmten Programmierparadigma, sondern erlaubt es, das für die jeweilige Aufgabe am besten geeignete Paradigma zu wählen. Objektorientierte und strukturierte Programmierung werden vollständig unterstützt, weiterhin gibt es Spracheigenschaften für funktionale und aspektorientierte Programmierung.Quelle: Wikipedia

Quelle: http://kamelopedia.mormo.org/index.php/Eierlegende_Wollmilchsau

Page 7: Imperative Programmierung  - mit Python

7 Interne Abläufe

Compiler

Interpreter

Der Quelltext eines Python Programms wird mit einem Texteditor geschrieben (z.B. Idle oder PyScripter).

Der Python-Compiler erzeugt einen (maschinenunabhängigen) Byte-Code.

Der Compiler entscheidet selbst, ob der Byte-Code nur als Zwischenprodukt im Arbeitsspeicher erzeugt wird, oder ob er auch als .pyc-Datei gespeichert wird.

Der Python-Interpreter führt den vom Compiler erzeugten Byte-Code aus. Derselbe Byte-Code kann auf verschiedenen Plattformen ausgeführt werden, sofern diese einen Python-Interpreter zur Verfügung stellen.

Page 8: Imperative Programmierung  - mit Python

8 Gängige Python-Versionen

http://portablepython.com/releases/

http://www.python.org/download/

Page 9: Imperative Programmierung  - mit Python

9 Entwicklungsumgebung Idle

Page 10: Imperative Programmierung  - mit Python

10 Entwicklungsumgebung PyScripter

Page 11: Imperative Programmierung  - mit Python

11 Literatur Johannes Ernesti, Peter Kaiser: Python 3. Das umfassende

Handbuch. Galileo Computing 2009. (Preis: 40 €)

Michael Weigend: Objektorientierte Programmierung mit Python. mitp 2008. (Preis: 40 €)

Michael Weigend: Python Ge-Packt. mitp 2006. (Preis: 16 €)

Thomas Theis: Einstieg in Python 3. Galileo Computing 2009. (Preis: 25 €)

Gregor Lingl: Python für Kids. bhv 2008. (Preis: 20 €)

P. Barry, D. Griffiths: Programmieren von Kopf bis Fuß. O´Reilly 2010 (Preis: 20 €)

...

Page 12: Imperative Programmierung  - mit Python

12 Materialien

Internet: Python Official Website

http://www.python.org/ Python-Tutorium von Guido van Rossum:

http://starship.python.net/crew/gherman/publications/tut-de/tut-de-21.pdfhttp://starship.python.net/crew/gherman/publications/tut-de/online/tut/

offenes eBook von von Peter Kaiser und Johannes Ernesti (Python 2.5):http://openbook.galileocomputing.de/python/?GalileoSession=10541258A3Vg6VBUX8A

PythonWiki: http://wiki.python.de/

Python-Kurs von W.Spiegel: http://www.wspiegel.de/pykurs/pykurs.htm

Python, Programmieren macht Spaß : http://www.thomas-guettler.de/vortraege/python/einfuehrung.html

BICS: http://schule.de/bics/inf2/programmiersprachen/python/

Unterrichtsmaterialien von Klaus Merkert:http://www.hsg-kl.de/faecher/inf/python/index.php

Unterrichtsmaterialien aufwww.inf-schule.de

Page 13: Imperative Programmierung  - mit Python

13 Teil 1

Populationsentwicklung -Datenverwaltung mit Variablen

Page 14: Imperative Programmierung  - mit Python

14 Populationsentwicklung

Modellannahmen: Unterteilung in drei Alterklassen: junge Mäuse, erwachsene Mäuse und alte Mäuse. In jedem Schritt erfolgt ein Wechsel der Altersklasse: Junge Mäuse werden erwachsen, erwachsene werden alt (und alte Mäuse leider nicht mehr jung). Nur ein bestimmter Anteil (siehe Diagramm) erreicht die nächste Altersstufe. Im Diagramm sind zusätzlich die Geburtenraten eingetragen. Wir gehen davon aus, dass jede erwachsene Maus (im Durchschnitt) vier junge Mäuse erzeugt und dass jede alte Maus (im Durchschnitt) zwei junge Mäuse erzeugt.

Zielsetzung:

Im Folgenden soll die Entwicklung dieser Mäusepopulation simuliert werden. Ziel ist es, sich mit Hilfe automastisierter Berechnungen einen Überblick über die Größe und Zusammensetzung einer sich fortpflanzenden Mäusepopulation zu verschaffen.

Page 15: Imperative Programmierung  - mit Python

15 Populationsentwicklung

Aufgabe: Berechne die Populationswerte (ohne Python). Zur Kontrolle: Nach 5 Schritten besteht die gesamte Population aus knapp 300 Mäusen.

Schritt

0

1

2

3

4

5

...

jung

6

60 = 4*9+2*12

erwachsen

9

3 = 6:2

alt

12

3 = 9:3

Page 16: Imperative Programmierung  - mit Python

16 Python als Taschenrechner

>>> jung = 6>>> erwachsen = 9>>> alt = 12>>> jung6>>> erwachsen9>>> alt12>>> alt = erwachsen // 3>>> erwachsen = jung // 2>>> jung = erwachsen*4 + alt*2...

Aufgabe:

(a) Probiere das selbst aus. Versuche auch zu verstehen, wie die ausgegebenen Zahlenwerte zustande kommen.

(b) Irgend etwas stimmt aber nicht. Eigentlich sollten es nach einem Simulationsschritt 60 junge Mäuse sein. Woran liegt es, dass hier ein falsches Ergebnis herauskommt?

(c) Benutze Hilfsvariablen, um noch benötigte Zahlenwerte zwischenzuspeichern.

(d) Kann man die Berechnungen auch mit Hilfe einer einzigen Hilfsvariablen durchführen?

Page 17: Imperative Programmierung  - mit Python

17 Python als Taschenrechner

>>> schritt = 0>>> schritt???>>> schritt = schritt + 1>>> schritt???>>> schritt = schritt + 1>>> schritt???>>> schritt = schritt + 1>>> schritt???

Aufgabe:

(a) Die Gesamtanzahl der Mäuse soll auch verwaltet werden. Führe hierzu eine geeignete Variable und geeignete Berechnungen ein.

(b) Zusätzlich soll auch noch der jeweilige Schrittzahl verwaltet werden. Teste den oben gezeigten Python-Dialog. Kannst du die Ergebnisse erklären, die anstelle der Fragezeichen auftreten?

Page 18: Imperative Programmierung  - mit Python

18 Python als Taschenrechner

>>> jung = 6>>> erwachsen = 9>>> alt = 12>>> jung6>>> erwachsen9>>> alt12

???

>>> jung60>>> erwachsen3>>> alt3>>>

Python-Dialog

Aufgabe: Bei der Berechnung des nächsten Populationszustands haben wir ein etwas merkwürdig aussehendes Divisionszeichen // benutzt. Teste, wie es sich auswirkt, wenn man anstatt des Divisionszeichens // das geläufigere Zeichen / benutzt. Was stellst du fest?

Aufgabe: Führe auch Python-Dialoge wie den unten gezeigten aus. Inwiefern tragen die hier erzielten Ergebnisse zur Erklärung des unterschiedlichen Verhaltens der beiden Divisionsoperatoren // und / bei? >>> jung = 11>>> type(jung)<class 'int'>>>> erwachsen = jung // 2>>> type(erwachsen)<class 'int'>

Page 19: Imperative Programmierung  - mit Python

19 Fachkonzept - Variable

Variablen dienen in der Informatik dazu, Daten zu verwalten. Eine Variable ist ein Name, der (in der Regel) mit einem Datenobjekt verknüpft ist.

Variable Wert

jung 6

erwachsen 9

alt 12

Variablenzustand

Als Wert einer Variablen wird das Datenobjekt angesehen, das von der Variablen verwaltet wird.

Ein Variablenzustand beschreibt die aktuell vorliegenden Variablen mit den verwalteten Daten.

Page 20: Imperative Programmierung  - mit Python

20 Fachkonzept - Zuweisung

Mit einer Zuweisung kann man eine Variable mit einem neuen Datenobjekt verknüpfen.

Auswertung einer Zuweisung: Erst wird der Wert des Terms mit Hilfe des aktuellen Variablenzustands ermittelt. Dieser Wert wird dann der Variablen als neuer aktueller Wert zugewiesen.

Aufbau einer Zuweisung: Eine Zuweisung besteht aus einer Variablen (der ein Wert zugewiesen wird) and einem Term (der den zuzuweisenden Wert festlegt).

Zustand - vorher

Zustand - nachher

Auswertung

alt = erwachsen // 3

Variable Term

Zuweisungszeichen

alt = erwachsen // 3

{jung -> 6; erwachsen -> 9; alt -> 12}

3

{jung -> 6; erwachsen -> 9; alt -> 3}

alt ->

Page 21: Imperative Programmierung  - mit Python

21 Trace-Tabelle

Eine Trace-Tabelle protokolliert die Veränderungen von Variablenzuständen, wenn mehrere Zuweisungen (bzw. sonstige Anweisungen) ausgeführt werden. Das folgende Beispiel zeigt eine solche Trace-Tabelle.

Zuweisung schritt jung erwachsen alt hilf

schritt = 0 0

jung = 6 0 6

erwachsen = 9 0 6 9

alt = 12 0 6 9 12

schritt = schritt + 1 1 6 9 12

hilf = erwachsen * 4 + alt * 2 1 6 9 12 60

alt = erwachsen // 3 1 6 9 3 60

erwachsen = jung // 2 1 6 3 3 60

jung = hilf 1 60 3 3 60

Page 22: Imperative Programmierung  - mit Python

22 Variablenbezeichner

Aufgabe: Die Folge von Zuweisungen soll die Entwicklung einer Population beschreiben. Beurteile die Wahl der Variablenbezeichner?

>>> a = 20>>> b = 12>>> c = a + b>>> d = a>>> a = a // 2 + 4 * b>>> b = d // 2 + b // 2>>> c = a + b>>> d = a>>> a = a // 2 + 4 * b>>> b = d // 2 + b // 2>>> c = a + b

Bei der Wahl der Variablenbezeichner (d.h. der Namen, die man den Variablen gibt) ist man recht flexibel: Verwendung von Buchstaben, Ziffern und dem Unterstrich; Unterscheidung zwischen Groß- und Kleinschreibung; keine Ziffern am Anfang; Umlaute sind erlaubt, machen aber gelegentlich Schwierigkeiten.

Bei der Wahl der Variablenbezeichner sollte man sprechende Namen benutzen. Das sind Namen, die möglichst gut erklären, welche Daten mit den Variablen verwaltet werden.

Page 23: Imperative Programmierung  - mit Python

23 Exkurs: Was ist eine Variable?

Variablen dienen in der Informatik dazu, Daten zu verwalten. Eine Variable ist ein Name, der mit einer Speicherzelle verknüpft ist. Mit der Variable kann man auf den in der zugehörigen Speicherzelle abgelegten Datenwert zugreifen.

Name

Speicherzelle mit Datenwert

Variablen dienen in der Informatik dazu, Daten zu verwalten. Eine Variable ist ein Name, der (in der Regel) mit einem Datenobjekt verknüpft ist.

Name

Datenobjekt

Variablen dienen in der Informatik dazu, Daten zu verwalten. Eine Variable ist ein Name, der (in der Regel) mit einem Wert verknüpft ist.

Name Datenwert

Zeiger

{jung -> 6; erwachsen -> 9; alt -> 12}

"Behältersemantik"

"Zeigersemantik"

"Wertsemantik"

Page 24: Imperative Programmierung  - mit Python

24 Exkurs: Variablen in Python

Variablen dienen in der Informatik dazu, Daten zu verwalten. Eine Variable ist ein Name, der (in der Regel) mit einem Datenobjekt verknüpft ist.

Name

Datenobjekt

Zeiger

"Zeigersemantik"

>>> id(2)505300136>>> type(2)<class 'int'>>>> 22

Jedes Datenobjekt in Python hat eine Identitätsnummer, einen Typ und einen Wert. Die Identitätsnummer ist die Adresse des Objekts im Speicher. Sie ist also eine Zahl, mit der man ein Datenobjekt eindeutig identifizieren kann. >>> id(2)

505300136>>> zahl = 2>>> id(zahl)505300136>>> type(zahl)<class 'int'>>>> zahl2

Eine Variable ist ein Name, der (in der Regel) mit einem Datenobjekt verknüpft ist. Die Verknüpfung wird durch einen Verweis (Referenz) auf die Speicheradresse des Datenobjekts hergestellt.

Page 25: Imperative Programmierung  - mit Python

25 Exkurs: Zuweisungen in Python

Eine Veränderung eines Variablenwerts kann mit Hilfe einer Zuweisung erfolgen.

>>> a = 2>>> id(a)505300136>>> b = a>>> id(b)505300136

>>> a = "Test">>> b = "Test">>> id(a)27764768>>> id(b)27757280

Erst wird der Wert des Terms (auf der rechten Seite der Zuweisung) mit Hilfe des aktuellen Variablenzustands ermittelt. Dann wird ein Datenobjekt mit diesem Wert an die Variable (auf der linken Seite der Zuweisung) gebunden. Dieses Datenobjekt kann ein bereits existierendes Datenobjekt sein oder ein neu erzeugtes. Python entscheidet nach internen Strategien, welche Version günstiger ist. Je nach Programmablaufsituation können gleiche Zuweisungen durchaus zu unterschiedlichen Datenobjektkonstellationen führen. Entscheidend ist nur, dass der Variablen ein Datenobjekt zugeordnet wird, das den gewünschten Datenwert hat.

[variable] = [term]

Struktur

Auswertung

Beachte: Auch wenn zwei Variablen denselben Wert haben, müssen sie nicht auf dasselbe Datenobjekt verweisen.

Page 26: Imperative Programmierung  - mit Python

26

Exkurs: Mehrfachzuweisungen in Python

Variablentupel

>>> (jung, erwachsen, alt) = (6, 9, 12)>>> jung6>>> erwachsen9>>> alt12>>> (jung, erwachsen, alt) = (erwachsen*4+alt*2, jung//2, erwachsen//3)>>> (jung, erwachsen, alt)(60, 3, 3)

Python erlaubt Zuweisungen der Gestalt [variablentupel] = [termtupel].

Termtupel

Page 27: Imperative Programmierung  - mit Python

27 Ein erstes Programm

Wenn man sich bei einem Dialog im Ausführfenster vertippt, muss man neu anfangen.>>> jung = 6>>> erwachsen = 9>>> alt = 12>>> hilf = erwachen*4 + alt*2... hilf = erwachen*4 + alt*2NameError: name 'erwachen' is not defined

Tippfehler

>>> >>> jung60>>> erwachsen3>>> alt3

jung = 6erwachsen = 9alt = 12hilf = erwachsen*4 + alt*2alt = erwachsen // 3erwachsen = jung // 2jung = hilf

Ausführfenster Programmfenster

Aufgabe: Öffne ein Programmfenster und gib die Anweisungen zur Berechnung der Entwicklung der Mäusepopulation hier ein. Speichere die Anweisungen in einer Datei ab. Mit einen Run-Befehl kann man jetzt die Anweisungen von Python ausführen lassen. Anschließend kann man sich im Ausführfenster die aktuell von den Variablen verwalteten Werte anzeigen lassen.

Page 28: Imperative Programmierung  - mit Python

28 Benutzerfreundliche Programme

Die bisher betrachteten Programme waren nicht benutzerfreundlich angelegt. Die Ausgangspopulation konnte nicht vom Benutzer vorgegeben werden, sondern war stets im Programm fest vorgegeben. Die erreichte Endpopulation musste vom Benutzer im Ausführfenster Schritt für Schritt abgefragt werden.

Ziel ist es, Programme etwas benutzerfreundlicher anzulegen.

Ausgaben

Benutzereingaben

Page 29: Imperative Programmierung  - mit Python

29 Ausgabe von Daten

Bearbeite hierzu die Aufgaben auf inf-schule 1.6.1.1.7.

>>> Die berechneten Populationswerte sind:Anzahl junger Maeuse: 60Anzahl erwachsener Maeuse: 3Anzahl alter Maeuse: 3

Aufgabe: Ändere das bisher entwickelte Programm zur Mäusepopulation so ab, dass folgende Ausgabe im Ausführfenster erscheint:

Ausführfenster

Page 30: Imperative Programmierung  - mit Python

30 Eingabe von Daten

Bearbeite hierzu die Aufgaben auf inf-schule 1.6.1.1.8.

>>> Gib die Werte der Ausgangspopulation ein:Anzahl junger Maeuse: 20Anzahl erwachsener Maeuse: 18Anzahl alter Maeuse: 4

Die berechneten Populationswerte sind:Anzahl junger Maeuse: 80Anzahl erwachsener Maeuse: 10Anzahl alter Maeuse: 6

Aufgabe:Ergänze das bisher entwickelte Programm zur Mäusepopulation so, dass der Benutzer selbst die Ausgangspopulation eingeben kann. Im Ausführfenster soll z.B. folgender Ein-/Ausgabe-Dialog erscheinen.

Ausführfenster

Page 31: Imperative Programmierung  - mit Python

31 Fachkonzept - Programm

# -*- coding: utf8 -*-# Eingabeprint('Gib die Werte der Ausgangspopulation ein:')jung = int(input('Anzahl junger Maeuse: '))erwachsen = int(input('Anzahl erwachsener Maeuse: '))alt = int(input('Anzahl alter Maeuse: '))# Verarbeitunghilf = erwachsen*4 + alt*2alt = erwachsen // 3erwachsen = jung // 2jung = hilf# Ausgabe:print('')print('Die berechneten Populationswerte sind:')print('Anzahl junger Maeuse: ', jung)print('Anzahl erwachsener Maeuse: ', erwachsen)print('Anzahl alter Maeuse: ', alt)Quelltext

Ein (Python-) Programm ist eine Folge von (Python-) Anweisungen und Kommentaren. Der Programmtext wird auch Quelltext genannt.

Jede Anweisung wird im Quell-text in eine neue Zeile geschrieben.

Die Verständlichkeit eines Programms wird durch sogenannte sprechende Bezeichner deutlich erhöht. Ein sprechende Bezeichner ist ein Name (z. B. für eine Variable), der die Bedeutung des bezeichneten Gegenstands möglichst gut wiedergibt.

Kommentare dienen dazu, die Bedeutung von Programmteilen zu erläutern. Kommentare werden eigentlich nur für die Menschen ergänzt, die den Quelltext bearbei-ten. Bei der Ausführung von Programmen werden sie ignoriert.

Page 32: Imperative Programmierung  - mit Python

32 Fachkonzept - EVA-Prinzip

# Eingabe...jung = int(input("Anzahl junger Maeuse: "))...# Verarbeitungschritt = 0...# Ausgabe...print('Anzahl junger Maeuse: ', jung)...

Eingabe

Viele Programme lassen sich wie im folgenden Beispiel nach dem EVA-Prinzip strukturieren. EVA steht hier für Eingabe - Verarbeitung - Ausgabe. Auf einen Eingabeteil folgt ein Verarbeitungsteil und schließlich ein Ausgabeteil.

Verarbeitung

Ausgabe

Eingaben in Python: Der input-Operator gibt zunächst den Aufforderungstext aus, wartet dann, bis der Benutzer seine Eingabe mit der Return-Taste abgeschlossen hat und liefert diese Eingabe als Zeichenkette vom Typ str zurück.

Ausgaben in Pythen: Die print-Anweisung gibt alle übergebenen Werte der Reihe nach (in einer Zeile) auf dem Bildschirm aus.

Page 33: Imperative Programmierung  - mit Python

33 Fehler in Programmen

# Eingabeprint('Gib die Werte der Ausgangspopulation ein:')jung = input('Anzahl junger Maeuse: ')erwachsen = input('Anzahl erwachsener Maeuse: ')alt = input('Anzahl alter Maeuse: '# Verarbeitunghilf = erwachsen*4 + alt*2alt = erwachsen // 3erwachen = jung // 2jung = hilf# Ausgabe:print('')print('Die berechneten Populationswerte sind:')print('Anzahl junger Maeuse: ', jung)print('Anzahl erwachsener Maeuse: ', erwachsen)print('Anzahl alter Maeuse: ', alt)Programm mit Fehlern

Jeder macht Fehler! Aufgabe:

Teste, wie sich das Programm verhält. Findest du die Fehler? Worin unterscheiden sie sich?

Page 34: Imperative Programmierung  - mit Python

34 Fehler in Programmen

Programmfenster

Bei einem Syntaxfehler hat man eine Regel der gewählten Programmiersprache nicht beachtet.

Aufgabe:

Welcher Syntaxfehler wird hier angezeigt?

Page 35: Imperative Programmierung  - mit Python

35 Fehler in Programmen

# Eingabeprint('Gib die Werte der Ausgangspopulation ein:')jung = input('Anzahl junger Maeuse: ')erwachsen = input('Anzahl erwachsener Maeuse: ')alt = input('Anzahl alter Maeuse: ')# Verarbeitunghilf = erwachsen*4 + alt*2alt = erwachsen // 3erwachen = jung // 2jung = hilf# Ausgabe:print('')print('Die berechneten Populationswerte sind:')print('Anzahl junger Maeuse: ', jung)print('Anzahl erwachsener Maeuse: ', erwachsen)print('Anzahl alter Maeuse: ', alt)Programmfenster

Laufzeitfehler treten während der Abarbeitung des Programms (zur Laufzeit) auf.

>>> Gib die Werte der Ausgangspopulation ein:Anzahl junger Maeuse: 6Anzahl erwachsener Maeuse: 9Anzahl alter Maeuse: 12Traceback (most recent call last): File ... alt = erwachsen // 3TypeError: unsupported operand type(s) for //: 'str' and 'int'

Ausführfenster

Aufgabe:

Warum kommt es hier zu einem Laufzeitfehler?

Page 36: Imperative Programmierung  - mit Python

36 Fehler in Programmen

# Eingabeprint('Gib die Werte der Ausgangspopulation ein:')jung = int(input('Anzahl junger Maeuse: '))erwachsen = int(input('Anzahl erwachsener Maeuse: '))alt = int(input('Anzahl alter Maeuse: '))# Verarbeitunghilf = erwachsen*4 + alt*2alt = erwachsen // 3erwachen = jung // 2jung = hilf# Ausgabe:print('')print('Die berechneten Populationswerte sind:')print('Anzahl junger Maeuse: ', jung)print('Anzahl erwachsener Maeuse: ', erwachsen)print('Anzahl alter Maeuse: ', alt)Programmfenster

Logische Fehler liegen vor, wenn das System nicht die beabsichtigten Ausgaben erzeugt.

>>> Gib die Werte der Ausgangspopulation ein:Anzahl junger Maeuse: 6Anzahl erwachsener Maeuse: 9Anzahl alter Maeuse: 12

Die berechneten Populationswerte sind:Anzahl junger Maeuse: 60Anzahl erwachsener Maeuse: 9Anzahl alter Maeuse: 3>>> globals(){..., 'erwachsen': 9, 'jung': 60, ..., 'erwachen': 3, ..., 'alt': 3, ..., 'hilf': 60}

Ausführfenster

Aufgabe:

Welcher logische Fehler liegt hier vor?

Page 37: Imperative Programmierung  - mit Python

37 Datentypen

Aufgaben:

(a) Im Testprogramm werden auch die Datentypen der von den Variablen verwalteten Daten ausgegeben. Führe das Programm aus. Erkläre die vom Programm gemachten Ausgaben, wenn du eine Zahl eingibst.

(b) Welche Rolle spielen hier der int-Operator und der str-Operator?

# Eingabeeingabe = input('Anzahl junger Maeuse: ')print(type(eingabe))jung = int(eingabe)print(type(jung))# Verarbeitungerwachsen = jung // 2print(type(erwachsen))# Ausgabe:ausgabe = 'Anzahl erwachsener Maeuse: ' + str(erwachsen)print(type(ausgabe))print(ausgabe)

Programm mit Ausgabe von Datentypen

Zu verarbeitende Daten können von ganz unterschiedlichem Typ sein, z. B. Zahlen, mit denen man rechnen kann, oder Zeichenketten, die man hintereinanderhängen kann. Mit dem Begriff "Datentyp" erfasst man in der Informatik diese unterschiedlichen Typen von Daten.

Page 38: Imperative Programmierung  - mit Python

38

>>> jung = 6>>> jung6>>> type(jung)<class 'int'>>>> erwachsen = jung // 2>>> erwachsen3>>> type(erwachsen)<class 'int'>>>> erwachsen = jung / 2>>> erwachsen3.0>>> type(erwachsen)<class 'float'>

Fachkonzept - Datentyp

Ein Datentyp beschreibt eine Menge von Datenobjekten, die alle die gleiche Struktur haben und mit denen die gleichen Operationen ausgeführt werden können.

# Eingabeeingabe = input('Anzahl junger Maeuse: ')print(type(eingabe))jung = int(eingabe)print(type(jung))# Verarbeitungerwachsen = jung // 2print(type(erwachsen))# Ausgabe:ausgabe = 'Anzahl erwachsener Maeuse: ' + str(erwachsen)print(type(ausgabe))print(ausgabe)>>> Anzahl junger Maeuse: 6<class 'str'><class 'int'><class 'int'><class 'str'>Anzahl erwachsener Maeuse: 3

Page 39: Imperative Programmierung  - mit Python

39 Exkurs: Datentypen in Python

>>> 22

Datentyp: ganze Zahl int

>>> 2.02.0

>>> TrueTrue

>>> 'Hallo!''Hallo!'

>>> ('Hans', 'Meier', 34, 'Koblenz')('Hans', 'Meier', 34, 'Koblenz')

>>> [1, 2, 3, 4, 5][1, 2, 3, 4, 5]

Datentyp: Dezimalzahl

float

Datentyp: Wahrheitswert

bool

Datentyp: Zeichenkette

string

Datentyp: Tupel tuple

Datentyp: Liste list

... ...

>>> "Hallo!"'Hallo!'

Page 40: Imperative Programmierung  - mit Python

40

Exkurs: Typumwandlungen in Python

>>> int("3")3>>> float("3")3.0>>> int(3.0)3>>> int(3.5)3>>> float(3)3.0>>> str(3)'3'

Häufig benötigt man Operatoren, mit denen man aus einem Datenobjekt ein entsprechendes mit einem anderen Datentyp erzeugen kann. Der folgende Python-Dialog zeigt einige Möglichkeiten auf.

>>> list("[1, 2, 3]")['[', '1', ',', ' ', '2', ',', ' ', '3', ']']>>> eval("[1, 2, 3]")[1, 2, 3]

Page 41: Imperative Programmierung  - mit Python

41 Wiederholte Berechnungen

Zur Simulation der Entwicklung der Mäusepopulation haben wir bisher ein Programm entwickelt, das die Berechnungen für einen einzigen Simulationsschritt durchführt. Interessanter wird es, wenn die Simulation über mehrere Schritte laufen soll.

Aufgabe:

Wie müsste man das Programm ergänzen, wenn genau 10 (bzw. 100) Simulationsschritte durchgeführt werden sollen? Warum ist der gezeigte Lösungsansatz nicht sonderlich praktisch?

# Eingabe...# Verarbeitungschritt = 0hilf = erwachsen*4 + alt*2alt = erwachsen // 3erwachsen = jung // 2jung = hilfschritt = schritt + 1hilf = erwachsen*4 + alt*2alt = erwachsen // 3erwachsen = jung // 2jung = hilfschritt = schritt + 1hilf = erwachsen*4 + alt*2alt = erwachsen // 3erwachsen = jung // 2jung = hilfschritt = schritt + 1...# Ausgabe:...

Programm mit einer Folge von Zuweisungen

Page 42: Imperative Programmierung  - mit Python

42 Wiederholte Berechnungen

Aufgaben:

(a) Erkläre, warum der Si-mulationsschritt hier genau 10 mal durchgeführt wird.

(b) Ändere das gezeigte Programm so ab, dass folgende Aufgaben erledigt werden können:

- In jedem Berechnungs-schritt sollen die aktuellen Populationswerte ausgegeben werden.

- Der Benutzer kann selbst eingeben, wie viele Schritte simuliert werden sollen.

- Der Benutzer kann eine bestimmte Gesamtanzahl von Mäusen eingeben, bis zu der die Simulation durchgeführt werden soll. Ausgabe: Schritte

# Eingabejung = int(input("Anzahl der jungen Maeuse: "))erwachsen = int(input("Anzahl der erwachsenen Maeuse: "))alt = int(input("Anzahl der alten Maeuse: "))

# Verarbeitungschritt = 0while schritt < 10: hilf = erwachsen*4 + alt*2 alt = erwachsen // 3 erwachsen = jung // 2 jung = hilf schritt = schritt + 1 # Ausgabe:print("Neue Populationswerte:")print("Anzahl der Schritte: ", schritt)print("Anzahl junger Maeuse: ", jung)print("Anzahl erwachsener Maeuse: ", erwachsen)print("Anzahl alter Maeuse: ", alt)

Programm mit Wiederholungsanweisung

Page 43: Imperative Programmierung  - mit Python

43 Fachkonzept - Wiederholung

Eine Solange-Wiederholung besteht aus einer Bedingung und einer Anweisungssequenz. Solange die Bedingung erfüllt ist, wird die Anweisungssequenz ausgeführt.

SOLANGE [Bedingung]: [Anweisungssequenz]

Flussdiagramm

while [Bedingung]: [Anweisungssequenz]

DoppelpunktEinrückung

Schlüsselwort

Struktogramm

Python-Syntax

Aufbau

Page 44: Imperative Programmierung  - mit Python

44 Übung zur Vernetzung

Der Body-Mass-Index wird mit der folgenden Formel berechnet.

(a) Teste das folgende Programm zur automatisierten Berechnung des BMI. Welche Nachteile hat das Programm?

a = 100b = 1.8c = a / (b*b)print(a, b, c)

(b) Erstelle selbst ein benutzer- und entwicklerfreudliches Programm zur automatisierten BMI-Berechnung.

Page 45: Imperative Programmierung  - mit Python

45 Teil 2

Zufallsexperimente - Ablaufmodellierung mit Kontrollstrukturen

Page 46: Imperative Programmierung  - mit Python

46 Craps

Craps ist ein in den USA beliebtes Glücksspiel, das mit 2 Würfeln gespielt wird.

Die beiden Würfel werden geworfen. Wenn die Augensumme 7 oder 11 beträgt, hat man gewonnen. Wenn die Augensumme 2, 3 oder 12 beträgt, hat man verloren. Ansonsten wird weitergewürfelt, bis eine Entscheidung gefallen ist. Bei jedem weiteren Wurf der beiden Würfel hat man verloren, wenn eine 7 fällt, und gewonnen, wenn die neue Augensumme gleich der Augensumme im ersten Wurf ist.

Hier stellt sich die Frage, ob das Spiel fair ist, oder ob der Spieler bzw. der Spielanbieter auf lange Sicht im Vorteil ist. Orientierung:

Um zu beurteilen, ob das Spiel fair ist, muss man das Spiel sehr oft ausführen (z.B. 1000 mal).

Ziel ist es, ein Programm zu entwickeln, mit dem man das Spiel wiederholt ausführen kann.

Page 47: Imperative Programmierung  - mit Python

47 Erzeugung von Zufallszahlen

Programmiersprachen stellen in der Regel einen Baustein zur Erzeugung von (Pseudo-) Zufallszahlen zur Verfügung. In Python heißt dieser Baustein random und kann wie folgt benutzt werden.

>>> from random import randint>>> randint(1, 6)2>>> randint(1, 6)5>>> randint(2, 5)5>>> augen = randint(1, 6)>>> augen6

Erzeugung von Zufallszahlen

Page 48: Imperative Programmierung  - mit Python

48 Simulation eines Münzwurfs

Aufgabe:

Welche Ausgaben werden nach dem Flussdiagramm erzeugt, wenn der Benutzer als Tipp ein 'K' eingibt und die Zufallszahl 1 erzeugt wird?

Welche Abläufe und Ausgaben sind hier denkbar. Begründe mit den Fallunterscheidungen im Flussdiagramm.

Page 49: Imperative Programmierung  - mit Python

49 Simulation eines Münzwurfs

Aufgabe:

(a) Teste zunächst das gezeigte Programm. Welcher Teil des Struktogramms wird hier implementiert?

(b) Ergänze den noch fehlenden Teil. Achte ganz genau auf Doppelpunkte und die Einrückungen (um 4 Einheiten).

from random import randint# Eingabetipp = input('Kopf (K) oder Zahl (Z): ')# Verarbeitung mit Ausgabezufallszahl = randint(0, 1)if zufallszahl == 0: print('Kopf ist gefallen.') seite = 'K'else: print('Zahl ist gefallen.') seite = 'Z'# Ausgabe# ...

Page 50: Imperative Programmierung  - mit Python

50 Simulation eines Münzwurfs

Aufgabe:

Das folgende Programm enthält weitere Fallunterscheidungen. Kannst du das Flussdiagramm so erweitern, dass es zum erweiterten Programm passt. Beschreibe anhand von Fallbeispielen, wie sich das erweiterte Programm verhält.

from random import randint# Eingabetipp = input('Kopf (K) oder Zahl (Z): ')if tipp == 'k': tipp = 'K'if tipp == 'z': tipp = 'Z'# Verarbeitung mit Ausgabezahl = randint(0, 1)if zahl == 0: print('Kopf ist gefallen.') seite = 'K'else: print('Zahl ist gefallen.') seite = 'Z'# Ausgabe# ...

Page 51: Imperative Programmierung  - mit Python

51 Simulation eines Würfelwurfs

Aufgabe:

(a) Verdeutliche die hier vorgesehenen Abläufe mit Struktogrammen.

(b) Das Programm links ist noch nicht ganz fertig erstellt. Ergänze den fehlenden Teil (siehe # ...) und teste das Programm. Vergleiche es mit dem Programm rechts.

from random import randint# Verarbeitungaugen = randint(1, 6)if augen == 1: bild = 'o'else: if augen == '2': bild = 'oo' else: if augen == '3': bild = 'ooo' else: # ...# Ausgabeprint(bild)

from random import randint# Verarbeitungaugen = randint(1, 6)if augen == 1: bild = 'o'if augen == '2': bild = 'oo'if augen == '3': bild = 'ooo'if augen == '4': bild = 'oooo'if augen == '5': bild = 'ooooo'if augen == '6': bild = 'oooooo'# Ausgabeprint(bild)

Page 52: Imperative Programmierung  - mit Python

52 Ein vereinfachtes Craps-Spiel

Aufgabe:

Entwickle ein Programm zur Simulation der folgenden vereinfachten Version des Craps-Spiels:

Zwei Würfel werden geworfen. Wenn die Augensumme 7 oder 11 beträgt, hat man gewonnen. Wenn die Augensumme 2, 3 oder 12 beträgt, hat man verloren. Ansonsten wird nochmal gewürfelt. Man hat dann gewonnen, wenn die neue Augensumme der Augensumme im ersten Wurf entspricht, ansonsten hat man verloren.

Beginne zunächst mit einem Struktogramm. Übersetze es dann in ein Programm.

Page 53: Imperative Programmierung  - mit Python

53 Fachkonzept - Fallunterscheidung

Eine Fallunterscheidung dient dazu, alternative Abläufe zu beschreiben.

Page 54: Imperative Programmierung  - mit Python

54 Fachkonzept - Fallunterscheidung

Eine Fallunterscheidung dient dazu, alternative Abläufe zu beschreiben.

zweiseitige Fallunterscheidun

g

einseitige Fallunterscheidun

g

WENN [Bedingung]: [Anweisungssequenz]SONST: [Anweisungssequenz]

WENN [Bedingung]: [Anweisungssequenz]

Page 55: Imperative Programmierung  - mit Python

55 Fachkonzept - Fallunterscheidung

Eine Fallunterscheidung dient dazu, alternative Abläufe zu beschreiben.

if [Bedingung]: [Anweisungssequenz]else: [Anweisungssequenz]

if [Bedingung]: [Anweisungssequenz]

Doppelpunkt

if zahl == 0: print('Kopf ist gefallen.') seite = 'K'else: print('Zahl ist gefallen.') seite = 'Z'

if tipp == 'k': tipp = 'K'if tipp == 'z': tipp = 'Z'

Einrückung

Schlüsselwort

zweiseitige Fallunterscheidun

g

einseitige Fallunterscheidun

g

Page 56: Imperative Programmierung  - mit Python

56

Exkurs: Mehrfachfallunterscheidung

augen = randint(1, 6)if augen == 1: bild = 'o'else: if augen == '2': bild = 'oo' else: if augen == '3': bild = 'ooo' else: # ...

augen = randint(1, 6)if augen == 1: bild = 'o'elif augen == '2': bild = 'oo'elif augen == '3': bild = 'ooo'elif augen == '4': bild = 'oooo'elif augen == '5': bild = 'ooooo'else: bild = 'oooooo'

if [Bedingung]: [Anweisungssequenz]elif [Bedingung]: [Anweisungssequenz]elif [Bedingung]: [Anweisungssequenz]...else: [Anweisungssequenz]

Doppelpunkt

Einrückung

Schlüsselwort

Page 57: Imperative Programmierung  - mit Python

57 Würfel wiederholt werfen

Beim Spiel "Mensch ärgere dich nicht" darf man erst loslegen, wenn man eine 6 gewürferlt hat. Manchmal dauert das ziemlich lang. Wie lang - das soll mit einem Programm hier untersucht werden.

Aufgabe:

Erkläre zunächst anhand der Diagramme, wie die Anzahl der benötigten Würfelwürfe hier bestimmt wird. Teste anschließend das gezeigte Programm. Ergänze es so, dass alle Würfelergebnisse zur Kontrolle ausgegeben werden. from random import randint# Verarbeitungaugenzahl = randint(1, 6)zaehler = 1while augenzahl != 6: augenzahl = randint(1, 6) zaehler = zaehler + 1# Ausgabeprint('Anzahl der Versuche: ', zaehler)

Page 58: Imperative Programmierung  - mit Python

58 Würfel wiederholt werfen

Aufgabe

Untersuche mit einem Programm, ob der mit dem Zufallsgenerator von Python simulierte Würfel fair ist. Hierzu soll ein Würfel 1000 mal (bzw. eine vom Benutzer eingegebene Anzahl mal) geworfen werden. Dabei soll mitgezählt werden, wie oft eine 6 fällt. Ausgegeben werden soll die Gesamtanzahl der Würfe und die Anzahl der Treffer (hier: 6). Wie kann man aus den beiden Zahlen auf Fairness schließen?

Aufgabe

Entwickle ein Programm, mit dem man herausfinden kann, wie oft man durchschnittlich würfeln muss, bis man eine 6 erhält. Benutze hierzu zwei ineinander geschachtelte Wiederholungen. Beginne mit einem Struktogramm oder Flussdiagramm. Wenn die Ablauflogik stimmt, dann übersetze das Diagramm in ein Programm.

Page 59: Imperative Programmierung  - mit Python

59 Fachkonzept - Wiederholung

Bei der automatisierten Verarbeitung von Daten kommt es sehr oft vor, dass dieselben Anweisungen in einer Art Schleife wiederholt ausgeführt werden. Das folgende Flussdiagramm zeigt eine solche Verarbeitung mit Wiederholung.

...while augenzahl != 6: augenzahl = randint(1, 6) zaehler = zaehler + 1...

Page 60: Imperative Programmierung  - mit Python

60 Fachkonzept - Wiederholung

Eine Solange-Wiederholung besteht aus einer Bedingung und einer Anweisungssequenz. Solange die Bedingung erfüllt ist, wird die Anweisungssequenz ausgeführt.

SOLANGE [Bedingung]: [Anweisungssequenz]

Flussdiagramm

while [Bedingung]: [Anweisungssequenz]

DoppelpunktEinrückung

Schlüsselwort

Struktogramm

Python-Syntax

Aufbau

Page 61: Imperative Programmierung  - mit Python

61 Exkurs - Kontrollstrukturen

Kontrollstrukturen sind Ablaufbausteine, die dazu dienen, die Reihenfolge der Abarbeitung von Anweisungen (eines Algorithmus / eines Programms) festzulegen.

Page 62: Imperative Programmierung  - mit Python

62 Exkurs - Struktogramme

Besonders deutlich werden die Ablaufbausteine, wenn man sie mit einer Bildsprache - den sogenannten Struktogrammen - beschreibt.

Page 63: Imperative Programmierung  - mit Python

63 Pasch

Wenn man mehrere Würfel wirft, dann bezeichnet man einen Wurf, bei dem alle Würfel dieselbe Augenzahl liefern, als Pasch. Es dauert manchmal ziemlich lange, bis man einen Pasch beim Würfeln mit 3 (bzw. n) Würfeln erhält. Im Folgenden soll ein Programm entwickelt werden, mit dessen Hilfe man die Anzahl der Versuche durch Simulation bestimmen kann.

from random import randint# Würfelergebnissew1 = randint(1, 6)w2 = randint(1, 6)w3 = randint(1, 6)print(w1, w2, w3)# Bedingungprint((w1 != w2) and (w2 != w3))print((w1 != w2) or (w1 != w3))print(not((w1 == w2) and (w1 == w3)))print(not((w1 == w2) or (w2 == w3)))

Aufgaben

Die Bedingung ist im Algorithmus noch umgangssprachlich in der Form "kein Pasch" dargestellt. Diese Bedingung soll jetzt präzisiert werden. Das folgende Testprogramm gibt die Werte von 4 Bedingungen aus. Welche dieser Bedingungen kann man zur Implementierung von "kein Pasch" benutzen? Implementiere den oben gezeigten Algorithmus.

Page 64: Imperative Programmierung  - mit Python

64 Pasch

Aufgabe:

Was leistet das folgende Programm? Analysiere hierzu den Quelltext und erkläre die einzelnen Anweisungen. Teste anschließend deine Vermutung

from random import randint# Initialisierungn = 5# Verarbeitung (mit Ausgaben)pasch = Truew1 = randint(1, 6)print(w1)for i in range(n-1): w = randint(1, 6) print(w) if w != w1: pasch = False# Ausgabeif pasch: print('Pasch')else: print('kein Pasch')

from random import randint# Verarbeitungpasch = Falseversuche = 0while not pasch: w1 = randint(1, 6) w2 = randint(1, 6) w3 = randint(1, 6) versuche = versuche + 1 if w1 == w2 and w1 == w3: pasch = True# Ausgabeprint(versuche)

Aufgabe:

Was leistet das folgende Programm? Analysiere hierzu den Quelltext und erkläre die einzelnen Anweisungen. Teste anschließend deine Vermutung.

Page 65: Imperative Programmierung  - mit Python

65 Logische Operatoren

A: Die Augenzahl von Würfel 1 ist gleich der Augenzahl von Würfel 2.

B: Die Augenzahl von Würfel 2 ist gleich der Augenzahl von Würfel 3.

"Pasch": A und B

"kein Pasch": (nicht A) oder (nicht B)

a b a and b

False False False

False True False

True False False

True True True

a b a or b

False False False

False True True

True False True

True True True

a not a

False True

True False

Konjunktion

DisjunktionNegation und oder

nicht

Page 66: Imperative Programmierung  - mit Python

66 Fachkonzept - Wahrheitswerte

Zur Beschreibung von Werten von Bedingungen benutzt man die Wahrheitswerte wahr and falsch bzw. True and False.

from random import randint# Initialisierungn = 5 # 5er-Pasch# Verabeitunggefunden = Falseversuche = 0while not gefunden: versuche = versuche + 1 pasch = True w1 = randint(1, 6) for i in range(n-1): w = randint(1, 6) pasch = pasch and (w == w1) if pasch: gefunden = True# Ausgabeprint(versuche)

from random import randint# Verarbeitungw1 = randint(1, 6)w2 = randint(1, 6)w3 = randint(1, 6)versuche = 1while not (w1 == w2 and w1 == w3): w1 = randint(1, 6) w2 = randint(1, 6) w3 = randint(1, 6) versuche = versuche + 1# Ausgabeprint(versuche)

zusammengesetzte Bedingung

logische Variable

Wahrheitswerte treten bei der Auswertung von Bedingungen auf. Wahrheitswerte können aber auch direkt mit logischen Variablen verwaltet werden.

Page 67: Imperative Programmierung  - mit Python

67 Anwendung - Craps

Craps ist ein in den USA beliebtes Glücksspiel, das mit 2 Würfeln gespielt wird.

Die beiden Würfel werden geworfen. Wenn die Augensumme 7 oder 11 beträgt, hat man gewonnen. Wenn die Augensumme 2, 3 oder 12 beträgt, hat man verloren. Ansonsten wird weitergewürfelt, bis eine Entscheidung gefallen ist. Bei jedem weiteren Wurf der beiden Würfel hat man verloren, wenn eine 7 fällt, und gewonnen, wenn die neue Augensumme gleich der Augensumme im ersten Wurf ist.

Hier stellt sich die Frage, ob das Spiel fair ist, oder ob der Spieler bzw. der Spielanbieter auf lange Sicht im Vorteil ist.

Page 68: Imperative Programmierung  - mit Python

68 Anwendung - Craps

Bevor man anfängt, die Durchführung des Spiels zu automatisieren, sollte man das Spiel erst einmal selbst durchführen, um Erfahrungen zu sammeln.

Aufgabe:

Führe das Spiel mehrfach durch. Protokolliere auch die Würfelergebnisse.

Aufgabe:

Die folgende Tabelle zeigt einen möglichen Spielablauf. Ergänze die fehlenden Einträge.

Page 69: Imperative Programmierung  - mit Python

69 Anwendung - Craps

Aufgabe: Im Struktogramm fehlen noch die rechten Seiten der Zuweisungen. Ergänze sie passend. Orientiere dich an der Tabelle oben zum Spielablauf.

Page 70: Imperative Programmierung  - mit Python

70 Anwendung - Craps

Aufgaben:

(a) Übersetze das Struktogramm in ein Programm.

(b) Um zu beurteilen, ob das Spiel fair ist, muss man das Spiel sehr oft ausführen (z.B. 1000 mal). Entwickle ein geeignetes Struktogramm zur wiederholten Ausführung des Spiels. Übersetze es in ein Python-Programm. Führe das entwickelte Programme aus. Jetzt solltest du das Spiel beurteilen können.

Page 71: Imperative Programmierung  - mit Python

71 Das Ziegenproblem

Das Ziegenproblem (vgl. Wikipedia - Ziegenproblem) geht auf eine Spielsituation bei einer amerikanischen Spielshow zurück.

Der Moderator der Spielshow zeigt dem Kandidaten 3 Türen: "Hinter einer der 3 Türen steht der Hauptgewinn, ein Auto. Hinter den beiden anderen Türen sind Ziegen. Welche Tür wählen Sie?" Nachdem sich der Kandidat entschieden hat (z.B. für Tür 1), öffnet der Moderator eine der beiden anderen mit einer Ziege (z.B. Tür 3) und stellt dem Kandidaten die folgende Frage: "Bleiben Sie nun bei Ihrer Wahl oder möchten Sie auf Tür 2 umwählen ?"

Wie soll sich der Kandidat entscheiden? Gibt es für ihn eine Strategie, mit der er eher an das Auto kommt? Orientierung:

Um die beiden Strategien (Wahl beibehalten / Umwahl) besser beurteilen zu können, muss man mit jeder Strategie das Spiel sehr oft ausführen (z.B. 1000 mal).

Ziel ist es, ein Programm zu entwickeln, mit dem man das Spiel mit einer festen Strategie wiederholt ausführen kann.

Page 72: Imperative Programmierung  - mit Python

72 Anwendung - Ziegenproblem

Tür-Auto: 1 Tür-Auto: 2 Tür-Auto: 3

Tür-Kandidat: 1

Tür-Kandidat: 2

Tür-Kandidat: 3

Tür-Mod.: 2|3

Bevor man anfängt, die Durchführung des Spiels zu automatisieren, sollte man erst einmal selbst spielen, um Erfahrungen zu sammeln. Das geht ganz leicht mit Spielkarten und Würfeln.

Schritt 1: Das Auto wird hinter einer Tür versteckt. Der Moderator kann hierzu einen Würfel benutzen, um die Tür zufällig auszuwählen.

Schritt 2: Der Kandidat wählt jetzt eine Tür aus.

Schritt 3: Der Moderator kennt die Tür, hinter der sich das Auto befindet, und die Tür, die der Kandidat ausgewählt hat. Er öffnet jetzt eine Tür, hinter der sich eine Ziege befindet. In der folgenden Tabelle oben sind die Wahlmöglichkeiten des Moderators eingetragen.

Schritt 4: Der Kandidat hat jetzt die Möglichkeit, bei seiner Wahl zu bleiben oder umzuwählen. Wenn man die beiden Strategien vergleichen will, dann sollte man das Spiel mehrfach mit der gleichen Strategie wiederholen.

Schritt 5: Der Moderator öffnet alle Türen und teilt das Ergebnis mit.

Aufgabe:

Ergänze zunächst die oben gezeigte Tabelle. Führe das Spiel mehrfach durch. Hast du bereits eine Vermutung, welche Strategie besser ist?

Tür-Mod.: 3

Page 73: Imperative Programmierung  - mit Python

73 Anwendung - Ziegenproblem

Ein Programm soll das Spiel anbieten und dabei die Rolle des Moderators über-nehmen.

Aufgabe - Ablaufmodellierung:

(a) Im Struktogramm "tuerZiege bestimmen - Fall 1" fehlen moch Angaben in Zuweisungen. Ergänze die fehlenden Angaben.

(b) Erstelle ein entsprechendes Struktogramm für einen der beiden anderen Fälle (das Auto steht hinter Tür 2 bzw. Tür 3).

Page 74: Imperative Programmierung  - mit Python

74 Anwendung - Ziegenproblem

Aufgabe

Entwickle zunächst ein Programm, mit dem man einmal die Aktionen der Spielshow simulieren kann.

Aufgabe

Um die beiden Strategien (Wahl beibehalten / Umwahl) besser beurteilen zu können, muss man mit jeder Strategie das Spiel sehr oft ausführen (z.B. 1000 mal).

Für eine solche wiederholte Ausführung ist es jedoch ungünstig, wenn das Spiel wie bisher interaktiv gestaltet ist.

Ersetze die Eingaben des Kandidaten durch Anweisungen, mit denen die Wahl der Tür mit Hilfe von Zufallszahlen erfolgt.

Führe die entwickelten Programme aus. Jetzt sollte klar sein, für welche Strategie man sich entscheiden sollte.

Page 75: Imperative Programmierung  - mit Python

75 Teil 3

Verschlüsselung -Modularisierung mit Funktionen

Page 76: Imperative Programmierung  - mit Python

76 Veschlüsselung

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

D E F G H I J K L M N O P Q R S T U V W X Y Z A B C

Schlüssel: 3Quelltext:

SALVECAESAR

Geheimtext:VDOYHFDHVDU

PYLZFOWBNQCYBUVNCBLGYCHYAYBYCGMWBLCZNYH

NTCZYLN

VDOYHFDHVD

U

In einer Fallstudie zur Verschlüsselung geht es vor allem darum, Funktionen als eigenständige Programmierbausteine einzuführen, um komplexere Programme besser zu strukturieren und nach dem Bausteinprinzip zu entwickeln.

Page 77: Imperative Programmierung  - mit Python

77 Automatisierte Verschlüsselung

>>> zeichen = 'A'>>> zeichen'A'>>> zahl = ord(zeichen)>>> zahl65>>> neuezahl = zahl + 3>>> neuezahl68>>> neueszeichen = chr(neuezahl)>>> neueszeichen'D'

>>> klartext = 'HALLO'>>> klartext'HALLO'>>> klartext[0]'H'>>> klartext[1]'A'>>> klartext[4]'O'>>> len(klartext)5>>> klartext[len(klartext)-1]'O'>>> geheimtext = ''>>> geheimtext''>>> geheimtext = geheimtext + 'K'>>> geheimtext'K'>>> geheimtext = geheimtext + 'D'>>> geheimtext'KD'

Die Python-Dialoge zeigen, wie man

- Buchstaben verschieben kann,

- wie man auf einzelne Zeichen einer Zeichenkette zugreifen kann,

- wie man neue Zeichketten aufbauen kann.

Aufgabe: Kannst du mit den Informationen ein Programm zum Verschlüsseln von Texten, die nur aus Großbuchstaben bestehen, entwickeln?

Page 78: Imperative Programmierung  - mit Python

78 Automatisierte Verschlüsselung

# Vorgabeklartext = 'HALLO'# Verarbeitunggeheimtext = ''for zeichen in klartext: zahl = ord(zeichen) neuezahl = zahl + 3 if neuezahl > ord('Z'): neuezahl = neuezahl - 26 neuesZeichen = chr(neuezahl) geheimtext = geheimtext + neuesZeichen# Ausgabeprint(geheimtext)

# Vorgabetext = 'Dieser Text müßte "bereingt" werden.'# VerarbeitungtextNeu = ''for zeichen in text: if ord(zeichen) >= ord('A') and \ ord(zeichen) <= ord('Z'): # zeichen ist ein Großbuchstabe textNeu = textNeu + zeichen # ...# Ausgabeprint(text)print(textNeu)

Aufgabe:

Entwickle entsprechend ein Programm zur Entschlüsselung von Texten, die nach dem Caesar-Verfahren verschlüsselt wurden.

Aufgabe:

Wir sind bisher davon ausgegangen, dass ein vorgegebener Text nur aus Großbuchstaben besteht. Einen beliebigen Text müsste man erst einmal in einen Text aus Großbuchstaben umwandeln, um das Verschlüsselungsverfahren anwenden zu können.

Page 79: Imperative Programmierung  - mit Python

79 Fachkonzept - Zeichenkette

Eine Zeichenkette ist eine (evtl. leere) Folge von Zeichen (aus einer vorgegebenen Zeichenmenge), die zu einer Dateneinheit zusammengefasst ist. Der Datentyp Zeichenkette beschreibt die Menge der möglichen Zeichenkette zusammen mit den Operationen, die mit Zeichenketten vorgesehen sind.

>>> z1 = 'Hallo'>>> z1'Hallo'>>> z2 = "Hallo">>> z2'Hallo'>>> z = ''>>> z

>>> text = """Dieser Text geht... über mehrere... Zeilen.""">>> text'Dieser\nText geht\nüber mehrere\nZeilen.'>>> print(text)Dieser Text gehtüber mehrereZeilen.

Darstellung von Zeichenketten

Page 80: Imperative Programmierung  - mit Python

80 Fachkonzept - Zeichenkette

Eine Zeichenkette ist ein sequentielles Datenobjekt, das aus einer Folge einzelner Zeichen besteht. Die Elemente eines solchen sequentiellen Datenobjekts sind der Reihe nach durchnummeriert. Die Nummerierung beginnt dabei mit 0. Die Nummer eines sequentiellen Datenobjekts wird auch Index genannt.

lesender Zugriff auf einzelne Zeichen

>>> klartext = 'HALLO'>>> klartext[0]'H'>>> klartext[1]'A'>>> klartext[4]'O'>>> klartext[5]Traceback (most recent call last): ... klartext[5]IndexError: string index out of range>>> len(klartext)5>>> klartext[len(klartext)-1]'O'

Länge einer Zeichenkette

beachte den Indexbereich

Page 81: Imperative Programmierung  - mit Python

81 Fachkonzept - Zeichenkette

Zeichenketten kann man über den Indexbereich, oder direkt über die einzelnen Zeichen durchlaufen.

# klartext = ...i = 0while i < len(klartext): # verarbeite klartext[i] i = i + 1 Schleife über den Indexbereich

# klartext = ...for zeichen in klartext: # verarbeite zeichen

for-Schleife für sequentielle Datenobjekte

Page 82: Imperative Programmierung  - mit Python

82 Fachkonzept - Zeichenkette

Eine Zeichenkette ist in Python ein nicht-veränderbares Datenobjekt. In Python ist nur ein lesender Zugriff auf einzelne Zeichen einer Zeichenkette möglich ist. Abändern kann man einzelne Zeichen einer Zeichenkette mit Hilfe von Zuweisungen nicht. Eine veränderte Zeichenkette erhält man nur, indem man eine neue Zeichenkette - z.B. mit dem Konkatenationsoperator - aufbaut.

>>> klartext = 'HALLO'>>> klartext[1]'A'>>> klartext[1] = 'E'TypeError: 'str' object does not support item assignment

kein schreibender Zugriff erlaubt

>>> klartext = 'HALLO'>>> klartextNeu = ''>>> klartextNeu = klartextNeu + klartext[0]>>> klartextNeu = klartextNeu + 'E'>>> klartextNeu'HE'

Zusammenfügen von Zeichenketten

Page 83: Imperative Programmierung  - mit Python

83 Strukturierung des Programmstext = 'Alles Käse!'print(text)textNeu = ''for zeichen in text: if ord(zeichen) >= ord('A') and ord(zeichen) <= ord('Z'): # zeichen ist ein Großbuchstabe textNeu = textNeu + zeichen elif ord(zeichen) >= ord('a') and ord(zeichen) <= ord('z'): # zeichen ist ein Kleinbuchstabe neuesZeichen = chr(ord(zeichen)-32) textNeu = textNeu + neuesZeichen elif zeichen == 'Ä' or zeichen == 'ä': textNeu = textNeu + 'AE' elif zeichen == 'Ö' or zeichen == 'ö': textNeu = textNeu + 'OE' elif zeichen == 'Ü' or zeichen == 'ü': textNeu = textNeu + 'UE' elif zeichen == 'ß': textNeu = textNeu + 'SS'klartext = textNeuprint(klartext)geheimtext = ''for zeichen in klartext: zahl = ord(zeichen) neuezahl = zahl + 3 if neuezahl > ord('Z'): neuezahl = neuezahl - 26 neuesZeichen = chr(neuezahl) geheimtext = geheimtext + neuesZeichenprint(geheimtext)...

...klartext = ''for zeichen in geheimtext: zahl = ord(zeichen) neuezahl = zahl - 3 if neuezahl < ord('A'): neuezahl = neuezahl + 26 neuesZeichen = chr(neuezahl) klartext = klartext + neuesZeichenprint(klartext)

Wenn Programme weiter wachsen - z.B. auf mehrere Millionen Programmzeilen -, dann kann keiner mehr alles Details eines Programms überblicken. Man benötigt dann Verfahren, um das Ganze in übersichtliche Programmeinheiten zu zerlegen.

Aufgabe: Zerlege das Programm in sinnvolle Einheiten. Verdeutliche die Zerlegung durch Kommentare.

Page 84: Imperative Programmierung  - mit Python

84

Zerlegung in Verarbeitungseinheiten

text = 'Alles Käse!'print(text)

# Text entschlüsselnklartext = ''for zeichen in geheimtext: zahl = ord(zeichen) neuezahl = zahl - 3 if neuezahl < ord('A'): neuezahl = neuezahl + 26 neuesZeichen = chr(neuezahl) klartext = klartext + neuesZeichenprint(klartext)

# Text bereinigentextNeu = ''for zeichen in text: if ord(zeichen) >= ord('A') and ord(zeichen) <= ord('Z'): # zeichen ist ein Großbuchstabe textNeu = textNeu + zeichen elif ord(zeichen) >= ord('a') and ord(zeichen) <= ord('z'): # zeichen ist ein Kleinbuchstabe neuesZeichen = chr(ord(zeichen)-32) textNeu = textNeu + neuesZeichen elif zeichen == 'Ä' or zeichen == 'ä': textNeu = textNeu + 'AE' elif zeichen == 'Ö' or zeichen == 'ö': textNeu = textNeu + 'OE' elif zeichen == 'Ü' or zeichen == 'ü': textNeu = textNeu + 'UE' elif zeichen == 'ß': textNeu = textNeu + 'SS'klartext = textNeuprint(klartext)

# Text verschlüsselngeheimtext = ''for zeichen in klartext: zahl = ord(zeichen) neuezahl = zahl + 3 if neuezahl > ord('Z'): neuezahl = neuezahl - 26 neuesZeichen = chr(neuezahl) geheimtext = geheimtext + neuesZeichenprint(geheimtext)

Page 85: Imperative Programmierung  - mit Python

85

Eigenständige Verarbeitungseinheit

def verschluesselterText(klartext): geheimtext = '' for zeichen in klartext: zahl = ord(zeichen) neuezahl = zahl + 3 if neuezahl > ord('Z'): neuezahl = neuezahl - 26 neuesZeichen = chr(neuezahl) geheimtext = geheimtext + neuesZeichen return geheimtext>>> verschluesselterText('HALLO')'KDOOR'>>> verschluesselterText('CAESAR')'FDHVDU'

Funktionsdefinition

# Text verschlüsselngeheimtext = ''for zeichen in klartext: zahl = ord(zeichen) neuezahl = zahl + 3 if neuezahl > ord('Z'): neuezahl = neuezahl - 26 neuesZeichen = chr(neuezahl) geheimtext = geheimtext + neuesZeichenprint(geheimtext)

Funktionsaufruf

Funktion

Aufgabe:Entwickle und teste analog Funktionsdefinitionen zu den Funktionen entschluesselterText und bereinigterText.

Page 86: Imperative Programmierung  - mit Python

86

Eigenständige Verarbeitungseinheit

# Funktionsdefinitionen

def verschluesselterText(klartext): geheimtext = '' for zeichen in klartext: zahl = ord(zeichen) neuezahl = zahl + 3 if neuezahl > ord('Z'): neuezahl = neuezahl - 26 neuesZeichen = chr(neuezahl) geheimtext = geheimtext + neuesZeichen return geheimtext

def entschluesselterText(geheimtext): # ... return klartext

def bereinigterText(text): # ... return textNeu

# Testprogramm

text1 = 'Alles Käse!'text2 = bereinigterText(text1)text3 = verschluesselterText(text2)text4 = entschluesselterText(text3)print(text1)print(text2)print(text3)print(text4)

Funktionsdefinition

Funktionsaufruf

Aufgabe:Ergänze die fehlenden Teile und speichere den gesamten Quelltext in einer Datei ab. Teste das Programm - auch mit anderen Texten.

Page 87: Imperative Programmierung  - mit Python

87 Schachtelung von Funktionen# Funktionsdefinitionen

def verschluesseltesZeichen(zeichen): zahl = ord(zeichen) neuezahl = zahl + 3 if neuezahl > ord('Z'): neuezahl = neuezahl - 26 neuesZeichen = chr(neuezahl) return neuesZeichen

def verschluesselterText(klartext): for zeichen in klartext: neuesZeichen = verschluesseltesZeichen(zeichen) geheimtext = geheimtext + neuesZeichen return geheimtext

...

# Testprogramm

text1 = 'Alles Käse!'text2 = bereinigterText(text1)text3 = verschluesselterText(text2)text4 = entschluesselterText(text3)print(text1)print(text2)print(text3)print(text4)

Funktionsdefinition

Funktionsaufruf

Aufgabe:Ergänze die fehlenden Teile und speichere den gesamten Quelltext in einer Datei ab. Teste das Programm - auch mit anderen Texten.

Page 88: Imperative Programmierung  - mit Python

88 Datenübergabe mit Parametern

# Funktionsdefinitionen

def verschluesseltesZeichen(zeichen, schluessel): # ... return neuesZeichen

def verschluesselterText(klartext, schluessel): # ... return geheimtext

...

# Testprogramm

text1 = 'Alles Käse!'text2 = bereinigterText(text1)text3 = verschluesselterText(text2, 4)text4 = entschluesselterText(text3, 4)print(text1)print(text2)print(text3)print(text4)

Funktionsdefinition

Funktionsaufruf

Aufgabe:An welchen Stellen im Quelltext muss die konkrete Verschiebezahl 3 durch die Funktionsvariable schluessel ersetzt werden? Probiere das aus und teste auch andere Verschiebezahlen.

Page 89: Imperative Programmierung  - mit Python

89 Funktionen

Eine Funktion ist eine Verarbeitungseinheit, die übergebene Daten verarbeitet und den berechneten Funktionswert als Ergebnis zurückgibt. Die Verarbeitung wird über eine Funktionsdefinition (man sagt oft auch Funktionsdeklaration) festgelegt. Aktiviert wird eine Verarbeitung durch einen Funktionsaufruf.

def verschluesselterText(klartext, schluessel): geheimtext = '' for zeichen in klartext: zahl = ord(zeichen) neuezahl = zahl + schluessel if neuezahl > ord('Z'): neuezahl = neuezahl - 26 neuesZeichen = chr(neuezahl) geheimtext = geheimtext + neuesZeichen return geheimtext

Funktionsaufruf

Funktionsdefinition

>>> verschluesselterText('HALLO', 4)'LEPPS'

Doppelpunkt

Einrückung

Schlüsselwort

Funktionsname(Parameter)

Page 90: Imperative Programmierung  - mit Python

90 Parameter

Parameter sind Variablen, mit deren Hilfe die zur Verarbeitung übergebenen Daten bei einer Funktion verwaltet werden.

def verschluesselterText(klartext, schluessel): ... return geheimtext

Parameter

>>> verschluesselterText('HALLO', 4)'LEPPS'

aktuelle Daten

FunktionsaufrufFunktionsdefinitio

n

verschluesselterText

'KDOOR'

'HALLO' text

return ...

Parameter

Daten-übergabe

Daten-rückgabe

zu verarbeitende Daten

zurück-gelieferte

Daten

Page 91: Imperative Programmierung  - mit Python

91 Übungen

Aufgabe:

A. verschlüsselt ihre Texte, indem sie sie einfach umdreht. Entwickle eine geeignete Funktionsdefinition und teste die Funktion mit verschiedenen Funktionsaufrufen.

Aufgabe:

B. verfremdet ihre Texte, indem sie alle vorkommenden Vokale durch einen vorgegebenen ersetzt. Entwickle eine geeignete Funktionsdefinition und teste die Funktion mit verschiedenen Funktionsaufrufen.

Page 92: Imperative Programmierung  - mit Python

92 Übungen

Aufgabe: Analysiere die Funktionsdefinitionen und ergänze den folgenden Python-Dialog. Überprüfe die Ergebnisse mit Python. Begründe: Man kann zum Ver- und Entschlüsseln von Texten nach der Verschiebemethode dieselben Funktionen benutzen.def verschobenesZeichen(zeichen, verschiebezahl): zahl = ord(zeichen) neuezahl = zahl + verschiebezahl if neuezahl > ord('Z'): neuezahl = neuezahl - 26 if neuezahl < ord('A'): neuezahl = neuezahl + 26 neuesZeichen = chr(neuezahl) return neuesZeichen

def verschobenerText(text, verschiebezahl): neuerText = '' for zeichen in text: neuesZeichen = verschobenesZeichen(zeichen, verschiebezahl) neuerText = neuerText + neuesZeichen return neuerText

>>> verschobenesZeichen('H', 1)???>>> verschobenesZeichen('H', -2)???>>> verschobenerText('HUND', 7)???>>> verschobenerText('OBUK', 19)???

Page 93: Imperative Programmierung  - mit Python

93 Laden und Speicherndef verschluesseltesZeichen(zeichen, schluessel): # ...

def verschluesselterText(klartext, schluessel): # ...

def entschluesseltesZeichen(zeichen, schluessel): # ...

def entschluesselterText(geheimtext, schluessel): # ...

def bereinigterText(text): # ...

def textAusDatei(dateiname): datei = open(dateiname, 'r', encoding='iso-8859-1') text = datei.read() datei.close() return text

def textInDateiSpeichern(dateiname, text): datei = open(dateiname, 'w', encoding='iso-8859-1') datei.write(text) datei.close()

# Testprogrammtext1 = textAusDatei('klartext.txt')text2 = bereinigterText(text1)text3 = verschluesselterText(text2, 5)textInDateiSpeichern('geheimtext.txt', text3)

Aufgabe:Teste das Programm. Bevor das möglich ist, solltest du eine Datei 'klartext.txt' anlegen und einen Text in dieser Datei speichern. Beachte, dass du die im Quelltext angegebene Codierung (hier: iso-8859-1) verwendest. Beachte auch, dass das Python-Programm und die Datei sich im gleichen Verzeichnis befinden. Wenn das Programm ausgeführt ist, dann schaue in die Datei 'geheimtext.txt' rein. Hier müsste jetzt der verschlüsselte Text zu finden sein.

Aufgabe:Die Funktionen textAusDatei und textInDateiSpeichern unterscheiden sich in einem wesentlichen Punkt. Das sieht man in den Funktionsdefinitionen und auch bei den Funktionsaufrufen. Zudem wird es durch die Namensgebung angedeutet. Worin besteht der Unterschied?

Page 94: Imperative Programmierung  - mit Python

94 Prozedur

Eine Prozedur ist eine Funktion, die keine Rückgabe erzeugt.

Funktion mit Rückgabe

Funktion ohne Rückgabe

text = textAusDatei('klartext.txt')# ...textInDateiSpeichern('geheimtext.txt', 'ZPTZHSHIPT')

Ein Aufruf der Funktion textAusDatei liefert ein Ergebnis, das verwaltet oder weiterverarbeitet werden muss. Der Funktionsaufruf textAusDatei('klartext.txt') ist hier daher (als Term auf der rechten Seite) in eine Zuweisung eingebunden.

Ganz anders wird die Funktion textInDateiSpeichern benutzt. Der Aufruf textInDateiSpeichern('geheimtext.txt', 'ZPTZHSHIPT') erzeugt kein Ergebnis und stellt eine eigenständige Anweisung dar.

Funktionsaufruf

Prozeduraufruf

Page 95: Imperative Programmierung  - mit Python

95 Häufigkeitsanalyse

XREQXRCCZVEZJKZEUIVZKVZCVXVKVZCKVZEVEURMFESVNFYEVEUZVSVCXVIUVEREUVIVEUZVRHLZKREVILEUUVEUIZKKVEUZVUZVZEZYIVIVZXVEVEJGIRTYVBVCKVEXVEREEKNVIUVELEUZELEJVIVIXRCCZVIYVZJJVEJZVRCCVLEKVIJTYVZUVEJZTYLEKVIVZEREUVIZEJGIRTYVXVNFYEYVZKVELEUXVJVKQVEUZVXRCCZVIKIVEEKMFEUVERHLZKREVIEUVIWCLJJXRIFEEVMFEUVESVCXVIEUZVDRIEVLEUUZVJVZEVUZVKRGWVIJKVERCCUZVJVIJZEUUZVSVCXVILEUQNRIUVJNVXVENVZCJZVMFEUVIBLCKLILEUCVSVEJNVZJVUVIIFVDZJTYVEGIFMZEQRDNVZKVJKVEVEKWVIEKJZEUJVYIJVCKVEBRLWCVLKVQLUZVJVEBFDDVELEUURJNRJQLIMVINVZTYCZTYLEXUVIXVDLVKVIWLVYIKVZEWLVYIVELEUNVZCJZVUVEXVIDREVEUZVAVEJVZKJUVJIYVZEVJCVSVELEUDZKUVEVEJZVJKRVEUZXBIZVXWLVYIVEJVYIERYVJZEURLJUZVJVDXILEULVSVIKIVWWVERLTYUZVYVCMVKZVIUZVLVSIZXVEXRCCZVIREKRGWVIBVZKNVZCJZVJZTYZEWRJKKRVXCZTYVEXVWVTYKVEDZKUVEXVIDREVEDVJJVENFSVZJZVUZVJVVEKNVUVIMFEZYIVDXVSZVKWVIEYRCKVEFUVIJVCSJKZEUVIVEXVSZVKBRVDGWVEVZEKVZCURMFEUVENZVXVJRXKUZVXRCCZVISVNFYEVEWZEUVKJVZEVELIJGILEXREUVIIYFEVNZIUSVXIVEQKMFEUVIXRIFEEVUVDFQVRELEUUVDXVSZVKUVISVCXVIVIJKIVTBKJZTYMFEUVEJVHLREVIELEUYVCMVKZVIEYZESZJQLDIYVZELEUQVZXKERTYEFIUVEURJXVSZVKUVISVCXVISVXZEEKREUVERVLJJVIJKVEXIVEQVEXRCCZVEJVIJKIVTBKJZTYSZJREUVELEKVIVEKVZCUVJIYVZEJLEUCZVXKERTYEFIUFJKVERHLZKREZVEVIJKIVTBKJZTYMFEUVDWCLJJXRIFEEVSZJREUZVGPIVERVVELEUQLUVDAVEZXVEKVZCUVJFQVREJUVISZJJGREZVEIVZTYKVJCZVXKZEIZTYKLEXEFIUNVJKVE

Der folgende Geheimtext soll entschlüsselt werden. Wir gehen davon aus, dass der Geheimtext mit der Verschiebemethode (nach Caesar, aber mit belielibiger Verschiebezahl) erzeugt wurde. Leider ist der Schlüssel (d.h. die Verschiebezahl) nicht bekannt. Warum könnte "Buchstaben zählen" hier weiterhelfen?

Page 96: Imperative Programmierung  - mit Python

96 Häufigkeitsanalyse

Wenn ein Programmteil - bis auf geringfügige Abweichungen - mehrfach in einem Programm vorkommt, spricht man von Codeduplizierung.

Codeduplizierung versucht man in der Regel zu vermeiden. Zum einen werden Programme hierdurch in der Regel kürzer. Zum anderen erspart man sich Arbeit, wenn der Programmteil noch einmal überarbeitet wird. Man muss dann nur einen einzigen Programmteil bearbeiten anstatt mehrere.

text = """ABRAKADABRASIMSALABIM"""

anzahl = 0for zeichen in text: if zeichen == 'A': anzahl = anzahl + 1print('A', ':', anzahl)

anzahl = 0for zeichen in text: if zeichen == 'B': anzahl = anzahl + 1print('B', ':', anzahl)

anzahl = 0for zeichen in text: if zeichen == 'C': anzahl = anzahl + 1print('C', ':', anzahl)...

Page 97: Imperative Programmierung  - mit Python

97 Häufigkeitsanalyse

Aufgabe:

(a) Vergleiche das vorliegende Program (mit Funktionsdefinition) und das oben gezeigte (ohne Funktionsdefinition). Was ist der Vorteil des vorliegenden Programms? Siehst du auch noch Nachteile? (s.u.)

(b) Benutze das vorliegende Programm, um den oben gezeigten verschlüsselten Text zu analysieren. Mit den erzielten Häufigkeitswerten kannst du dann bestimmt den noch fehlenden Schlüssel ermitteln.

def haeufigkeit(buchstabe, text): anzahl = 0 for zeichen in text: if zeichen == buchstabe: anzahl = anzahl + 1 return anzahl

# Testprogramm

aktuellerText = """ABRAKADABRASIMSALABIM"""

print('A', ':', haeufigkeit('A', aktuellerText))print('B', ':', haeufigkeit('B', aktuellerText))print('C', ':', haeufigkeit('C', aktuellerText))print('D', ':', haeufigkeit('D', aktuellerText))# ...

Page 98: Imperative Programmierung  - mit Python

98 Häufigkeitsanalyse

Aufgabe:

Du kannst die Folge von print-Anweisungen im oben gezeigten Programm auch durch eine geeignete Wiederholungsanweisung ersetzen. Ergänze hierzu das folgende Programm.

Bemerkung: Das hier entwickelte Programm hat noch den Nachteil, dass der zu analysierende Text für jeden Buchstaben einmal durchlaufen wird. Natürlich geht das auch noch einfacher. Wenn du dich bereits mit Listen auskennst, dann kannst du ja versuchen, das Programm so zu gestalten, dass man mit einem Durchlauf über den Text auskommt.

...

# Testprogramm

aktuellerText = """ABRAKADABRASIMSALABIM"""

abc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'for zeichen in abc: ...

Page 99: Imperative Programmierung  - mit Python

99 Verwendung von Funktionen

Strukturierung des Quelltextes

Programme werden zur Steuerung von Computern entwickelt. Einem Computer ist es egal, wie lang und unübersichtlich ein Programm ist. Der Computer muss ja nur die Anweisungen des Programms Schritt für Schritt abarbeiten.

Programme werden (in der Regel) von Menschen entwickelt. Wenn Programme zu unübersichtlich werden, dann können sich leicht Fehler einschleichen. Je unübersichtlicher ein Programm ist, desto schwieriger gestaltet sich die Fehlersuche. Ein zentrales Ziel bei der Programmentwicklung ist es daher, den Quelltext möglichst strukturiert zu gestalten.

Funktionen sind ein Mittel zur Struktur-ierung von Programmen. Mit Funktionen kann man Verarbeitungseinheiten bilden und diese als Unterprogramme in einem größeren Programm verwenden.

# Funktionsdefinitionen

def verschluesseltesZeichen(zeichen, schluessel): # ... return neuesZeichen

def verschluesselterText(klartext, schluessel): # ... return geheimtext

...

# Testprogramm

text1 = 'Alles Käse!'text2 = bereinigterText(text1)text3 = verschluesselterText(text2, 4)text4 = entschluesselterText(text3, 4)print(text1)print(text2)print(text3)print(text4)

Page 100: Imperative Programmierung  - mit Python

100 Verwendung von Funktionen

Vermeidung von Codeduplizierung

Wenn ein Programmteil - bis auf geringfügige Abweichungen - mehrfach in einem Programm vorkommt, spricht man von Codeduplizierung.

Codeduplizierung versucht man in der Regel zu vermeiden. Zum einen werden Programme hierdurch in der Regel kürzer. Zum anderen erspart man sich Arbeit, wenn der Programmteil noch einmal überarbeitet wird. Man muss dann nur eine einzige Verarbeitungseinheit bearbeiten anstatt mehrere.

Funktionen helfen bei der Vermeidung von Codeduplizierung. Eine Verarbeitungseinheit, die in ähnlicher Form mehrfach in einem Programm vorkommt, lässt sich mit einer Funktion als eigenständiges Unterprogramm konzipieren.

def haeufigkeit(buchstabe, text): anzahl = 0 for zeichen in text: if zeichen == buchstabe: anzahl = anzahl + 1 return anzahl

# Testprogramm

aktuellerText = """ABRAKADABRASIMSALABIM"""abc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'for zeichen in abc: hZeichen = haeufigkeit(zeichen, aktuellerText) print(zeichen, ':', hZeichen)

Page 101: Imperative Programmierung  - mit Python

101

Veschlüsselung mit Zuordnungstabelle

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

G K X C S L Z U A H W D B M T Y E N J V P O I R F Q

Schlüssel: GKXCSLZUAHW..Quelltext:

SALVECAESAR

Geheimtext:JGDOSXGSJGN

Das bisher benutzte Verfahren zum Verschlüsseln von Texten nach der Verschiebemethode ist sehr einfach. Das hat den Nachteil, dass es relativ leicht "geknackt" werden kann. Wenn man die Verschiebezahl kennt, kann man direkt einen Text entschlüsseln.

Wir versuchen im Folgenden, das Verfahren zu verbessern. Statt Buchstaben systematisch um eine feste Zahl im Alphabet zu verschieben, benutzen wir eine Zuordnungstabelle, die Buchstaben willkürlich neue Buchstaben zuordnet - jedoch so, dass die Zuordnung eindeutig bleibt. Zuordnungstabell

e

J U L I U S C A E S A R | | | | | | | | | | | | H P D A P J . . . . . .

. . . . . . . . . . . .| | | | | | | | | | | |

J G D O S G J V S N A R

Page 102: Imperative Programmierung  - mit Python

102

Veschlüsselung mit Zuordnungstabelle

def verschluesseltesZeichen(zeichen, schluessel): # zeichen: Großbuchstabe # schluessel: Zuordnungstabelle in Form einer Zeichenkette # return: zum übergebenen Buchstaben zugeordneter Buchstabe # Beispiel: """ >>> verschluesseltesZeichen('B', 'GKXCSLZUAHWDBMTYENJVPOIRFQ') 'K' """

nummer = ord(zeichen)-ord('A') neuesZeichen = schluessel[nummer] return neuesZeichen

def verschluesselterText(klartext, schluessel):

# klartext: Zeichenkette aus Großbuchstaben # schluessel: Zuordnungstabelle in Form einer Zeichenkette # return: neue, mit der Zuordnungstabelle konstruierte Zeichenkette # Beispiel: """ >>> verschluesselterText('HUND', 'GKXCSLZUAHWDBMTYENJVPOIRFQ') 'UPMC' """

geheimtext = '' for zeichen in klartext: neuesZeichen = verschluesseltesZeichen(zeichen, schluessel) geheimtext = geheimtext + neuesZeichen return geheimtext

Funktion als fertiger Baustein

Page 103: Imperative Programmierung  - mit Python

103

Veschlüsselung mit Zuordnungstabelle

# Import der Funktionen

from verschluesselung_mit_zuordnungstabelle import *

# Verwendung der Funktionen

zuordnung = 'GKXCSLZUAHWDBMTYENJVPOIRFQ'geheimtext = verschluesselterText('SALVECAESAR', zuordnung)print(geheimtext)

Verwendung des fertigen Bausteins

Aufgabe:

Funktionen kann man selbstverständlich auch benutzen, wenn man sie nicht selbst definiert hat. Voraussetzung dafür ist, dass man genau weiß, welche Daten man der Funktion zur Verarbeitung übergeben muss und was die Funktion als Ergebnis zurückgibt. In einer Schnittstellenbeschreibung werden alle diese Informationen genau beschrieben.

Speichere jetzt die gezeigten Funktionsdefinitionen in einer Datei mit dem Dateinamen verschluesselung_mit_zuordnungstabelle.py ab. Erstelle anschließend ein Testprogramm wie das folgende, das die Funktionen verwendet.

Page 104: Imperative Programmierung  - mit Python

104

Veschlüsselung mit Zuordnungstabelle

Aufgabe:

Fertige entsprechende Schnittstellenbeschreibungen zu den folgenden Funktionen an. Erstelle auch ein Testprogramm, das diese Funktionen verwendet.

def entschluesseltesZeichen(zeichen, schluessel):

# ... i = 0 ... return neuesZeichen

def entschluesselterText(geheimtext, schluessel): # ... klartext = '' ... return klartext

def bereinigterText(text):

# ... textNeu = '' ... return textNeu

Page 105: Imperative Programmierung  - mit Python

105 Funktion als Baustein

Modularisierung ist ein Prinzip, nach dem viele Systeme entwickelt werden. Die Idee besteht darin, das Gesamtsystem nach dem Baukastenprinzip aus wiederverwendbaren Einzelbausteinen (den sogenannten "Modulen") zusammenzusetzen. Modularisierung erleichtert es, komplexe Systeme zu entwickeln.Funktionen können also als einfache Umsetzungen des Modularisierungsprinzips angesehen werden. Wenn man Funktionen als eigenständige Verarbeitungseinheiten konzipiert, dann lassen sie sich als Bausteine verwenden und und bei der Entwicklung von Programmen nach dem Baukastenprinzip verwenden. Man muss bei der Verwendung als Baustein nur die Schnittstelle der Funktion genau kennen.

# Import der Funktionen

from verschluesselung_mit_zuordnungstabelle import *

# Verwendung der Funktionen

zuordnung = 'GKXCSLZUAHWDBMTYENJVPOIRFQ'geheimtext = verschluesselterText('SALVECAESAR', zuordnung)print(geheimtext)

Strukturierung des Quelltextes

Vermeidung von Codeduplizierung

Page 106: Imperative Programmierung  - mit Python

106 Schnittstelle einer Funktion

Die Schnittstelle einer Funktion legt sämtliche Informationen fest, die man wissen muss, um diese Verarbeitungseinheit benutzen zu können.

Man kann diese Informationen aus dem Quelltext der Funktion erschließen. Oft will man aber nicht alle Details des Quelltextes genau analysieren, um an die erforderlichen Informationen heranzukommen, sondern die Funktion direkt nutzen. Man benötigt dann Antworten auf die folgenden Fragen: Welchen Namen hat die Funktion?

Wie viele Parameter gibt es?

Welche Werte darf man für sie einsetzen?

In welcher Reihenfolge treten sie auf?

Wofür stehen sie?

Welche Werte werden als Rückgaben erzeugt?

Wie verhält sich die Funktion?

Page 107: Imperative Programmierung  - mit Python

107 Schnittstellenbeschreibung

Wir verwenden verschiedene Formen der Schnittstellenbeschreibung. Oft begnügen wir uns mit einem Black-Box-Diagramm. Im Quelltext stellen wir die erforderlichen Informationen in unten gezeigten Weise dar.

def verschluesselterText(klartext, schluessel):

# klartext: Zeichenkette aus Großbuchstaben # schluessel: Zuordnungstabelle in Form einer Zeichenkette # return: neue, mit der Zuordnungstabelle konstruierte Zeichenkette # Beispiel:

""" >>> verschluesselterText('HUND', 'GKXCSLZUAHWDBMTYENJVPOIRFQ') 'UPMC' """

geheimtext = '' for zeichen in klartext: neuesZeichen = verschluesseltesZeichen(zeichen, schluessel) geheimtext = geheimtext + neuesZeichen return geheimtext

Signatur

Verhalten

Page 108: Imperative Programmierung  - mit Python

108 Modultest in Python

Python stellt eine Möglichkeit zur Verfügung, wie man Testfälle automatisiert überprüfen kann. Hierzu muss man nur die Funktion testmod des Moduls doctest ausführen (s.u.). def verschluesseltesZeichen(zeichen, schluessel): # zeichen: Großbuchstabe # schluessel: Zuordnungstabelle in Form einer Zeichenkette # return: zum übergebenen Buchstaben zugeordneter Buchstabe # Beispiel: """ >>> verschluesseltesZeichen('B', 'GKXCSLZUAHWDBMTYENJVPOIRFQ') 'K' """

nummer = ord(zeichen)-ord('A') neuesZeichen = schluessel[nummer] return neuesZeichen

def verschluesselterText(klartext, schluessel):

...

if __name__ == '__main__': from doctest import testmod testmod(verbose=True)

>>> Trying: verschluesselterText('HUND', 'GKXCSLZUAHWDBMTYENJVPOIRFQ')Expecting: 'UPMC'okTrying: verschluesseltesZeichen('B', 'GKXCSLZUAHWDBMTYENJVPOIRFQ')Expecting: 'K'ok2 items passed all tests: 1 tests in __main__.verschluesselterText 1 tests in __main__.verschluesseltesZeichen2 tests in 2 items.2 passed and 0 failed.Test passed.

Testfälle

automatisierter Modultest in Python Testprotokoll

Page 109: Imperative Programmierung  - mit Python

109 Experimente mit Variablen

Das Zusammenspiel von Variablen des Hauptprogramms, von Variablen von Unterprogrammen und von Parametern ist nicht so einfach. Mit Hilfe von Experimenten sollen die Zusammenhänge erschlossen werden.

def verschluesselterText(klartext, schluessel): geheimtext = '' for zeichen in klartext: nummer = ord(zeichen)-ord('A') neuesZeichen = schluessel[nummer] geheimtext = geheimtext + neuesZeichen print() print('lokale Variablen:') print(locals()) print('globale Variablen:') print(globals()) return geheimtext

# Testprogramm

zuordnung = 'GKXCSLZUAHWDBMTYENJVPOIRFQ'aktuellerKlartext = 'OBELIX'geheimtext = NoneaktuellerGeheimtext = verschluesselterText(aktuellerKlartext, zuordnung)print()print(klartext)print(geheimtext)print()print('globale Variablen:')print(globals())

Programm 1

Aufgabe:

Führe das Programm aus. Kannst du anhand der ausgegebenen Daten erschließen, was die Hilfsoperatoren locals() und globals() als Ergebnisse zurückliefern?

Page 110: Imperative Programmierung  - mit Python

110 Experimente mit Variablendef verschluesselterText(klartext, schluessel): geheimtext = '' for zeichen in klartext: nummer = ord(zeichen)-ord('A') neuesZeichen = schluessel[nummer] geheimtext = geheimtext + neuesZeichen print() print('lokale Variablen:') print(locals()) print('globale Variablen:') print(globals()) return geheimtext

# Testprogramm

schluessel = 'GKXCSLZUAHWDBMTYENJVPOIRFQ'klartext = 'OBELIX'geheimtext = Nonegeheimtext = verschluesselterText(klartext, schluessel)print()print(klartext)print(geheimtext)print()print('globale Variablen:')print(globals())

Programm 2

Aufgabe:

Beachte, dass hier die Parameter der Funktion verschluesselterText dieselben Namen haben wie die Variablen im Tesprogramm zur Verwaltung der aktuellen Daten.

Führe das Programm aus. Welche Schlüsse kannst du anhand der ausgegebenen Daten ziehen?

Page 111: Imperative Programmierung  - mit Python

111 Experimente mit Variablendef textVerschluesseln(): global zuordnung global klartext global geheimtext geheimtext = '' for zeichen in klartext: nummer = ord(zeichen)-ord('A') neuesZeichen = zuordnung[nummer] geheimtext = geheimtext + neuesZeichen print() print('lokale Variablen:') print(locals()) print('globale Variablen:') print(globals())

# Testprogramm

zuordnung = 'GKXCSLZUAHWDBMTYENJVPOIRFQ'klartext = 'OBELIX'geheimtext = NonetextVerschluesseln()print()print(klartext)print(geheimtext)print()print('globale Variablen:')print(globals())

Programm 3

Aufgabe:

Führe das Programm aus. Was bewirken Anweisungen wie global geheimtext? Warum funktioniert die Datenverarbeitung mit einer Funktion ohne Rückgabe hier?

Page 112: Imperative Programmierung  - mit Python

112 Experimente mit Variablendef textVerschluesseln(): #global zuordnung global klartext global geheimtext geheimtext = '' for zeichen in klartext: nummer = ord(zeichen)-ord('A') neuesZeichen = zuordnung[nummer] geheimtext = geheimtext + neuesZeichen print() print('lokale Variablen:') print(locals()) print('globale Variablen:') print(globals())

# Testprogramm

zuordnung = 'GKXCSLZUAHWDBMTYENJVPOIRFQ'klartext = 'OBELIX'geheimtext = NonetextVerschluesseln()print()print(klartext)print(geheimtext)print()print('globale Variablen:')print(globals())

Programm 4

Aufgabe:

Wir lassen jetzt Schritt für Schritt die Anweisungen global ... weg, indem wir sie auskommentieren.

Führe die modifizierten Programme aus. Was stellst du fest? Hast du eine Erklärung hierfür?

Page 113: Imperative Programmierung  - mit Python

113 lokale / globale Variable

Eine globale Variable ist (vereinfacht gesagt) eine Variable, die im Hauptprogramm eingeführt wird. Eine lokale Variable ist (vereinfacht gesagt) eine Variable, die nur innerhalb eines Unterprogramms benutzt wird. Beachte, dass die (formalen) Parameter eines Unterprogramms auch zu diesen lokalen Variablen zählen.def d(x): y = x + x return y

# Testa = 2b = d(a)print(a)

>>> 4

def d(x): x = x + x return x

# Testx = 2y = d(x)print(y)

>>> 4

a = 2{a -> 2}b = d(a)--------------------------Funktionsaufruf: d(a)--------------------------{a -> 2} {x -> 2} y = x + x {x -> 2, y -> 4} return y--------------------------Ergebnis: 4--------------------------{a -> 2; b -> 4}

x = 2{x -> 2}y = d(x)-----------------------Funktionsaufruf: d(x)-----------------------{x -> 2} {x -> 2} x = x + x {x -> 4} return x-----------------------Ergebnis: 4-----------------------{x -> 2; y -> 4}

siehe auch: http://people.csail.mit.edu/pgbovine/python/tutor.html#mode=visualize

Page 114: Imperative Programmierung  - mit Python

114 lokale / globale Variable

Eine lokale Variable ist nur innerhalb der Funktionsdefinition, in der sie eingeführt ist, gültig bzw. sichtbar. Anders verhält es sich bei globalen Variablen. Auf eine globale Variable kann man innerhalb einer Funktion lesend zugreifen - sofern dort nicht eine gleichlautende Variable eingeführt ist.

def d(): y = x + x return y

# Testx = 2y = d()print(y)

>>> 4

def d(): global x global y y = x + x

# Testx = 2d()print(y)

>>> 4

x = 2{x -> 2}y = d()--------------------------Funktionsaufruf: d()--------------------------{x -> 2} {} y = x + x {y -> 4} return y--------------------------Ergebnis: 4--------------------------{x -> 2; y -> 4}

x = 2{x -> 2}d()-----------------------Funktionsaufruf: d()-----------------------{x -> 2} {} y = x + x{x -> 2; y -> 4} {}-----------------------{x -> 2; y -> 4}

Verändert man innerhalb einer Prozedur den Wert einer globalen Variablen, so spricht man auch von einem Seiteneffekt.

Page 115: Imperative Programmierung  - mit Python

115 Teil 4

Lotto -Datenverwaltung mit Datenstrukturen

Page 116: Imperative Programmierung  - mit Python

116 Lottosimulation

Wie wahrscheinlich ist es, dass man beim Lottospielen gewinnt? Diese Frage soll hier mit einem Simulationsprogramm beantwortet werden. Bei der Programmentwicklung werden wir uns mit der Verwaltung vieler Daten beschäftigen.

Page 117: Imperative Programmierung  - mit Python

117 Datenverwaltung mit Listen

Die Zahlen einer Lotto-Ziehung (ohne Zusatzzahl) sollen mit Hilfe von Python verwaltet werden. Im Folgenden findest du zwei Vorschläge, wie man das machen könnte. # Version 1>>> ziehung1 = 25>>> ziehung2 = 40...>>> ziehung125>>> ziehung240...

# Version 2>>> ziehung = [25, 40, 44, 1, 45, 21]>>> ziehung[25, 40, 44, 1, 45, 21]>>> ziehung[0]25>>> ziehung[1]40>>> len(ziehung)6>>> ziehung[0] = 23>>> ziehung[23, 40, 44, 1, 45, 21]

Verwendung vieler Variablen

Verwendung einer Variablen sowie einer Liste als "Datencontainer"

Aufgaben:(a) Welche Vorteile hat es, wenn man Listen als eine Art "Datencontainer" benutzt? (b) Wie bildet man in Python eine Liste? Wie greift man auf einzelne Listenelemente zu? Wie sind diese durchnummeriert? Was leistet die Funktion len?

Page 118: Imperative Programmierung  - mit Python

118 Datenverwaltung mit Listen

Aufgabe:Ein Tipp soll verwaltet werden. Zwei Möglichkeiten stehen zur Auswahl. Für welche Version sollte man sich entscheiden? Begründe deine Entscheidung.

# Version 1>>> tipp1 = True>>> tipp2 = False...

# Version 2>>> tipp = [ True , False, False, False, False, False, False, \ False, False, False, False, True , False, False, \ False, False, False, False, False, False, True , \ False, False, False, False, False, False, False, \ False, False, True , False, False, False, False, \ False, True , False, False, False, False, False, \ False, False, False, True , False, False, False, \ ]

Page 119: Imperative Programmierung  - mit Python

119 Eine Liste durchlaufen

# Initialisierungziehung = [25, 40, 44, 1, 45, 21]# Verarbeitung und Ausgabei = 0while i < len(ziehung): print(ziehung[i]) i = i+1

Aufgabe: (a) Was leistet das Programm? Kannst du es - ohne vorheriges Testen - vorhersagen?(b) Ergänze das Programm so, dass man folgende Ausgabe erhält:

Die Zahlen einer Lotto-Ziehung (ohne Zusatz-zahl) sollen mit einer Liste verwaltet werden. Die Listenelemente sind dabei - beginnend mit 0 - mit einem Index durchnummeriert.

Liste über den Index durchlaufen

>>> Kugel 1 : 25Kugel 2 : 40Kugel 3 : 44Kugel 4 : 1Kugel 5 : 45Kugel 6 : 21

Page 120: Imperative Programmierung  - mit Python

120 Eine Liste durchlaufen

Aufgabe:Teste auch dieses Programm. Was leistet es?

# Initialisierungziehung = [25, 40, 44, 1, 45, 21]# Verarbeitung und Ausgabefor z in ziehung: print(z)

Die Zahlen einer Lotto-Ziehung (ohne Zusatz-zahl) sollen mit einer Liste verwaltet werden. Die Listenelemente sind dabei - beginnend mit 0 - mit einem Index durchnummeriert.

Liste über die Elemente durchlaufen

Page 121: Imperative Programmierung  - mit Python

121 Anzahl der Richtigen

# Initialisierungziehung = [25, 40, 44, 1, 45, 21]tipp = [1, 12, 21, 31, 37, 46]# Verarbeitungrichtige = 0i = 0while i < len(ziehung): j = 0 while j < len(tipp): print('vergleiche: ', ziehung[i], tipp[j]) # ... j = j+1 i = i+1# Ausgabeprint(richtige)

# Initialisierungziehung = [25, 40, 44, 1, 45, 21]tipp = [1, 12, 21, 31, 37, 46]# Verarbeitungrichtige = 0for z in ziehung: for t in tipp: print('vergleiche: ', z, t) # ...# Ausgabeprint(richtige)

Ziel ist, es, die Anzahl der richtig getippten Zahlen mit einem Programm zu ermitteln.

Aufgabe:Die folgenden Programm liefert ein Gerüst, mit dem man jede Zahl der Liste ziehung mit jeder Zahl der Liste tipp vergleichen kann.

Ergänze die noch fehlenden Vergleiche.

Page 122: Imperative Programmierung  - mit Python

122 Anzahl der Richtigen

# Initialisierungziehung = [ True , False, False, False, False, False, False, \ False, False, False, False, False, False, False, \ ... ]tipp = [ True , False, False, False, False, False, False, \ False, False, False, False, True , False, False, \ ... ]# Verarbeitungrichtige = 0# ...# Ausgabeprint(richtige)

Ziel ist, es, die Anzahl der richtig getippten Zahlen mit einem Programm zu ermitteln.

Aufgabe:

Ergänze das Programm so, dass man die Anzahl der Richtigen erhält.

Page 123: Imperative Programmierung  - mit Python

123 Elemente hinzufügen

>>> tipp = []>>> tipp[]>>> tipp = tipp + [12]>>> tipp[12]>>> tipp = tipp + [15]>>> tipp[12, 15]>>> tipp = [7] + tipp>>> tipp...>>> tipp = tipp + [42, 47]>>> tipp...>>> tipp = [3] + tipp>>> tipp...

Der folgende Python-Dialog zeigt, wie man eine Liste zur Verwaltung der Zahlen eines Tipps schrittweise aufbauen kann.

Listen aneinanderhängen

Aufgabe:Analysiere den gezeigten Python-Dialog. Stelle Vermutungen auf, was an Stelle der drei Punkte ... steht. Überprüfe deine Vermutung.

Page 124: Imperative Programmierung  - mit Python

124 Elemente löschen

>>> tipp[3, 7, 12, 15, 42, 47]>>> tipp[0:3][3, 7, 12]>>> tipp[4:6][42, 47]>>> tipp[0:3] + tipp[4:6][3, 7, 12, 42, 47]>>> tipp[3, 7, 12, 15, 42, 47]>>> tipp = tipp[0:3] + tipp[4:6]>>> tipp[3, 7, 12, 42, 47]

Aus Listen kann man auch wieder Elemente löschen. Bei der hier gezeigten Version wird hierzu eine neue Liste aus Teillisten der gegebenen Liste erzeugt.

Zugriff auf Teillisten

Aufgabe:Führe selbst entsprechende Dialoge. Kannst du erklären, wie die neue Liste zustande kommt?

Page 125: Imperative Programmierung  - mit Python

125 Ziehung automatisiert erzeugen

from random import *# Verarbeitungziehung = []for i in range(6): zahl = randint(1, 49) ziehung = ziehung + [zahl]# Ausgabeprint(ziehung)

Ziel ist es, eine Ziehung der Lottozahlen mit Hilfe des Zufallsgenerators von Python zu simulieren. Hier ein erster Vorschlag:

Aufgabe:

(a) Analysiere das Programm und erkläre die einzelnen Anweisungen.

(b) Teste das Programm mehrfach. Welche Schwierigkeit tritt hier auf.

(c) Kannst du die Schwierigkeit beheben?

Page 126: Imperative Programmierung  - mit Python

126 Ziehung automatisiert erzeugen

from random import *# Verarbeitungziehung = []for i in range(49): ziehung = ziehung + [False]for i in range(6): zahl = randint(1, 49) ziehung[zahl-1] = True# Ausgabefor i in range(49): if ziehung[i] == True: print(i+1)

Ziel ist es, eine Ziehung der Lottozahlen mit Hilfe des Zufallsgenerators von Python zu simulieren. Hier ein weiterer Vorschlag:

Aufgabe:

(a) Teste das folgende Programm. Erkläre, wie hier die Liste zur Verwaltung der Wahrheitswerte aufgebaut wird.

(b) Auch hier ist noch etwas nicht in Ordnung. Kannst du die Schwierigkeit durch Ergänzungen im Programm beheben?

Page 127: Imperative Programmierung  - mit Python

127 Fachkonzept - Liste

Eine Liste ist eine Datenstruktur zur Verwaltung endlicher Folgen von Daten, bei der man flexibel neue Daten hinzufügen und vorhandene Daten entfernen kann.

BrotButterJoghurtSchokoladeMehlEier...

Äpfel

Zur Darstellung von Listen verwenden wir - wie in Python - eckige Klammern.

Alle Elemente einer Liste werden mit Kommata getrennt.

Eine besondere Liste ist die leere Liste. Sie enthält keine Elemente.

Die Elemente einer Liste können (in unserer Darstellung hier) von beliebigem - also auch unterschiedlichem - Typ sein.

Eine Liste kann selbst wieder Listen als Elemente haben. Listen können also geschachtelt werden.

[1, 12, 21, 31, 37, 46]

['[email protected]', '[email protected]', '[email protected]', ...]

[]

[1, 21, 25, 40, 44, 45, ("Zusatzzahl", 3), ("Superzahl", 5)]

[[1, 12, 21, 31, 37, 46], [3, 8, 10, 30, 31, 49], [5, 12, 20, 22, 29, 40]]

Page 128: Imperative Programmierung  - mit Python

128 Liste als sequentieller Datentyp

Index

>>> L = [10, 15, 21, 33, 37, 40]>>> L[0]10>>> L[1]15

lesender Zugriff

>>> L = [10, 15, 21, 33, 37, 40]>>> L[10, 15, 21, 33, 37, 40]>>> L[4] = 36>>> L[10, 15, 21, 33, 36, 40]

schreibender Zugriff

Während ein lesender Zugriff auf jedes Element der Sequenz bei allen sequentiellen Datenobjekten möglich ist, ist ein schreibender Zugriff nur bei veränderbaren Datenobjekten (wie Listen) möglich.

Sequentielle Datenobjekte sind in Python zusammengesetzte Datenobjekte, die aus einer Folge von (gleichartigen oder auch verschiedenen) Datenobjekten bestehen. Die Elemente eines solchen sequentiellen Datenobjekts sind durchnummeriert Die Nummerierung beginnt immer bei 0. Die Nummer wird auch Index genannt.

25

ziehung0

401

442

1

3

454

215

Element

Page 129: Imperative Programmierung  - mit Python

129 Liste als sequentieller Datentyp

>>> ziehung = [25, 40, 44, 1, 45, 21]>>> ziehung[0:2][25, 40]>>> ziehung[2:5][44, 1, 45]>>> ziehung[3:3][]

Teillisten

>>> ziehung = [25, 40, 44, 1, 45, 21]>>> ziehung[:2][25, 40]>>> ziehung[2:][44, 1, 45, 21]>>> ziehung[:][25, 40, 44, 1, 45, 21]

Ein Zugriff auf eine Teilliste ist möglich: Wenn L eine Liste bezeichnet, dann beschreibt der Ausdruck L[i:j] die Liste, die alle Elemente der Ausgangsliste L mit den Nummern von i bis j-1 enthält. Beachte, dass diese Teilliste auch leer sein kann.

Teillisten

25

ziehung0

401

442

1

3

454

215

Page 130: Imperative Programmierung  - mit Python

130 Liste als sequentieller Datentyp

>>> tippAnfang = [2, 6]>>> tippEnde = [16, 40, 41, 43]>>> tippAnfang + tippEnde[2, 6, 16, 40, 41, 43]>>> tippAnfang + [10][2, 6, 10]>>> [] + tippAnfang[2, 6]

Konkatenation

>>> tippAnfang = [2, 6, 16, 40]>>> len(tippAnfang)4>>> len([])0

Da Listen dynamisch wachsen oder schrumpfen können, benötigt man häufig eine Operation zur Bestimmung der Länge der Liste. Die Länge einer Liste beschreibt dabei die Anzahl der Listenelemente. Wenn L eine Listen bezeichnet, dann beschreibt der Ausdruck len(L) die Länge der Liste.

Bei der Konkatenation von Listen werden diese zu einer Gesamtliste verbunden. Wenn L und M zwei Listen bezeichnen, dann beschreibt der Ausdruck L+M die Liste, die zunächst alle Elemente von L und danach alle Elemente von M enthält.

Länge

25

ziehung0

401

442

1

3

454

215

Page 131: Imperative Programmierung  - mit Python

131 Liste als sequentieller Datentyp

>>> tippAnfang = [2, 6, 16, 40]>>> t = 25>>> t in tippAnfangFalse>>> t = 40>>> t in tippAnfangTrue

Elementbeziehung

>>> ziehung = [25, 40, 44, 1, 45, 21]>>> for z in ziehung:... print(z)... 25404414521

Mit einer for-Anweisung der Gestalt for e in L: ...kann man alle Elemente einer Liste (Sequenz) der Reihe nach durchlaufen.

Mit einem Ausdruck der Gestalt e in L kann man überprüfen, ob das von e verwaltete Datenobjekt in der von L verwalteten Liste vorkommt.

Durchlaufen einer Liste

25

ziehung0

401

442

1

3

454

215

Page 132: Imperative Programmierung  - mit Python

132 Übungen

Aufgabe:

Teste die Funktion. Entwickle analog eine Funktionsdefinition mit Schnittstellenbeschreibung zur Funktion mitLetztem(e, L).

def mitErstem(e, L):

# e: Element, das hinzugefügt wird # L: bestehende Liste # return: neue Liste mit e als erstem Element # Beispiele:

""" >>> mitErstem('H', ['A', 'L', 'T']) ['H', 'A', 'L', 'T'] >>> mitErstem('O', []) ['O'] """

N = [e] + L # neue Liste return N

Page 133: Imperative Programmierung  - mit Python

133 Übungen

Aufgabe:

Mit eine Variablen daten wird eine Liste mit Daten (die der Einfachheit halber in Form von Zeichenketten dargestellt sind) verwaltet. Ergänze im folgenden Python-Dialog die Ergebnisse und überprüfe sie anschließend mit Python.

>>> daten = ['a', 'b', 'c', 'd', 'e']>>> daten[3]...>>> ['x'] + daten + ['y']...>>> daten[1:]...>>> daten[0:2] + daten[3:len(daten)]...>>> daten[0:2] + ['z'] + daten[2:len(daten)]...

Page 134: Imperative Programmierung  - mit Python

134 Übungen

Aufgabe:

Die Funktion ohneElement soll aus der übergebenen Liste L das Element mit der übergebenen Nummer i entfernen.

def ohneElement(i, L): N = L[0:i] + L[(i+1):len(L)] return N

(a) Warum liefert der Ausdruck L[0:i] + L[(i+1):len(L)] die gewünschte neue Liste?

(b) Teste die Funktion mit verschiedenen Testdaten.

Page 135: Imperative Programmierung  - mit Python

135 Übungen

Aufgabe:

Die Funktion mitNeuemElement soll das übergebene Element x an die Stelle mit der übergebenen Nummer i in einer übergebenen Liste L einfügen.

def mitNeuemElement(x, i, L): N = ... return N

(a) Ergänze den noch fehlenden Ausdruck in der Funktionsdeklaration.

(b) Teste deinen Implementierungsvorschlag.

Page 136: Imperative Programmierung  - mit Python

136 Übungen

Aufgabe:

Entwickle ein Ersetzungsverfahren und ergänze entsprechend die Funktionsdefinition.

def mitErsetztemElement(a, b, L):

# a: zu ersetzendes Element # b: neues Element # L: Liste # Beispiele:

""" >>> mitErsetztemElement('A', 'U', ['H', 'A', 'N', 'D']) ['H', 'U', 'N', 'D'] >>> mitErsetztemElement('E', 'I', ['H', 'A', 'N', 'D']) ['H', 'A', 'N', 'D'] >>> mitErsetztemElement('L', 'S', ['B', 'A', 'L', 'L']) ['B', 'A', 'S', 'S'] """

# ...

Page 137: Imperative Programmierung  - mit Python

137 Achtung: FehlerquelleSimone hat sich folgende Lottozahlen als Tipp ausgedacht: 4, 13, 21, 33, 34, 42. Anne gefallen diese Zahlen. Nur die 13, die hätte sie gerne ersetzt durch eine 8. Im folgenden Python-Dialog wird ein Lotto-Tipp kopiert und anschließend etwas abgeändert. Probiere das selbst einmal aus. Was fällt auf? Entsprechen alle Ergebnisse deinen Erwartungen?

>>> tipp1 = [4, 13, 21, 33, 34, 42]>>> tipp2 = tipp1>>> tipp2[1] = 8>>> tipp2[4, 8, 21, 33, 34, 42]>>> tipp1[4, 8, 21, 33, 34, 42]>>> tipp1 = [4, 13, 21, 33, 34, 42]>>> tipp1[4, 13, 21, 33, 34, 42]>>> tipp2[4, 8, 21, 33, 34, 42]>>> tipp2[0] = 3>>> tipp2[3, 8, 21, 33, 34, 42]>>> tipp1[4, 13, 21, 33, 34, 42]

Page 138: Imperative Programmierung  - mit Python

138

Verwaltung von Listen mit Variablen

Jedes Datenobjekt hat (in Python) eine Identitätsnummer, einen Typ und einen bestimmten Wert.

>>> id([4, 13, 21, 33, 34, 42])12289008>>> type([4, 13, 21, 33, 34, 42])<type 'list'>>>> [4, 13, 21, 33, 34, 42][4, 13, 21, 33, 34, 42]

Variablen dienen in der Informatik dazu, Datenobjekte zu verwalten. Variablen werden an Datenobjekte angebunden, um die betreffenden Datenobjekte verwalten zu können.Eine Variable, die ein Datenobjekt referenziert, ist eine Art Name für das betreffende Datenobjekt. Mit dem Variablennamen kann man sich die Identitätsnummer, den Typ und den Wert des referenzierten Datenobjekts verschaffen.

>>> tipp1 = [4, 13, 21, 33, 34, 42]>>> id(tipp1)12289008>>> type(tipp1)<type 'list'>>>> tipp1[4, 13, 21, 33, 34, 42]

Page 139: Imperative Programmierung  - mit Python

139

Verwaltung von Listen mit Variablen

>>> tipp1 = [4, 13, 21, 33, 34, 42]>>> tipp2 = tipp1>>> tipp2[1] = 8>>> tipp2[4, 8, 21, 33, 34, 42]>>> tipp1[4, 8, 21, 33, 34, 42]>>> tipp1 = [4, 13, 21, 33, 34, 42]>>> tipp1[4, 13, 21, 33, 34, 42]>>> tipp2[4, 8, 21, 33, 34, 42]>>> tipp2[0] = 3>>> tipp2[3, 8, 21, 33, 34, 42]>>> tipp1[4, 13, 21, 33, 34, 42]

Page 140: Imperative Programmierung  - mit Python

140 Exkurs: Listenverarbeitung

>>> L = [1, 2, 3]>>> L[1, 2, 3]>>> id(L)12283056>>> L = L + [4]>>> L[1, 2, 3, 4]>>> id(L)12289008>>> L = L[1:]>>> L[2, 3, 4]>>> id(L)12257720>>> L = [1, 2] + L[1:]>>> L[1, 2, 3, 4]>>> id(L)12289008

>>> L = [1, 2, 3]>>> L[1, 2, 3]>>> id(L)12283536>>> L[1] = 5>>> L[1, 5, 3]>>> id(L)12283536>>> L.remove(5)>>> L[1, 3]>>> id(L)12283536>>> L.insert(1, 2)>>> L[1, 2, 3]>>> id(L)12283536

Erzeugung neuer Listen

Veränderung einer bestehenden Listen

objektorientiert: L.Listenoperation funktional: L = Listenkonstruktor

Page 141: Imperative Programmierung  - mit Python

141

Anwendung - Gewinnchancen b. Lotto

Die Gewinnchancen beim Lottospiel kann man näherungsweise ermitteln, indem man sehr oft einen (evtl. festen) Tipp vorgibt und eine Lotto-Ziehung durchführt. Man muss dann nur mitzählen, wie oft man 0, 1, ..., 6 Richtige hatte.

Tipp Ziehung Richtige---------------------------------------------------------------------------[ 1, 12, 21, 31, 37, 46] [25, 40, 44, 1, 45, 21] [0, 0, 1, 0, 0, 0, 0][ 1, 12, 21, 31, 37, 46] [11, 15, 3, 20, 40, 30] [1, 0, 1, 0, 0, 0, 0][ 1, 12, 21, 31, 37, 46] [ 6, 49, 32, 18, 19, 24] [2, 0, 1, 0, 0, 0, 0]...

Aufgaben:

(a) Entwickle ein Programm zur Ermittlung der Gewinnchancen beim Lotto. Mit dem Programm soll es z.B. möglich sein, zu ermitteln, wie oft man 0, 1, 2, ..., 6 Richtige erhält, wenn man 10000 mal Lotto spielt. Strukturiere das Programm mit Hilfe von Funktionen.

(b) Wie lange dauert es im wirklichen Leben, bis 10000 Ziehungen durchgeführt wurden, wenn man von einer Ziehung am Mittwoch und einer am Samstag ausgeht und wenn man einen Tipp pro Spiel abgibt? Beurteile mit den Ergebnissen die Gewinnaussichten beim Lottospiel.

Page 142: Imperative Programmierung  - mit Python

142

Anwendung - Gewinnchancen b. Lotto

Wenn man ein Programm zur wiederholten Simulation entwickeln möchte, dann sollte man Funktionen zur Durchführung von Teilaufgaben nutzen. Hier ein Vorschlag zur Modellierung von Funktionen.

Page 143: Imperative Programmierung  - mit Python

143 Datenmodellierung mit Listen

Beim Lotto werden insgesamt 7 Kugeln gezogen - 6 Kugeln mit den eigentlichen Lottozahlen und eine weitere Kugel mit der sogenannten Zusatzzahl. Ziel ist es, die Daten einer Ziehungen mit Zusatzzahl zu erfassen.

Aufgabe:

Was steht vermutlich an Stelle der drei Punkte? Überprüfe deine Vermutung.

>>> gewinnzahlen = [33, 13, 8, 12, 40, 41]>>> zusatzzahl = 2>>> ziehung = [gewinnzahlen, zusatzzahl]>>> ziehung...>>> ziehung[1]...>>> ziehung[0]...>>> ziehung[0][2]...

Page 144: Imperative Programmierung  - mit Python

144 Datenmodellierung mit Listen

Wer beim Lotto mitspielt, füllt einen Tippschein aus. Hier hat man die Möglichkeit, mehrere Tipps auf den Zahlenfeldern einzutragen.

Aufgabe:

Mache einen Vorschlag, wie man solche Mehrfachtipps mit Listen erfassen könnte. Teste deinen Vorschlag mit einem Python-Dialog.

Page 145: Imperative Programmierung  - mit Python

145 Datenmodellierung mit Tupeln

Bisher haben wir Folgen von Daten immer mit Listen erfasst. In Python geht das aber auch anders - mit sogenannten Tupeln.

Aufgabe:

Vergleiche die verschiedenen Datenmodellierungen.

>>> gewinnzahlen = [33, 13, 17, 12, 40, 41]>>> gewinnzahlen[1]13>>> gewinnzahlen[1] = 17>>> gewinnzahlen[33, 17, 17, 12, 40, 41]

>>> gewinnzahlen = (33, 13, 17, 12, 40, 41)>>> gewinnzahlen(33, 13, 17, 12, 40, 41)>>> gewinnzahlen[1]13>>> gewinnzahlen[1] = 17Traceback (most recent call last): File ... gewinnzahlen[1] = 17TypeError: 'tuple' object does not support item assignment

>>> gewinnzahlen = [33, 13, 8, 12, 40, 41]>>> zusatzzahl = 2>>> ziehung = (gewinnzahlen, zusatzzahl)>>> ziehung([33, 13, 8, 12, 40, 41], 2)>>> ziehung[1]2>>> ziehung[0][33, 13, 8, 12, 40, 41]

Liste als Datencontainer

Tupel als Datencontainer

Tupel und Liste als

Datencontainer

Page 146: Imperative Programmierung  - mit Python

146 Fachkonzept - Tupel

Eine Tupel ist eine Datenstruktur, bei der mehrere Daten zu einer Einheit zusammengefasst werden.

Tupel weisen einige Ähnlichkeiten mit Listen auf, unterscheiden sich aber in einigen Punkten wesentlich von Listen.

Ein lesender Zugriff auf Tupelelemente erfolgt genau wie bei Listen. Ein schreibender Zugriff auf Tupelelemente ist - anders als bei Listen - nicht möglich. Man kann ein Tupel nicht dadurch abändern, dass man ein Element durch ein anderes ersetzt. Wenn man ein Tupel abändern will, muss man ein neues Tupelobjekt erzeugen. >>> gewinnzahlen = (33, 13, 8, 12, 40, 41)>>> zusatzzahl = 2>>> ziehung = (gewinnzahlen, zusatzzahl)>>> ziehung((33, 13, 8, 12, 40, 41), 2)

>>> gewinnzahlen = (33, 13, 17, 12, 40, 41)>>> gewinnzahlen(33, 13, 17, 12, 40, 41)>>> gewinnzahlen[1]13>>> gewinnzahlen[1] = 17Traceback (most recent call last): File ... gewinnzahlen[1] = 17TypeError: 'tuple' object does not support item assignment

Tupel zusammenpacken

>>> ziehung = ((33, 13, 8, 12, 40, 41), 2)>>> (gewinnzahlen, zusatzzahl) = ziehung>>> gewinnzahlen(33, 13, 8, 12, 40, 41)>>> zusatzzahl2

Tupel auspacken

Page 147: Imperative Programmierung  - mit Python

147 Fachkonzept - Datenstruktur

Datenstrukturen ermöglichen es, strukturierte Daten als Einheit zu verwalten.

>>> lottoschein = [ [(3, 6, 19, 21, 38, 41), (4, 9, 17, 37, 38, 39), (18, 23, 28, 36, 38, 46)], ('Losnummer', 4440674), ('Superzahl', 4), ('Ziehungstage', 'Sa + Mi'), ('Laufzeit', 1), ('Spiel 77', False), ('Super 6', False), ('Gluecksspirale', False) ]

Datenmodellierung mit den Datenstrukturen "Liste" und "Tupel"

Page 148: Imperative Programmierung  - mit Python

148 Übungen - Datenstruktur

>>> lottoschein = [ [(3, 6, 19, 21, 38, 41), (4, 9, 17, 37, 38, 39), (18, 23, 28, 36, 38, 46)], ('Losnummer', 4440674), ('Superzahl', 4), ('Ziehungstage', 'Sa + Mi'), ('Laufzeit', 1), ('Spiel 77', False), ('Super 6', False), ('Gluecksspirale', False) ]>>> lottoschein[0][1]...>>> lottoschein[0][1][2]...>>> lottoschein[1][0]...

Aufgabe 1: Zugriff auf geschachtelte Daten

Ergänze die Ergebnisse. Überprüfe sie mit Python.

Aufgabe 2: Datenmodellierung

Wie könnte man die Gewinnquoten beim Lotto mit Datenstrukturen erfassen?