Powerpoint-Präsentation

advertisement
Imperative Programmierung
mit Python
Klaus Becker
2012
2
Imperative Programmierung
3
Teil 0
Vorbemerkungen zu 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
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
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
Interne Abläufe
7
Der Quelltext eines Python Programms wird mit einem
Texteditor geschrieben (z.B. Idle oder PyScripter).
Compiler
Interpreter
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 PythonInterpreter zur Verfügung stellen.
8
Gängige Python-Versionen
http://www.python.org/download/
http://portablepython.com/releases/
9
Entwicklungsumgebung Idle
10
Entwicklungsumgebung PyScripter
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 €)
 ...
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.pdf
http://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 auf
www.inf-schule.de
13
Teil 1
Populationsentwicklung Datenverwaltung mit Variablen
14
Populationsentwicklung
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.
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.
Populationsentwicklung
15
Aufgabe:
Berechne die Populationswerte
(ohne Python).
Zur Kontrolle: Nach 5 Schritten
besteht die gesamte Population
aus knapp 300 Mäusen.
Schritt
jung
erwachsen
alt
0
6
9
12
1
60 = 4*9+2*12
3 = 6:2
3 = 9:3
2
3
4
5
...
16
Python als Taschenrechner
>>>
>>>
>>>
>>>
6
>>>
9
>>>
12
>>>
>>>
>>>
...
jung = 6
erwachsen = 9
alt = 12
jung
erwachsen
alt
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?
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?
Python als Taschenrechner
18
>>>
>>>
>>>
>>>
6
>>>
9
>>>
12
jung = 6
erwachsen = 9
alt = 12
jung
erwachsen
alt
???
>>> jung
60
>>> erwachsen
3
>>> alt
3
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'>
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.
Fachkonzept - Zuweisung
20
Mit einer Zuweisung kann man eine Variable mit einem neuen Datenobjekt verknüpfen.
Zustand - vorher
Zuweisungszeichen
alt = erwachsen // 3
{jung -> 6; erwachsen -> 9; alt -> 12}
alt = erwachsen // 3
Auswertung
alt ->
Variable
Term
3
{jung -> 6; erwachsen -> 9; alt -> 3}
Zustand - nachher
Aufbau einer Zuweisung:
Eine Zuweisung besteht aus einer
Variablen (der ein Wert zugewiesen wird)
and einem Term (der den zuzuweisenden
Wert festlegt).
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.
Trace-Tabelle
21
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
Variablenbezeichner
22
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.
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
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
Aufgabe:
Die Folge von Zuweisungen soll die Entwicklung einer Population beschreiben. Beurteile die
Wahl der Variablenbezeichner?
Exkurs: Was ist eine Variable?
23
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.
"Behältersemantik"
Speicherzelle mit
Datenwert
Name
Variablen dienen in der Informatik dazu, Daten zu verwalten. Eine Variable ist ein Name, der
(in der Regel) mit einem Datenobjekt verknüpft ist.
"Zeigersemantik"
Name
Zeiger
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.
"Wertsemantik"
{jung -> 6; erwachsen -> 9; alt -> 12}
Name
Datenwert
Exkurs: Variablen in Python
24
Variablen dienen in der Informatik dazu, Daten zu verwalten. Eine Variable ist ein Name, der
(in der Regel) mit einem Datenobjekt verknüpft ist.
"Zeigersemantik"
Name
Zeiger
Datenobjekt
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
>>> type(2)
<class 'int'>
>>> 2
2
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.
>>> id(2)
505300136
>>> zahl = 2
>>> id(zahl)
505300136
>>> type(zahl)
<class 'int'>
>>> zahl
2
25
Exkurs: Zuweisungen in Python
Eine Veränderung eines Variablenwerts kann mit Hilfe einer Zuweisung erfolgen.
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.
Beachte: Auch wenn zwei Variablen
denselben Wert haben, müssen sie
nicht auf dasselbe Datenobjekt
verweisen.
>>> a = 2
>>> id(a)
505300136
>>> b = a
>>> id(b)
505300136
[variable] = [term]
Struktur
Auswertung
>>> a = "Test"
>>> b = "Test"
>>> id(a)
27764768
>>> id(b)
27757280
26
Exkurs: Mehrfachzuweisungen in Python
Python erlaubt Zuweisungen der Gestalt [variablentupel] = [termtupel].
>>> (jung, erwachsen, alt) = (6, 9, 12)
>>> jung
6
>>> erwachsen
9
>>> alt
Variablentupel
Termtupel
12
>>> (jung, erwachsen, alt) = (erwachsen*4+alt*2, jung//2, erwachsen//3)
>>> (jung, erwachsen, alt)
(60, 3, 3)
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*2
NameError: name 'erwachen' is not defined
>>>
>>> jung
60
>>> erwachsen
3
>>> alt
3
Ausführfenster
Tippfehler
Programmfenster
jung = 6
erwachsen = 9
alt = 12
hilf = erwachsen*4 + alt*2
alt = erwachsen // 3
erwachsen = jung // 2
jung = hilf
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.
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.
Benutzereingaben
Ausgaben
29
Ausgabe von Daten
Aufgabe:
Ändere das bisher entwickelte Programm zur Mäusepopulation so ab, dass folgende Ausgabe
im Ausführfenster erscheint:
>>>
Die berechneten Populationswerte sind:
Anzahl junger Maeuse: 60
Anzahl erwachsener Maeuse: 3
Anzahl alter Maeuse: 3
Ausführfenster
Bearbeite hierzu die Aufgaben auf inf-schule 1.6.1.1.7.
30
Eingabe von Daten
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-/AusgabeDialog erscheinen.
>>>
Gib die Werte der Ausgangspopulation ein:
Anzahl junger Maeuse: 20
Anzahl erwachsener Maeuse: 18
Anzahl alter Maeuse: 4
Ausführfenster
Die berechneten Populationswerte sind:
Anzahl junger Maeuse: 80
Anzahl erwachsener Maeuse: 10
Anzahl alter Maeuse: 6
Bearbeite hierzu die Aufgaben auf inf-schule 1.6.1.1.8.
Fachkonzept - Programm
31
Ein (Python-) Programm ist eine Folge von (Python-) Anweisungen und Kommentaren. Der
Programmtext wird auch Quelltext genannt.
# -*- coding: utf8 -*# Eingabe
print('Gib die Werte der Ausgangspopulation ein:')
jung = int(input('Anzahl junger Maeuse: '))
erwachsen = int(input('Anzahl erwachsener Maeuse: '))
alt = int(input('Anzahl alter Maeuse: '))
# Verarbeitung
hilf = erwachsen*4 + alt*2
alt = erwachsen // 3
erwachsen = jung // 2
jung = hilf
# Ausgabe:
print('')
print('Die berechneten Populationswerte sind:')
print('Anzahl junger Maeuse: ', jung)
print('Anzahl erwachsener Maeuse: ', erwachsen)
print('Anzahl alter Maeuse: ', alt)
Quelltext
 Jede Anweisung wird im Quelltext 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 bearbeiten. Bei der Ausführung von
Programmen werden sie ignoriert.
32
Fachkonzept - EVA-Prinzip
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.
Eingabe
Verarbeitung
Ausgabe
# Eingabe
...
jung = int(input("Anzahl junger Maeuse: "))
...
# Verarbeitung
schritt = 0
...
# Ausgabe
...
print('Anzahl junger Maeuse: ', jung)
...
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.
Fehler in Programmen
33
Jeder macht Fehler!
# Eingabe
print('Gib die Werte der Ausgangspopulation ein:')
jung = input('Anzahl junger Maeuse: ')
erwachsen = input('Anzahl erwachsener Maeuse: ')
alt = input('Anzahl alter Maeuse: '
# Verarbeitung
hilf = erwachsen*4 + alt*2
alt = erwachsen // 3
erwachen = jung // 2
jung = 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
Aufgabe:
Teste, wie sich das
Programm verhält. Findest
du die Fehler? Worin
unterscheiden sie sich?
34
Fehler in Programmen
Bei einem Syntaxfehler hat man eine Regel der gewählten Programmiersprache nicht
beachtet.
Programmfenster
Aufgabe:
Welcher Syntaxfehler wird
hier angezeigt?
35
Fehler in Programmen
Laufzeitfehler treten während der Abarbeitung des Programms (zur Laufzeit) auf.
# Eingabe
Aufgabe:
print('Gib die Werte der Ausgangspopulation ein:')
Warum kommt es hier zu
jung = input('Anzahl junger Maeuse: ')
einem Laufzeitfehler?
erwachsen = input('Anzahl erwachsener Maeuse: ')
alt = input('Anzahl alter Maeuse: ')
# Verarbeitung
hilf = erwachsen*4 + alt*2
alt = erwachsen // 3
erwachen = jung // 2
Ausführfenster
jung = hilf
# Ausgabe:
>>>
print('')
Gibsind:')
die Werte der Ausgangspopulation ein:
print('Die berechneten Populationswerte
print('Anzahl junger Maeuse: ', jung) Anzahl junger Maeuse: 6
Anzahl erwachsener Maeuse: 9
print('Anzahl erwachsener Maeuse: ', erwachsen)
Anzahl alter Maeuse: 12
print('Anzahl alter Maeuse: ', alt)
Traceback (most recent call last):
File ...
Programmfenster
alt = erwachsen // 3
TypeError: unsupported operand type(s) for //: 'str' and
'int'
36
Fehler in Programmen
Logische Fehler liegen vor, wenn das System nicht die beabsichtigten Ausgaben erzeugt.
# Eingabe
Aufgabe:
print('Gib die Werte der Ausgangspopulation ein:')
Welcher logische Fehler liegt
jung = int(input('Anzahl junger Maeuse: '))
hier vor?
erwachsen = int(input('Anzahl erwachsener Maeuse: '))
alt = int(input('Anzahl alter Maeuse: '))
# Verarbeitung
Ausführfenster
hilf = erwachsen*4 + alt*2
alt = erwachsen // 3
>>>
erwachen = jung // 2
Gib die Werte der Ausgangspopulation ein:
jung = hilf
Anzahl junger Maeuse: 6
# Ausgabe:
Anzahl erwachsener Maeuse: 9
print('')
Anzahl
print('Die berechneten Populationswerte
sind:')alter Maeuse: 12
print('Anzahl junger Maeuse: ', jung)
Die berechneten Populationswerte sind:
print('Anzahl erwachsener Maeuse: ', erwachsen)
Anzahl junger Maeuse: 60
print('Anzahl alter Maeuse: ', alt)
Anzahl erwachsener Maeuse: 9
Anzahl alter Maeuse: 3
Programmfenster
>>> globals()
{..., 'erwachsen': 9, 'jung': 60, ..., 'erwachen': 3, ..., 'alt':
3, ..., 'hilf': 60}
37
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.
# Eingabe
eingabe = input('Anzahl junger Maeuse: ')
print(type(eingabe))
jung = int(eingabe)
print(type(jung))
# Verarbeitung
erwachsen = jung // 2
print(type(erwachsen))
# Ausgabe:
ausgabe = 'Anzahl erwachsener Maeuse: ' + str(erwachsen)
print(type(ausgabe))
print(ausgabe)
Programm mit Ausgabe von 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?
38
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.
>>> jung = 6
>>> jung
6
>>> type(jung)
<class 'int'>
>>> erwachsen = jung // 2
>>> erwachsen
3
>>> type(erwachsen)
<class 'int'>
>>> erwachsen = jung / 2
>>> erwachsen
3.0
>>> type(erwachsen)
<class 'float'>
# Eingabe
eingabe = input('Anzahl junger Maeuse: ')
print(type(eingabe))
jung = int(eingabe)
print(type(jung))
# Verarbeitung
erwachsen = jung // 2
print(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
39
Exkurs: Datentypen in Python
>>> 2
2
Datentyp: ganze Zahl
int
>>> 2.0
2.0
Datentyp: Dezimalzahl
float
>>> True
True
Datentyp: Wahrheitswert
bool
Datentyp: Zeichenkette
string
>>> ('Hans', 'Meier', 34, 'Koblenz')
('Hans', 'Meier', 34, 'Koblenz')
Datentyp: Tupel
tuple
>>> [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
Datentyp: Liste
list
...
...
>>> 'Hallo!'
'Hallo!'
>>> "Hallo!"
'Hallo!'
40
Exkurs: Typumwandlungen in Python
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.
>>>
3
>>>
3.0
>>>
3
>>>
3
>>>
3.0
>>>
'3'
int("3")
float("3")
int(3.0)
int(3.5)
float(3)
str(3)
>>> list("[1, 2, 3]")
['[', '1', ',', ' ', '2', ',', ' ', '3', ']']
>>> eval("[1, 2, 3]")
[1, 2, 3]
41
Wiederholte Berechnungen
# Eingabe
...
# Verarbeitung
schritt = 0
hilf = erwachsen*4 + alt*2
alt = erwachsen // 3
erwachsen = jung // 2
jung = hilf
schritt = schritt + 1
hilf = erwachsen*4 + alt*2
alt = erwachsen // 3
erwachsen = jung // 2
jung = hilf
schritt = schritt + 1
hilf = erwachsen*4 + alt*2
alt = erwachsen // 3
erwachsen = jung // 2
jung = hilf
schritt = schritt + 1
...
# Ausgabe:
...
Programm mit einer Folge von Zuweisungen
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?
42
Wiederholte Berechnungen
# Eingabe
jung = int(input("Anzahl der jungen Maeuse: "))
erwachsen = int(input("Anzahl der erwachsenen Maeuse: "))
alt = int(input("Anzahl der alten Maeuse: "))
Aufgaben:
# Verarbeitung
schritt = 0
while schritt < 10:
hilf = erwachsen*4 + alt*2
alt = erwachsen // 3
erwachsen = jung // 2
jung = hilf
schritt = schritt + 1
(b) Ändere das gezeigte
Programm so ab, dass
folgende Aufgaben erledigt
werden können:
# Ausgabe:
print("Neue Populationswerte:")
print("Anzahl der Schritte: ", schritt)
print("Anzahl junger Maeuse: ", jung)
print("Anzahl erwachsener Maeuse: ", erwachsen)
print("Anzahl alter Maeuse: ", alt)
- Der Benutzer kann selbst
eingeben, wie viele Schritte
simuliert werden sollen.
Programm mit Wiederholungsanweisung
(a) Erkläre, warum der Simulationsschritt hier genau
10 mal durchgeführt wird.
- In jedem Berechnungsschritt sollen die aktuellen
Populationswerte
ausgegeben werden.
- Der Benutzer kann eine
bestimmte Gesamtanzahl
von Mäusen eingeben, bis
zu der die Simulation
durchgeführt werden soll.
Ausgabe: Schritte
43
Fachkonzept - Wiederholung
Eine Solange-Wiederholung besteht aus einer Bedingung und einer Anweisungssequenz.
Solange die Bedingung erfüllt ist, wird die Anweisungssequenz ausgeführt.
Aufbau
SOLANGE [Bedingung]:
[Anweisungssequenz]
Struktogramm
Python-Syntax
Schlüsselwort
Flussdiagramm
Einrückung
Doppelpunkt
while [Bedingung]:
[Anweisungssequenz]
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 = 100
b = 1.8
c = a / (b*b)
print(a, b, c)
(b) Erstelle selbst ein benutzer- und entwicklerfreudliches Programm zur automatisierten BMIBerechnung.
45
Teil 2
Zufallsexperimente Ablaufmodellierung mit Kontrollstrukturen
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.
Erzeugung von Zufallszahlen
47
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.
>>>
>>>
2
>>>
5
>>>
5
>>>
>>>
6
from random import randint
randint(1, 6)
randint(1, 6)
randint(2, 5)
augen = randint(1, 6)
augen
Erzeugung von Zufallszahlen
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.
49
Simulation eines Münzwurfs
from random import randint
# Eingabe
tipp = input('Kopf (K) oder Zahl (Z): ')
# Verarbeitung mit Ausgabe
zufallszahl = randint(0, 1)
if zufallszahl == 0:
print('Kopf ist gefallen.')
seite = 'K'
else:
print('Zahl ist gefallen.')
seite = 'Z'
# Ausgabe
# ...
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).
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
# Eingabe
tipp = input('Kopf (K) oder Zahl (Z): ')
if tipp == 'k':
tipp = 'K'
if tipp == 'z':
tipp = 'Z'
# Verarbeitung mit Ausgabe
zahl = randint(0, 1)
if zahl == 0:
print('Kopf ist gefallen.')
seite = 'K'
else:
print('Zahl ist gefallen.')
seite = 'Z'
# Ausgabe
# ...
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
# Verarbeitung
augen = randint(1, 6)
if augen == 1:
bild = 'o'
else:
if augen == '2':
bild = 'oo'
else:
if augen == '3':
bild = 'ooo'
else:
# ...
# Ausgabe
print(bild)
from random import randint
# Verarbeitung
augen = 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'
# Ausgabe
print(bild)
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.
53
Fachkonzept - Fallunterscheidung
Eine Fallunterscheidung dient
dazu, alternative Abläufe zu
beschreiben.
54
Fachkonzept - Fallunterscheidung
Eine Fallunterscheidung dient dazu, alternative Abläufe zu beschreiben.
WENN [Bedingung]:
[Anweisungssequenz]
SONST:
[Anweisungssequenz]
zweiseitige
Fallunterscheidung
WENN [Bedingung]:
[Anweisungssequenz]
einseitige
Fallunterscheidung
55
Fachkonzept - Fallunterscheidung
Eine Fallunterscheidung dient dazu, alternative Abläufe zu beschreiben.
zweiseitige
Fallunterscheidung
einseitige
Fallunterscheidung
Doppelpunkt
if [Bedingung]:
[Anweisungssequenz]
else:
[Anweisungssequenz]
if zahl == 0:
print('Kopf ist gefallen.')
seite = 'K'
else:
print('Zahl ist gefallen.')
seite = 'Z'
Schlüsselwort
Einrückung
if [Bedingung]:
[Anweisungssequenz]
if tipp == 'k':
tipp = 'K'
if tipp == 'z':
tipp = 'Z'
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:
# ...
Schlüsselwort
Einrückung
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
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
# Verarbeitung
augenzahl = randint(1, 6)
zaehler = 1
while augenzahl != 6:
augenzahl = randint(1, 6)
zaehler = zaehler + 1
# Ausgabe
print('Anzahl der Versuche: ', zaehler)
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.
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
...
60
Fachkonzept - Wiederholung
Eine Solange-Wiederholung besteht aus einer Bedingung und einer Anweisungssequenz.
Solange die Bedingung erfüllt ist, wird die Anweisungssequenz ausgeführt.
Aufbau
SOLANGE [Bedingung]:
[Anweisungssequenz]
Struktogramm
Python-Syntax
Schlüsselwort
Flussdiagramm
Einrückung
Doppelpunkt
while [Bedingung]:
[Anweisungssequenz]
61
Exkurs - Kontrollstrukturen
Kontrollstrukturen sind Ablaufbausteine, die dazu dienen, die Reihenfolge der Abarbeitung von
Anweisungen (eines Algorithmus / eines Programms) festzulegen.
62
Exkurs - Struktogramme
Besonders deutlich werden die Ablaufbausteine, wenn man sie mit einer Bildsprache - den
sogenannten Struktogrammen - beschreibt.
Pasch
63
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.
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.
from random import randint
# Würfelergebnisse
w1 = randint(1, 6)
w2 = randint(1, 6)
w3 = randint(1, 6)
print(w1, w2, w3)
# Bedingung
print((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)))
64
Pasch
Aufgabe:
Aufgabe:
Was leistet das folgende Programm?
Analysiere hierzu den Quelltext und erkläre
die einzelnen Anweisungen. Teste
anschließend deine Vermutung.
Was leistet das folgende Programm?
Analysiere hierzu den Quelltext und erkläre
die einzelnen Anweisungen. Teste
anschließend deine Vermutung
from random import randint
# Verarbeitung
pasch = False
versuche = 0
while 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
# Ausgabe
print(versuche)
from random import randint
# Initialisierung
n=5
# Verarbeitung (mit Ausgaben)
pasch = True
w1 = randint(1, 6)
print(w1)
for i in range(n-1):
w = randint(1, 6)
print(w)
if w != w1:
pasch = False
# Ausgabe
if pasch:
print('Pasch')
else:
print('kein Pasch')
Logische Operatoren
65
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
not a
a
b
a and b
a
b
a or b
False
True
False
False
False
False
False
False
True
False
False
True
False
False
True
True
True
False
False
True
False
True
True
True
True
True
True
True
nicht
Negation
Konjunktion
und
Disjunktion
oder
66
Fachkonzept - Wahrheitswerte
Zur Beschreibung von Werten von Bedingungen benutzt man die Wahrheitswerte wahr and
falsch bzw. True and False.
Wahrheitswerte treten bei der Auswertung von Bedingungen auf. Wahrheitswerte können aber
auch direkt mit logischen Variablen verwaltet werden.
from random import randint
# Verarbeitung
w1 = randint(1, 6)
w2 = randint(1, 6)
zusammengesetzte
w3 = randint(1, 6)
Bedingung
versuche = 1
while not (w1 == w2 and w1 == w3):
w1 = randint(1, 6)
w2 = randint(1, 6)
w3 = randint(1, 6)
versuche = versuche + 1
# Ausgabe
print(versuche)
from random import randint
# Initialisierung
n = 5 # 5er-Pasch
# Verabeitung
logische Variable
gefunden = False
versuche = 0
while 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
# Ausgabe
print(versuche)
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.
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.
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.
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.
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.
72
Anwendung - Ziegenproblem
Tür-Auto: 1
Tür-Kandidat: 1
Tür-Mod.: 2|3
Tür-Kandidat: 2
Tür-Mod.: 3
Tür-Auto: 2
Tür-Auto: 3
Tür-Kandidat: 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?
73
Anwendung - Ziegenproblem
Ein Programm soll das Spiel anbieten und
dabei die Rolle des Moderators übernehmen.
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).
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.
75
Teil 3
Verschlüsselung Modularisierung mit Funktionen
Veschlüsselung
76
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.
PYLZFOWBNQCYBUVNCBLGYC
HYAYBYCGMWBLCZNYHNTCZY
LN
VDOYH
FDHVDU
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
Quelltext:
SALVECAESAR
Schlüssel: 3
Geheimtext:
VDOYHFDHVDU
77
>>>
>>>
'A'
>>>
>>>
65
>>>
>>>
68
>>>
>>>
'D'
Automatisierte Verschlüsselung
zeichen = 'A'
zeichen
zahl = ord(zeichen)
zahl
neuezahl = zahl + 3
neuezahl
neueszeichen = chr(neuezahl)
neueszeichen
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?
>>> 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'
78
Automatisierte Verschlüsselung
# Vorgabe
klartext = 'HALLO'
# Verarbeitung
geheimtext = ''
for zeichen in klartext:
zahl = ord(zeichen)
neuezahl = zahl + 3
if neuezahl > ord('Z'):
neuezahl = neuezahl - 26
neuesZeichen = chr(neuezahl)
geheimtext = geheimtext +
neuesZeichen
# Ausgabe
print(geheimtext)
# Vorgabe
text = 'Dieser Text müßte "bereingt"
werden.'
# Verarbeitung
textNeu = ''
for zeichen in text:
if ord(zeichen) >= ord('A') and \
ord(zeichen) <= ord('Z'):
# zeichen ist ein Großbuchstabe
textNeu = textNeu + zeichen
# ...
# Ausgabe
print(text)
print(textNeu)
Aufgabe:
Aufgabe:
Entwickle entsprechend ein Programm zur
Entschlüsselung von Texten, die nach dem
Caesar-Verfahren verschlüsselt wurden.
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.
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 mehrere
Zeilen.
Darstellung von Zeichenketten
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.
>>> 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'
lesender Zugriff auf einzelne Zeichen
beachte den Indexbereich
Länge einer Zeichenkette
81
Fachkonzept - Zeichenkette
Zeichenketten kann man über den Indexbereich, oder direkt über die einzelnen Zeichen
durchlaufen.
# klartext = ...
i=0
while i < len(klartext):
# verarbeite klartext[i]
i=i+1
# klartext = ...
for zeichen in klartext:
# verarbeite zeichen
Schleife über den Indexbereich
for-Schleife für sequentielle Datenobjekte
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
>>>
>>>
>>>
>>>
>>>
'HE'
klartext = 'HALLO'
klartextNeu = ''
klartextNeu = klartextNeu + klartext[0]
klartextNeu = klartextNeu + 'E'
klartextNeu
kein schreibender Zugriff erlaubt
Zusammenfügen von Zeichenketten
83
Strukturierung des Programms
text = '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 = textNeu
print(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
print(geheimtext)
...
...
klartext = ''
for zeichen in geheimtext:
zahl = ord(zeichen)
neuezahl = zahl - 3
if neuezahl < ord('A'):
neuezahl = neuezahl + 26
neuesZeichen = chr(neuezahl)
klartext = klartext + neuesZeichen
print(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.
84
Zerlegung in Verarbeitungseinheiten
text = 'Alles Käse!'
print(text)
# Text bereinigen
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 = textNeu
print(klartext)
# Text verschlüsseln
geheimtext = ''
for zeichen in klartext:
zahl = ord(zeichen)
neuezahl = zahl + 3
if neuezahl > ord('Z'):
neuezahl = neuezahl - 26
neuesZeichen = chr(neuezahl)
geheimtext = geheimtext + neuesZeichen
print(geheimtext)
# Text entschlüsseln
klartext = ''
for zeichen in geheimtext:
zahl = ord(zeichen)
neuezahl = zahl - 3
if neuezahl < ord('A'):
neuezahl = neuezahl + 26
neuesZeichen = chr(neuezahl)
klartext = klartext + neuesZeichen
print(klartext)
85
Eigenständige Verarbeitungseinheit
Funktion
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'
# Text verschlüsseln
geheimtext = ''
for zeichen in klartext:
zahl = ord(zeichen)
neuezahl = zahl + 3
if neuezahl > ord('Z'):
neuezahl = neuezahl - 26
neuesZeichen = chr(neuezahl)
geheimtext = geheimtext + neuesZeichen
print(geheimtext)
Aufgabe:
Entwickle und teste analog
Funktionsdefinitionen zu den Funktionen
entschluesselterText und bereinigterText.
Funktionsdefinition
Funktionsaufruf
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
Funktionsdefinition
Aufgabe:
Ergänze die fehlenden Teile und
speichere den gesamten Quelltext in
einer Datei ab. Teste das Programm auch mit anderen Texten.
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)
Funktionsaufruf
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
Funktionsdefinition
Funktionsaufruf
...
# Testprogramm
text1 = 'Alles Käse!'
text2 = bereinigterText(text1)
text3 = verschluesselterText(text2)
text4 = entschluesselterText(text3)
print(text1)
print(text2)
print(text3)
print(text4)
Aufgabe:
Ergänze die fehlenden Teile und
speichere den gesamten Quelltext in
einer Datei ab. Teste das Programm auch mit anderen Texten.
88
Datenübergabe mit Parametern
# Funktionsdefinitionen
def verschluesseltesZeichen(zeichen, schluessel):
# ...
return neuesZeichen
def verschluesselterText(klartext, schluessel):
# ...
return geheimtext
Funktionsdefinition
...
# Testprogramm
text1 = 'Alles Käse!'
text2 = bereinigterText(text1)
text3 = verschluesselterText(text2, 4)
text4 = entschluesselterText(text3, 4)
print(text1)
print(text2)
print(text3)
print(text4)
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.
Funktionen
89
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.
Schlüsselwort
Funktionsname(Parameter)
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
Doppelpunkt
Funktionsdefinition
Einrückung
>>> verschluesselterText('HALLO', 4)
'LEPPS'
Funktionsaufruf
Parameter
90
Parameter sind Variablen, mit deren Hilfe die zur Verarbeitung übergebenen Daten bei einer
Funktion verwaltet werden.
Datenübergabe
Datenrückgabe
verschluesselterText
'HALLO'
text
return ...
zu
verarbeitende
Daten
Parameter
Parameter
def verschluesselterText(klartext, schluessel):
...
return geheimtext
'KDOOR'
zurückgelieferte
Daten
aktuelle Daten
>>> verschluesselterText('HALLO', 4)
'LEPPS'
Funktionsaufruf
Funktionsdefinition
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.
Übungen
92
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)
93
Laden und Speichern
def 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()
# Testprogramm
text1 = 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?
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')
Funktionsaufruf
Prozeduraufruf
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.
95
Häufigkeitsanalyse
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?
XREQXRCCZVEZJKZEUIVZKVZCVXVKVZCKVZEVEURMFESVNFYEVEUZVSVCXVIUVEREUVI
VEUZVRHLZKREVILEUUVEUIZKKVEUZVUZVZEZYIVIVZXVEVEJGIRTYVBVCKVEXVEREEK
NVIUVELEUZELEJVIVIXRCCZVIYVZJJVEJZVRCCVLEKVIJTYVZUVEJZTYLEKVIVZEREU
VIZEJGIRTYVXVNFYEYVZKVELEUXVJVKQVEUZVXRCCZVIKIVEEKMFEUVERHLZKREVIEU
VIWCLJJXRIFEEVMFEUVESVCXVIEUZVDRIEVLEUUZVJVZEVUZVKRGWVIJKVERCCUZVJV
IJZEUUZVSVCXVILEUQNRIUVJNVXVENVZCJZVMFEUVIBLCKLILEUCVSVEJNVZJVUVIIF
VDZJTYVEGIFMZEQRDNVZKVJKVEVEKWVIEKJZEUJVYIJVCKVEBRLWCVLKVQLUZVJVEBF
DDVELEUURJNRJQLIMVINVZTYCZTYLEXUVIXVDLVKVIWLVYIKVZEWLVYIVELEUNVZCJZ
VUVEXVIDREVEUZVAVEJVZKJUVJIYVZEVJCVSVELEUDZKUVEVEJZVJKRVEUZXBIZVXWL
VYIVEJVYIERYVJZEURLJUZVJVDXILEULVSVIKIVWWVERLTYUZVYVCMVKZVIUZVLVSIZ
XVEXRCCZVIREKRGWVIBVZKNVZCJZVJZTYZEWRJKKRVXCZTYVEXVWVTYKVEDZKUVEXVI
DREVEDVJJVENFSVZJZVUZVJVVEKNVUVIMFEZYIVDXVSZVKWVIEYRCKVEFUVIJVCSJKZ
EUVIVEXVSZVKBRVDGWVEVZEKVZCURMFEUVENZVXVJRXKUZVXRCCZVISVNFYEVEWZEUV
KJVZEVELIJGILEXREUVIIYFEVNZIUSVXIVEQKMFEUVIXRIFEEVUVDFQVRELEUUVDXVS
ZVKUVISVCXVIVIJKIVTBKJZTYMFEUVEJVHLREVIELEUYVCMVKZVIEYZESZJQLDIYVZE
LEUQVZXKERTYEFIUVEURJXVSZVKUVISVCXVISVXZEEKREUVERVLJJVIJKVEXIVEQVEX
RCCZVEJVIJKIVTBKJZTYSZJREUVELEKVIVEKVZCUVJIYVZEJLEUCZVXKERTYEFIUFJK
VERHLZKREZVEVIJKIVTBKJZTYMFEUVDWCLJJXRIFEEVSZJREUZVGPIVERVVELEUQLUV
DAVEZXVEKVZCUVJFQVREJUVISZJJGREZVEIVZTYKVJCZVXKZEIZTYKLEXEFIUNVJKVE
96
text = """
ABRAKADABRA
SIMSALABIM
"""
anzahl = 0
for zeichen in text:
if zeichen == 'A':
anzahl = anzahl + 1
print('A', ':', anzahl)
anzahl = 0
for zeichen in text:
if zeichen == 'B':
anzahl = anzahl + 1
print('B', ':', anzahl)
anzahl = 0
for zeichen in text:
if zeichen == 'C':
anzahl = anzahl + 1
print('C', ':', anzahl)
...
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.
97
Häufigkeitsanalyse
def haeufigkeit(buchstabe, text):
anzahl = 0
for zeichen in text:
if zeichen == buchstabe:
anzahl = anzahl + 1
return anzahl
Aufgabe:
# Testprogramm
(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.
aktuellerText = """
ABRAKADABRA
SIMSALABIM
"""
print('A', ':', haeufigkeit('A', aktuellerText))
print('B', ':', haeufigkeit('B', aktuellerText))
print('C', ':', haeufigkeit('C', aktuellerText))
print('D', ':', haeufigkeit('D', aktuellerText))
# ...
(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.)
98
Häufigkeitsanalyse
...
# Testprogramm
aktuellerText = """
ABRAKADABRA
SIMSALABIM
"""
abc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
for zeichen in abc:
...
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.
99
Verwendung von Funktionen
# 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)
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 Strukturierung von Programmen. Mit Funktionen
kann man Verarbeitungseinheiten bilden
und diese als Unterprogramme in einem
größeren Programm verwenden.
100
Verwendung von Funktionen
def haeufigkeit(buchstabe, text):
anzahl = 0
for zeichen in text:
if zeichen == buchstabe:
anzahl = anzahl + 1
return anzahl
# Testprogramm
aktuellerText = """
ABRAKADABRA
SIMSALABIM
"""
abc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
for zeichen in abc:
hZeichen = haeufigkeit(zeichen, aktuellerText)
print(zeichen, ':', hZeichen)
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.
101
Veschlüsselung mit Zuordnungstabelle
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.
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
Quelltext:
Schlüssel: GKXCSLZUAHW..
SALVECAESAR
J U L I U S C A E S A R
| | | | | | | | | | | |
H P D A P J . . . . . .
Geheimtext:
JGDOSXGSJGN
. . . . . . . . . . . .
| | | | | | | | | | | |
J G D O S G J V S N A R
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
103
Veschlüsselung mit Zuordnungstabelle
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.
# Import der Funktionen
from verschluesselung_mit_zuordnungstabelle import *
# Verwendung der Funktionen
zuordnung = 'GKXCSLZUAHWDBMTYENJVPOIRFQ'
geheimtext = verschluesselterText('SALVECAESAR', zuordnung)
print(geheimtext)
Verwendung des
fertigen Bausteins
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
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 *
Strukturierung des
Quelltextes
# Verwendung der Funktionen
zuordnung = 'GKXCSLZUAHWDBMTYENJVPOIRFQ'
geheimtext = verschluesselterText('SALVECAESAR', zuordnung)
print(geheimtext)
Vermeidung von
Codeduplizierung
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?
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
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')
Testfälle
'K'
"""
>>>
Trying:
nummer = ord(zeichen)-ord('A')
verschluesselterText('HUND', 'GKXCSLZUAHWDBMTYENJVPOIRFQ')
neuesZeichen = schluessel[nummer]
Expecting:
return neuesZeichen
'UPMC'
ok
def verschluesselterText(klartext, schluessel):
Trying:
verschluesseltesZeichen('B', 'GKXCSLZUAHWDBMTYENJVPOIRFQ')
...
Expecting:
'K'
if __name__ == '__main__':
ok
from doctest import testmod
2 items passed all tests:
testmod(verbose=True)
1 tests in __main__.verschluesselterText
1 tests in __main__.verschluesseltesZeichen
2 tests in 2 items.
automatisierter Modultest in
2 passed and 0 failed.
Testprotokoll
Python
Test passed.
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
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?
# Testprogramm
zuordnung = 'GKXCSLZUAHWDBMTYENJVPOIRFQ'
aktuellerKlartext = 'OBELIX'
geheimtext = None
aktuellerGeheimtext = verschluesselterText(aktuellerKlartext, zuordnung)
print()
print(klartext)
print(geheimtext)
print()
print('globale Variablen:')
print(globals())
110
Experimente mit Variablen
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
schluessel = 'GKXCSLZUAHWDBMTYENJVPOIRFQ'
klartext = 'OBELIX'
geheimtext = None
geheimtext = 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?
111
Experimente mit Variablen
def 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 = None
textVerschluesseln()
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?
112
Experimente mit Variablen
def 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 = None
textVerschluesseln()
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?
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
# Test
a=2
b = d(a)
print(a)
>>>
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
def d(x):
x=x+x
return x
# Test
x=2
y = d(x)
print(y)
>>>
4
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
# Test
x=2
y = d()
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}
def d():
global x
global y
y=x+x
# Test
x=2
d()
print(y)
>>>
4
Verändert man innerhalb einer Prozedur den Wert einer globalen Variablen, so spricht man
auch von einem Seiteneffekt.
115
Teil 4
Lotto Datenverwaltung mit Datenstrukturen
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.
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
...
>>> ziehung1
25
>>> ziehung2
40
...
Verwendung vieler Variablen
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?
# 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 einer Variablen sowie einer
Liste als "Datencontainer"
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, \
]
119
Eine Liste durchlaufen
Die Zahlen einer Lotto-Ziehung (ohne Zusatzzahl) sollen mit einer Liste verwaltet werden.
Die Listenelemente sind dabei - beginnend mit
0 - mit einem Index durchnummeriert.
# Initialisierung
ziehung = [25, 40, 44, 1, 45, 21]
# Verarbeitung und Ausgabe
i=0
while 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:
>>>
Kugel
Kugel
Kugel
Kugel
Kugel
Kugel
Liste über den Index durchlaufen
1
2
3
4
5
6
:
:
:
:
:
:
25
40
44
1
45
21
120
Eine Liste durchlaufen
Die Zahlen einer Lotto-Ziehung (ohne Zusatzzahl) sollen mit einer Liste verwaltet werden.
Die Listenelemente sind dabei - beginnend mit
0 - mit einem Index durchnummeriert.
# Initialisierung
ziehung = [25, 40, 44, 1, 45, 21]
# Verarbeitung und Ausgabe
for z in ziehung:
print(z)
Aufgabe:
Teste auch dieses Programm. Was leistet
es?
Liste über die Elemente durchlaufen
121
Anzahl der Richtigen
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.
# Initialisierung
ziehung = [25, 40, 44, 1, 45, 21]
tipp = [1, 12, 21, 31, 37, 46]
# Verarbeitung
richtige = 0
i=0
while i < len(ziehung):
j=0
while j < len(tipp):
print('vergleiche: ', ziehung[i], tipp[j])
# ...
j = j+1
i = i+1
# Ausgabe
print(richtige)
# Initialisierung
ziehung = [25, 40, 44, 1, 45, 21]
tipp = [1, 12, 21, 31, 37, 46]
# Verarbeitung
richtige = 0
for z in ziehung:
for t in tipp:
print('vergleiche: ', z, t)
# ...
# Ausgabe
print(richtige)
Ergänze die noch fehlenden Vergleiche.
122
Anzahl der Richtigen
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.
# Initialisierung
ziehung = [
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, \
...
]
# Verarbeitung
richtige = 0
# ...
# Ausgabe
print(richtige)
Elemente hinzufügen
123
Der folgende Python-Dialog zeigt, wie man eine Liste zur Verwaltung der Zahlen eines Tipps
schrittweise aufbauen kann.
>>> tipp
>>> tipp
[]
>>> tipp
>>> tipp
[12]
>>> tipp
>>> tipp
[12, 15]
>>> tipp
>>> tipp
...
>>> tipp
>>> tipp
...
>>> tipp
>>> tipp
...
= []
= tipp + [12]
= tipp + [15]
= [7] + tipp
= tipp + [42, 47]
= [3] + tipp
Listen aneinanderhängen
Aufgabe:
Analysiere den gezeigten Python-Dialog.
Stelle Vermutungen auf, was an Stelle der
drei Punkte ... steht. Überprüfe deine
Vermutung.
124
Elemente löschen
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.
>>> 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]
Zugriff auf Teillisten
Aufgabe:
Führe selbst entsprechende Dialoge. Kannst
du erklären, wie die neue Liste zustande
kommt?
125
Ziehung automatisiert erzeugen
Ziel ist es, eine Ziehung der Lottozahlen mit Hilfe des
Zufallsgenerators von Python zu simulieren. Hier ein
erster Vorschlag:
from random import *
# Verarbeitung
ziehung = []
for i in range(6):
zahl = randint(1, 49)
ziehung = ziehung + [zahl]
# Ausgabe
print(ziehung)
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?
126
Ziehung automatisiert erzeugen
Ziel ist es, eine Ziehung der Lottozahlen mit Hilfe des
Zufallsgenerators von Python zu simulieren. Hier ein
weiterer Vorschlag:
from random import *
# Verarbeitung
ziehung = []
for i in range(49):
ziehung = ziehung + [False]
for i in range(6):
zahl = randint(1, 49)
ziehung[zahl-1] = True
# Ausgabe
for i in range(49):
if ziehung[i] == True:
print(i+1)
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?
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.
 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]
['amueller@gmx.de', 'carla2@hotmail.org', 'herbert.fluhr@web.de', ...]
[]
[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]]
Brot
Butter
Joghurt
Äpfel
Schokolade
Mehl
Eier
...
128
Liste als sequentieller Datentyp
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.
Element
ziehung
25
40
44
1
45
21
0
1
2
3
4
5
Index
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.
>>> L = [10, 15, 21, 33, 37, 40]
>>> L[0]
10
>>> L[1]
lesender Zugriff
15
>>> L = [10, 15, 21, 33, 37, 40]
>>> L
[10, 15, 21, 33, 37, 40]
>>> L[4] = 36
schreibender Zugriff
>>> L
[10, 15, 21, 33, 36, 40]
129
Liste als sequentieller Datentyp
ziehung
>>> ziehung = [25, 40, 44, 1, 45, 21]
>>> ziehung[0:2]
[25, 40]
>>> ziehung[2:5]
[44, 1, 45]
>>> ziehung[3:3]
[]
Teillisten
25
40
44
1
45
21
0
1
2
3
4
5
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.
>>> ziehung = [25, 40, 44, 1, 45, 21]
>>> ziehung[:2]
[25, 40]
>>> ziehung[2:]
[44, 1, 45, 21]
>>> ziehung[:]
[25, 40, 44, 1, 45, 21]
130
Liste als sequentieller Datentyp
ziehung
25
40
44
1
45
21
0
1
2
3
4
5
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.
>>> 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
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.
>>> tippAnfang = [2, 6, 16, 40]
>>> len(tippAnfang)
4
>>> len([])
0
Länge
131
Liste als sequentieller Datentyp
ziehung
25
40
44
1
45
21
0
1
2
3
4
5
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.
Mit einer for-Anweisung der Gestalt
for e in L: ...
kann man alle Elemente einer Liste
(Sequenz) der Reihe nach durchlaufen.
>>>
>>>
>>>
False
>>>
>>>
True
>>> ziehung = [25, 40, 44, 1, 45, 21]
>>> for z in ziehung:
...
print(z)
...
25
40
44
1
Durchlaufen einer Liste
45
21
tippAnfang = [2, 6, 16, 40]
t = 25
t in tippAnfang
t = 40
t in tippAnfang
Elementbeziehung
Übungen
132
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
return N
# neue Liste
Übungen
133
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)]
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.
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.
Übungen
136
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']
"""
# ...
137
Achtung: Fehlerquelle
Simone 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]
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]
>>> tipp1 = [4, 13, 21, 33, 34, 42]
>>> id(tipp1)
12289008
>>> type(tipp1)
<type 'list'>
>>> tipp1
[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.
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]
140
Exkurs: Listenverarbeitung
funktional: L = Listenkonstruktor
>>> 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)
Erzeugung neuer Listen
12289008
objektorientiert: L.Listenoperation
>>> 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
Veränderung einer
bestehenden Listen
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.
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.
Datenmodellierung mit Listen
143
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.
>>>
>>>
>>>
>>>
...
>>>
...
>>>
...
>>>
...
gewinnzahlen = [33, 13, 8, 12, 40, 41]
zusatzzahl = 2
ziehung = [gewinnzahlen, zusatzzahl]
ziehung
ziehung[1]
ziehung[0]
ziehung[0][2]
Aufgabe:
Was steht vermutlich an Stelle der drei Punkte? Überprüfe deine Vermutung.
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.
145
Datenmodellierung mit Tupeln
Bisher haben wir Folgen von Daten immer mit
Listen erfasst. In Python geht das aber auch
anders - mit sogenannten Tupeln.
Liste als Datencontainer
>>> gewinnzahlen = [33, 13, 17, 12, 40, 41]
>>> gewinnzahlen[1]
13
>>> gewinnzahlen[1] = 17
>>> gewinnzahlen
[33, 17, 17, 12, 40, 41]
>>> gewinnzahlen = [33, 13, 8, 12, 40, 41]
>>> zusatzzahl = 2
>>> ziehung = (gewinnzahlen, zusatzzahl)
>>> ziehung
([33, 13, 8, 12, 40, 41], 2)
>>> ziehung[1]
2
Tupel und Liste
>>> ziehung[0]
als Datencontainer
[33, 13, 8, 12, 40, 41]
Tupel als Datencontainer
>>> gewinnzahlen = (33, 13, 17, 12, 40, 41)
>>> gewinnzahlen
(33, 13, 17, 12, 40, 41)
>>> gewinnzahlen[1]
13
>>> gewinnzahlen[1] = 17
Traceback (most recent call last):
File ...
gewinnzahlen[1] = 17
TypeError: 'tuple' object does not support
item assignment
Aufgabe:
Vergleiche die verschiedenen
Datenmodellierungen.
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)
Tupel zusammenpacken
>>> gewinnzahlen = (33, 13, 17, 12, 40, 41)
>>> gewinnzahlen
(33, 13, 17, 12, 40, 41)
>>> gewinnzahlen[1]
13
>>> gewinnzahlen[1] = 17
Traceback (most recent call last):
File ...
gewinnzahlen[1] = 17
TypeError: 'tuple' object does not support
item assignment
>>> ziehung = ((33, 13, 8, 12, 40, 41), 2)
>>> (gewinnzahlen, zusatzzahl) = ziehung
>>> gewinnzahlen
(33, 13, 8, 12, 40, 41)
>>> zusatzzahl
2
Tupel auspacken
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"
148
Übungen - Datenstruktur
Aufgabe 1: Zugriff auf geschachtelte Daten
Ergänze die Ergebnisse. Überprüfe sie mit Python.
>>> 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 2: Datenmodellierung
Wie könnte man die Gewinnquoten beim Lotto mit
Datenstrukturen erfassen?
Herunterladen