Beruflich Dokumente
Kultur Dokumente
Vorkenntnisse
Innerhalb von 7 Tagen ein
neuronales Netz programmieren
lernen
Benjamin Spahic
Inhalt
1. Vorwort und Einleitung ............................................................ 1
2. Vorbereitung – Interpreter und Texteditor installieren ........... 4
2.1. Der Texteditor................................................................... 4
2.2. Installation von Anaconda ................................................ 6
3. Programmierung - die wichtigsten Bausteine .......................... 9
3.1. Kommentare ..................................................................... 9
3.2. Docstrings ......................................................................... 9
3.3. Anweisungen .................................................................. 10
3.4. Konsolenausgabe mit print() .......................................... 11
3.5. Variablen......................................................................... 13
3.6. Datentypen ..................................................................... 16
3.7. Benutzereingabe mit input() .......................................... 19
3.8. Runden mit round........................................................... 20
3.9. Datentypumwandlung .................................................... 21
3.10. Operatoren ..................................................................... 22
3.11. Funktionen ...................................................................... 25
4. Datenspeicher und Verarbeitung ........................................... 27
4.1. Listen............................................................................... 27
4.2. Listen bearbeiten ............................................................ 31
4.3. Tupel ............................................................................... 34
4.4. Dictionaries ..................................................................... 35
4.5. Schleifen und Bedingungen ............................................ 36
4.6. if-Bedingung.................................................................... 37
4.7. While-Schleife ................................................................. 39
4.8. Die for-Schleife ............................................................... 41
4.9. Abbrechen mit break() ................................................... 43
4.10. Übungsaufgabe – Listen und Dictionaries ...................... 43
4.11. Lösung............................................................................. 44
4.12. Funktionen selbst erstellen ............................................ 46
4.13. Standard-Argumente setzen .......................................... 52
4.14. Funktionen in Modulen auslagern.................................. 54
4.15. Bibliotheken.................................................................... 57
4.16. Übungsaufgabe – Durchschnittnote berechnen ............ 59
4.17. Lösung............................................................................. 60
5. Objektorientieres Programmieren OOP ................................. 63
5.1. Klassen ............................................................................ 63
5.2. Kapselung von Klassen -public, protected, private ........ 67
5.3. Methoden ....................................................................... 70
5.4. Set und Get - Methoden ................................................. 71
5.5. __del__ Methode ........................................................... 72
5.6. Übung – Passwortschutz ................................................ 73
5.7. Lösung............................................................................. 73
5.8. Klassenvariablen ............................................................. 77
5.9. Übung - Durchschnittsgröße........................................... 79
5.10. Lösung............................................................................. 80
5.11. Vererbung ....................................................................... 82
5.12. Klassen auslagern ........................................................... 85
5.13. Übung – Lottospielen ..................................................... 87
5.14. Lösung............................................................................. 89
6. Grafische Oberflächen erzeugen ............................................ 93
6.1. Tkinter – verschiedene Bausteine .................................. 93
6.2. Optische Gestaltung der Fenster .................................. 105
6.3. Der grid-Manager ......................................................... 106
6.4. Place-Manager .............................................................. 108
6.5. Laden von PNG-Dateien ............................................... 109
6.6. Objekte farbig hervorheben ......................................... 111
6.7. Übung-Taschenrechner ................................................ 113
6.8. Lösung ........................................................................... 114
7. Künstliche Intelligenz und neuronale Netze ......................... 119
7.1. Ziel und Nutzen einer KI ............................................... 119
7.2. Aufbau eines neuronalen Netzes ................................. 121
7.3. Wie lernt ein neuronales Netz? .................................... 122
7.4. Datenstromoptimierte Programmierung ..................... 125
7.5. Arrays und numpy ........................................................ 131
Gratis eBook ......................................................................................... 138
1. Vorwort und Einleitung
In den letzten 50 Jahren hat die Menschheit eine Revolution erlebt, wie es in der
bisherigen Geschichte nur selten der Fall war.
Keine andere Entwicklung hatte einen so gigantischen Einfluss auf die Produkti-
vität und das Wohlbefinden der gesamten Weltbevölkerung.
Die Rede ist von der immer noch anhaltenden Digitalisierung. Dank dieses tech-
nischen Fortschritts können wir das Leben führen, wie wir es tun. Wir arbeiten
vor Bildschirmen oder kommunizieren mit Hilfe unseres Smartphones. Gleichzei-
tig stellen unzählige Fabriken voller Roboter und Förderbänder Waren und Güter
her.
Das alles ist nur durch jahrelange Forschung und Entwicklung und dem perfek-
ten Zusammenspiel aus Hardware und Software möglich. Zur Hardware gehö-
ren die Mikroprozessoren, Computer und elektrischen Bausteine, welchen
schließlich durch die angepasste Software, dem Aufspielen des Programms
bzw. des Programmcodes, Leben eingehaucht wird. Beides geht Hand in Hand
und ohne das eine ist das andere wertlos. Die Hardware wird immer erschwing-
licher. Gleichzeitig vervielfacht sich die Rechenleistung der Prozessoren.
Damit steigt auch die Nachfrage an Programmierern für die Maschinen und es
entstehen zahlreiche neue Arbeitsplätze auf diesem Sektor, die allerdings nicht
immer besetzt werden können. Große Firmen wie Bosch, Siemens oder SAP su-
chen seit Jahren permanent nach gut ausgebildeten, hochqualifizierten Infor-
matikern. Auch die namenhaften Autohersteller haben einen akuten Mangel an
Programmierern für ihre Steuereinheiten, Sicherheitssysteme etc.
Da du dieses Buch gekauft hast, scheinst du dich jedoch für genau dieses The-
mengebiet zu interessieren. Und das führt uns zum Kernthema dieses Buches –
die Programmierung in Python.
Python ist aktuell eine der einfachsten Programmiersprachen und wird daher im-
mer beliebter, sowohl im privaten Bereich als auch in der Industrie. Die Program-
mierung in Python ist anfängerfreundlich, anwendungsbasiert, schnell zu erler-
nen und es gibt eine große Community, deren Mitglieder bei Fragen zu bestimm-
ten Themen für einen Support zur Verfügung stehen. Wenn man an einer Stelle
Vielleicht bist du ein Schüler, der sich mit der Programmierung eines Roboters
beschäftigt, ein Elektrotechniker, der mehr über die Software erfahren möchte
oder ein junggebliebener Pensionär, der sich allgemein für Programmierung in-
teressiert.
In jedem Fall wirst du es nicht bereuen, dich mit der Materie auseinanderzuset-
zen.
Gewiss gibt es viele Internetseiten und Bücher, die einen an das Thema Python-
Programmierung heranführen. Diese Bücher sind jedoch teilweise über 500 Sei-
ten stark und für Neueinsteiger vollkommen ungeeignet.
Wenn man sich bereits mit dem Thema etwas auskennt und Anhaltspunkte für
ein spezielles Projekt benötigt, können solche Lehrbücher hilfreich sein, aber für
einen Großteil der Interessenten sind diese weder erforderlich noch effektiv.
Und genau aus dieser Problemstellung heraus ist dieses Buch entstanden.
Es stellt einen Einsteigerratgeber für Interessenten dar, die ohne viel Vorwissen
die Grundkenntnisse der Python-Programmierung erlernen wollen, um
schnellstmöglich das erste eigene Projekt starten zu können.
Dazu werden zunächst folgende Fragen geklärt: Welche Programme und Biblio-
theken brauche ich? Wie programmiere ich meine eigenen Funktionen? Was gibt
es zu beachten? All das wird Schritt für Schritt erarbeitet und mit einem echten
Beispiel-Projekt abgerundet.
Der Name Python ist nicht von der Schlangenart abgeleitet, sondern von einer
britischen Kult-TV-Show Namens Monty Python‘s Flying Circus aus dem Beginn
der 70er Jahre.
Der niederländische Erfinder Guido van Rossum war ein großer Fan der Show.
Das spiegelt sich auch in vielen seiner Dokumentationen und Lernmaterialen zur
Programmiersprache wider, welche mit Zitaten aus der TV-Show versehen sind.
Dieses Buch ist für jeden geeignet, der eine Grundbegeisterung für IT und Pro-
grammierung mitbringt. Die Grundkenntnisse der Programmierung wie Syntax,
Ablauf eines Programms etc. sind wichtig und werden deshalb in den ersten Ka-
piteln aufgeführt.
Zur besseren Struktur sind im Buch an bestimmten Stellen immer wieder fol-
gende Icons zu finden:
Jetzt wünsche ich dir viel Spaß beim Lesen und Eintauchen in die Python-Pro-
grammierung.
Seit 2020 wird Python 2 nicht mehr weiterentwickelt bzw. unterstützt, weshalb
es für Neueinsteiger eindeutig die bessere Wahl ist, direkt mit Python 3 einzu-
steigen. Diese Version hat vor allem die Vorteile, dass es vollständig in Unicode
codiert. Das bedeutet, dass Sonderzeichen und Umlaute korrekt dargestellt wer-
den. Wir werden sehen, dass bei den Beispielen später immer wieder Umlaute
wie Ö, Ä, Ü vorkommen, ohne dass diese umgeschrieben werden müssen. Alles
in allem ist Python 3 die Zukunft. Große Unternehmen wie Instagram und Face-
book stellen gerade von Python 2 auf Python 3 um.
Um mit dem Programmieren starten zu können, müssen wir erst einmal einige
Software auf unserem Rechner installieren. Als erstes müssen wir die Pro-
gramme herunterladen, welche für die Python-Programmierung benötigt wer-
den. Dazu zählen ein Texteditor und ein Interpreter. Was genau ein Interpreter
ist, wird später noch genauer erklärt. Zunächst kümmern wir uns um den pas-
senden Texteditor.
Ein Programm (Quellcode) lässt sich zunächst einfach als ein mehrzeiliger Text
beschreiben.
Zum Schreiben eines Programms in Python können wir also jeden beliebigen
Texteditor benutzen.
Der Standard-Windows-Editor (engl. „Notepad“) ist schon deutlich mehr auf Pro-
grammierung ausgerichtet, unterstützt jedoch viele, für die Programmierung
wichtige Funktionen nicht. Linux Benutzer haben mit dem gEdit bereits einen
umfangreichen Editor mit an Bord. Für Windows Benutzer, welche die meisten
von uns sein werden, empfiehlt sich hingegen das Tool NotepadPlusPlus (Note-
pad++). Das Programm ist für verschiedene Programmiersprachen geeignet. Sig-
nalwörter werden farbig hervorgehoben und einige Fehlermeldungen automa-
tisch erkannt. Der Nachteil dabei ist, dass man das Programm nicht direkt aus-
führen kann. Vor allem für Einsteiger ist eine schnelle ready-to-go Lösung rat-
sam.
Im Rahmen dieses Buches verwenden wir den Editor Anaconda. Dabei handelt
es sich um ein Open-Source-Projekt für die Programmiersprachen Python und R.
Anaconda wird auch an Schulen und Universitäten eingesetzt, da es besonders
anfängerfreundlich ist.
Ein Interpreter übernimmt, meist zusammen mit einem Compiler, die „Überset-
zung“ und Interpretation des Programmcodes. Die Arbeitsweise ist dabei kom-
plex und wird deshalb vereinfacht dargestellt. Im Grunde benötigt eine Program-
miersprache einen passenden, an sie angepassten Interpreter.
In unserem Fall nutzen wir daher IPython, welcher direkt mit Anaconda installiert
wird.
Bevor wir zum ersten Programm kommen, müssen wir das Paket, das eine grafi-
sche Benutzeroberfläche und den Interpreter enthält, zunächst einmal downloa-
den. Das Tool wird von diversen Drittanbietern zur Verfügung gestellt, es emp-
fiehlt sich jedoch auch hier, Anaconda von der offiziellen Webseite herunterzu-
laden.
Hierfür können wir die für unser Betriebssystem passende Version auswählen.
Da Windows-Systeme am meisten verbreitet sind, wird die Installation anhand
von Windows gezeigt. Auf den anderen Plattformen ist die Vorgehensweise ana-
log.
Spyder ist jedoch auch und vor allem für Einsteiger geeignet. Schlüsselwörter
werden automatisch erkannt und farbig dargestellt. Damit heben sich verschie-
dene Programmierelemente wie Variablen, Kommentare, Funktionen oder Klas-
sen voneinander ab. Was genau unter diesen Begriffen zu verstehen ist, wird in
den nächsten Kapiteln erklärt.
Normale Variablen und Befehle sind weiß hinterlegt. Kommentare werden auto-
matisch ausgegraut und Signalwörter werden eingefärbt.
Zusätzliche In
Bilder, Grafiken etc.
Programmcode
Konsole
Benutzer Ein- und Ausgabe
Vor Start sollte man das Programm in einem beliebigen Ordner abspei-
chern und einen sinnvollen Namen vergeben. Die Endung einer Python
Datei ist dabei immer .py
Bevor es an die konkrete Codeerstellung geht, wird der Aufbau eines Python-
Programms erklärt.
Spezieller werden die Bausteine wie das Benutzen von Kommentaren, Klammern
oder Einrücken anhand von Python beschrieben. Die Prinzipien lassen sich auch
auf andere Programmiersprachen wie Java, C, C# und weitere übertragen. Py-
thon hat jedoch den entscheidenden Vorteil, dass der Fokus auf Übersichtlich-
keit und Einfachheit gelegt wurde. Beispielsweise gibt es, anders als in anderen
Programmiersprachen, nur selten Klammern oder Semikolons.
3.1. Kommentare
Kommentare dienen der Übersichtlichkeit und Struktur eines Programms. Wenn
wir ein Programm verfassen und es anschließend jahrelang nicht mehr verwen-
den, werden wir später sehr lange brauchen, um die Funktionen wieder nachzu-
vollziehen.
Deshalb sind Kommentare für das schnelle Verständnis der Funktion eines Pro-
gramms enorm wichtig.
Es gibt keine feste Regel, wann wir einen Kommentar setzen sollten. Bei der Ent-
scheidungshilfe gilt der Spruch: „Lieber einen Kommentar zu viel als zu wenig“.
Andere Programmierer, welche unseren Code verstehen wollen, und auch wir
selbst werden später für jeden Kommentar dankbar sein.
3.2. Docstrings
Für eine bessere Übersichtlichkeit empfiehlt es sich, zusätzlich zu den Kommen-
taren, eine Beschreibung des Programms anzugeben. Diese Beschreibungen
werden als Docstring bezeichnet und machen es dem Programmierer leichter,
die Hintergründe und Funktionsweise des Programms zu verstehen. Docstrings
Vor allem, wenn mehrere Leute an einem Projekt arbeiten oder meh-
rere Personen denselben Code verstehen sollen, sind Kommentare und
Docstrings unumgänglich.
Erstellt: 12.12.2021
Projektstand: 01.01.2022
’’’
Wie im obigen Beispiel zu sehen, wird die Kommentarsektion des Docstrings mit
drei einfachen ‘‘‘ oder drei doppelten Anführungszeichen “‘‘‘ geöffnet und ge-
schlossen. Die Funktion ist genau dieselbe.
“““ Alles innerhalb der Anführungszeichen wird als Überschrift/Beschreibung inter-
pretiert. “““
Jetzt wissen wir wie wichtig es ist, ein Programm ausreichend zu dokumentieren
und wie wir die Kommentare und Docstrings setzen. Als nächstes geht es an die
konkrete Programmierung Mittels Anweisungen.
3.3. Anweisungen
Anweisungen (engl. instructions) bilden den Kern eines Programms. „Anwei-
sung“ ist ein Überbegriff für beispielsweise Rechenoperationen oder Ein- oder
Ausgabebefehle an der Konsole. Auch das Definieren von Variablen, das Aufru-
fen von Funktionen oder das Abbrechen einer Schleife ist eine Anweisung. Bei
Anweisungen empfiehlt es sich, wieder einen Kommentar anzuhängen.
Als erste, einfach verständliche Anweisung wird der Aufruf der print()
Funktion eingeführt.
Mit dem Befehl print() können Wörter und Zahlen an der Konsole ausgegeben
werden, ebenso wie der Inhalt von Variablen, Listen oder ganzen Datensätzen,
welche im folgenden Kapitel behandelt werden.
Im ersten Beispiel übergeben wir der Funktion einen Text, der dem Benutzer an-
gezeigt werden soll. Diesen Text setzen wir bei der print()-Funktion zwischen die
runden Klammern.
Der auszugebende Text wird innerhalb der Klammern in einfachen oder doppel-
ten Anführungszeichen gesetzt.
print(“Hallo Welt“) #gibt Hallo Welt in der Konsole aus
Nicht vergessen, damit das Programm startet, muss es über die Schalt-
fläche mit dem grünen Pfeil ausgeführt werden.
Praktisch ist dabei, dass nach einem print()-Befehl automatisch ein Umbruch in
der Konsole eingefügt wird.
Zur Darstellung der Ausgabe stehen uns verschiedene Möglichkeiten zur Verfü-
gung.
Für ein geordnetes Erscheinungsbild können bei der Ausgabe der Daten über ei-
nen leeren print()-Befehl zusätzlich Absätze und Leerzeilen eingefügt werden.
print() #Leerzeile
Ein Zeilenumbruch kann durch die Zeichenfolge \n realisiert werden, eine Einrü-
ckung (Tabulator) mit der Zeichenfolge \t .
print('Absatz folgt\n') #Absatz
print('Leerzeile folgt')
print() #Leerzeile
Alternativ kann ein print()-Befehl auch über mehrere Zeilen ausgegeben werden.
Dafür werden drei Anführungszeichen am Anfang und am Ende des Textes be-
nötigt, genau wie bei einem Docstring.
wird
in 4 Zeilen
ausgegeben''')
Nachdem wir gelernt haben, wie man einfachen Text oder Zahlen mittels der
print()-Funktion ausgibt, beschäftigen wir uns als nächstes mit dem Speichern
von Daten in Variablen.
3.5. Variablen
Variablen sind unverzichtbar für nahezu jedes Python-Programm. Dabei handelt
es sich um Zahlen, Zeichen oder ganze Texte, die während der Laufzeit eines Pro-
gramms verändert werden können. Sie dienen zur Speicherung von Werten.
Durch Nennen der Variablen können wir im Verlauf des Programms den Wert
wieder abrufen, beispielsweise um diesen in einer Rechnung einzusetzen.
Eine Variable besteht aus einem Namen und einem Wert. Wir können uns die
Variable wie eine Box vorstellen, auf der der Name der Variablen geschrieben
ist. Der Inhalt ist dabei der Wert der Variablen. Dieses Verständnis wird später
noch von Bedeutung sein.
Zum Anlegen einer Variablen schreiben wir lediglich den Namen der ge-
wünschten Variablen und weisen ihr mit dem Gleichheitszeichen (Zu-
weisungsoperator) direkt einen Wert zu.
Der Name der Variablen kann bei der Erstellung beliebig gewählt werden und
Buchstaben, Ziffern und Unterstriche enthalten. Allerdings nicht mit einer Ziffer
begonnen werden.
variable_test_1 = 4
4
variable_test_1
Abbildung 10 Variablen-Box-Modell
Die Benennung der Variablen sollte sinnvoll und kurz sein. Bei mehreren
ähnlichen Variablen empfiehlt es sich, diese durch den Namen oder an-
hand von Indizes zu unterscheiden. Eine Variable, in der beispielsweise
ein Temperaturwert gespeichert wird, könnte demnach temp1 heißen.
temp1 = 20
temp2 = 30
Der Variablen temp1 (beispielsweise in einem Innenraum) wird der Wert 20 zu-
geordnet. Der Variablen temp2 (beispielsweise im Außenbereich) entsprechend
der Wert 30.
Die Variablen müssen eindeutige Namen erhalten, ein Name darf nicht
mehrmals vergeben werden. In Python wird zusätzlich in Groß- und
Kleinschreibung unterschieden. Temp1, TEMP1 und temp1 werden als
drei verschiedene Variablen interpretiert.
Wenn wir Wörter oder Sätze in einer Variablen speichern wollen, müssen wir
immer Anführungszeichen setzen. Dabei können wir einfache oder doppelte An-
führungszeichen verwenden. Die Funktion ist die gleiche.
name = ‘Tom‘
name = “Tom“
Der Wert einer Variablen kann ebenfalls mit dem print() Befehl ausgegeben wer-
den.
print(temp1)
Bei der Ausgabe von Variablen über die print()-Funktion gibt es hinsichtlich der
Syntax einiges zu beachten.
Möchte man den Inhalt einer Variablen ausgeben, werden keine Anfüh-
rungszeichen geschrieben. D.h. ohne Anführungszeichen wird von dem
Befehl print() eine Variable erwartet, die definiert sein muss.
Der letzte Aufruf gibt einen Error aus, weil keine Anführungszeichen ge-
setzt sind. Die Funktion fordert an dieser Stelle eine Variable. Die Vari-
able Tom ist jedoch nicht bekannt. Tom ist lediglich der Inhalt der Vari-
ablen name. Das ist ein wichtiger Unterschied.
Die print()-Funktion kann auch eine Kombination aus Text und Variablen anzei-
gen. Dafür müssen nicht mehrere Befehle aufgeführt werden.
Wollen wir beispielsweise die Temperatur inklusive der Einheit °C angeben, kön-
nen wir beides in einen print()-Befehl packen. Die Syntax dabei ist:
print(“TEXT“,VARIABLE,“TEXT“)
print('Temperatur: ',temp1,'°C')
Der Text wird einfach über das Setzen in Anführungszeichen der Variablen hin-
zugefügt.
Was passiert jedoch, wenn wir ein Anführungszeichen speichern oder ausgeben
möchten?
print(variable)
Jetzt wissen wir, wie wir Zahlen oder Worte in Variablen speichern und diese
über die Konsole ausgeben können. Damit haben wir bereits viel gewonnen. Im
nächsten Kapitel beschäftigen wir uns mit Datentypen von Variablen und deren
Einteilung.
3.6. Datentypen
In jeder Programmiersprache gibt es verschiedene Variablentypen, die sich hin-
sichtlich ihrer Größe (Speicherplatzbedarf) oder dem Inhalt unterscheiden.
Man spricht dabei von Datentypen. Verschiedene Daten werden nach ihrer Art
und ihrer Funktion eingeteilt. Eine Zahl hat dabei beispielsweise einen anderen
Typ als ein Wort. Doch wozu braucht man diese Unterscheidung überhaupt?
Neben dem Haushalten mit Speichereinheiten gibt es noch weitere Gründe, wa-
rum es sinnvoll ist, Daten in verschiedenen Typen abzuspeichern.
Ganze Zahlen werden als Integer, kurz int, abgespeichert. Der Interpre-
ter weiß: Mit Integer-Variablen kann man rechnen.
Der Datentyp für Wörter heißt string. Mit ihm kann man nicht so ein-
fach rechnen wir mit Integer-Variablen.
Man könnte den Ausdruck als „Hallo Welt“ interpretieren, eine mathematische
Grundlage gibt es dafür nicht. Noch deutlicher wird es bei einem Vergleich.
„Hallo“ < „Welt“ # Was ergibt das?
Dies verdeutlicht, dass man arithmetische oder logische Operatoren nicht auf
string-Variablen anwenden kann.
Das Verständnis der Unterschiede ist für spätere Kapitel noch essenziell.
Neben den beiden Datentypen string und int gibt noch weitere. In der folgenden
Tabelle sind die wichtigsten Variablentypen mit ihren Eigenschaften aufgelistet.
Darüber hinaus gibt es unzählige weitere Variablentypen, die für Neueinsteiger
aber nur eine geringe bis überhaupt keine Rolle spielen.
Nicht so bei Python. Der Vorteil von Python liegt vor allem in der einfachen Zu-
ordnung von Datentypen. Python erkennt anhand der Variablen selbst, welcher
Datentyp verwendet werden soll. Durch den Inhalt bzw. die Schreibweise des
Inhalts wird automatisch ein Datentyp zugewiesen, ohne dass dieser separat an-
geben werden muss.
x=5 # Variable wird als Ganzzahl (integer) abgespeichert
Datentypen sind nicht starr. Das heißt, sie können auch innerhalb des
Programms verändert werden.
Python passt auch hier bei Bedarf den Datentyp an. Wird eine ganze Zahl (int)
mit einer Gleitkommazahl (float) verrechnet, wird dem Ergebnis automatisch
auch eine Gleitkommazahl (float)zugewiesen.
i = 52 # Der Datentyp wird automatisch zu Integer gesetzt
Bei Spyder kann man sich die Variablen und deren Inhalt sowie den Da-
tentyp anzeigen lassen. Das ist vor allem bei der Suche nach Fehlern
sehr hilfreich. Unter dem Punkt Variable Explorer im oberen, rechten
Feld werden der Variablenname, der Datentyp sowie Länge und Inhalt
der Variablen angezeigt.
Die Funktion input() erfüllt genau diesen Zweck. Sie ist hilfreich, um den
Benutzer des Programms während der Laufzeit miteinzubeziehen.
Der Funktion kann man zusätzlich eine Aufforderung als Argument übergeben.
input(“Bitte geben Sie eine Zahl zwischen 0 und 10 ein“)
Sobald das Programm die Funktion ausführt, wird die Aufforderung in der Kon-
sole ausgegeben und es verlangt nach einer Benutzereingabe. Die Benutzerein-
gabe erfolgt ebenfalls über die Konsole. Es können eine Zahl, ein Wort oder sogar
Die Funktion input() speichert die Dateneingabe als Zeichenkette ab. Für Wörter
oder Sätze ist das korrekt und kann so übernommen werden.
Die Funktion eval() speichert die eingelesenen Daten unter dem richti-
gen Datentyp ab. Denn wir erinnern uns, dass man mit string-Variablen
nicht rechnen kann.
Jetzt wird es etwas komplizierter: Wir übergeben der Funktion eval() die kom-
plette Funktion input() als Argument. Wir schachteln die Funktionen ineinander.
Möchten wir einen eingegeben Wert in einer Variablen mit dem passenden Da-
tentyp speichern, lautet der vollständige Befehl:
x= eval(input(“Bitte geben Sie eine Zahl zwischen 0 und 10 ein“))
Damit wird die Aufforderung ausgeben, anschließend die Zahl eingelesen und in
den passenden Datentyp (integer) umgewandelt und in die Variable x gespei-
chert.
print(y)
Es gibt noch viele weitere Funktionen, von denen wir auch noch weitere ken-
nenlernen und sogar selbst verfassen werden. Davor sehen wir uns jedoch
noch einmal genauer an, wie man Daten effektiv speichern und verarbeiten
kann.
3.9. Datentypumwandlung
Wir haben bereits verschiedene Datentypen kennengelernt und wie Python
diese verarbeitet. Meistens wird automatisch der richtige Datentyp angelegt.
Wir haben aber auch schon ein Beispiel gesehen, bei dem das nicht der Fall ist.
Die input()-Funktion liefert nicht immer den Datentyp, den wir uns wünschen.
Als Lösung haben wir die eval()-Funktion verwendet, welche die Eingabe evalu-
iert und den richtigen Datentyp zuordnet.
Außerdem ist die Auswertung des eingegebenen Ausdrucks mit der eval()-Funk-
tion teilweise sogar gefährlich. Ein Bediener kann einen Ausdruck eingeben, des-
sen Auswertung durch die Funktion Schäden auf dem Rechner, auf dem das Pro-
gramm läuft, verursacht. In der Praxis wird eval() nur eingesetzt, wenn das Pro-
gramm von niemand anders als dem Programmierer bedient wird.
Als Alternative können wir die Datentypen auch vorgeben, indem wir den Daten-
typ vor den auszuführenden Befehl schreiben. Wollen wir eine Eingabe als Inte-
ger-Zahl abspeichern, schreiben wir:
x= int(input("geben sie eine Zahl ein"))
print(x)
print(y)
print(z)
Die zweite und dritte Ausgabe ist identisch, jedoch ist einmal der Datentyp float
ausgegeben worden und einmal eine Zeichenkette. Das zeigt auch der Variablen-
Manager in Spyder.
3.10. Operatoren
Wir haben bereits Variablen und Datentypen kennengelernt und können die ab-
gespeicherten Werte nicht nur mit der print()-Funktion ausgeben, sondern auch
mit ihnen rechnen oder verschiedene Variablen miteinander vergleichen.
Die Operatoren wie plus, minus, mal und geteilt und weitere werden
arithmetische Operatoren genannt.
= Zuweisung x=3
+ Addition x=y+2
- Subtraktion x=y-2
* Multiplikation x=y*2
/ Division x=y/2
Auf die Frage: „Ist der Inhalt der Variable x größer als die Zahl fünf?“ gibt es nur
zwei Antwortmöglichkeiten. Entweder stimmt die (Un-)Gleichung und ist damit
wahr (True) oder sie stimmt nicht und ist damit falsch (False).
Vergleichsoperatoren
Operator Bedeutung Beispiel Ergebnis
x==5 # Es wird geprüft, ob x den Wert 5 enthält. Das Ergebnis ist True oder False
Der Befehl print(3<4) gibt als Ergebnis „True“ also „wahr“ aus.
Warum sind hier keine Anführungszeichen gesetzt? Was würde die Kon-
sole ausgeben, wenn man diese einfügt?
Lösung: Wenn Anführungszeichen eingesetzt werden, wird der Text und nicht das
Ergebnis der Operation ausgegeben. In dem Fall print(“3<4“) würde 3<4 ausge-
geben.
Als letzten Unterpunkt schauen wir uns die logischen Operatoren an. Logische
Operatoren interpretieren jeden Zahlenwert und jede Variable als wahr oder
falsch, ähnlich wie bei den Vergleichsoperatoren. Dabei wird jeder Wert außer
der Null als True interpretiert. Lediglich die Null wird als False angenommen. Lo-
gische Operatoren werden meist mit Bedingungen kombiniert.
Die Besonderheit bei den logischen Operatoren ist, dass der Operator selbst kein
Zeichen, sondern ein Wort ist.
Logische Operatoren
Operator Bedeutung Beispiel Funktion
x=6;y=0 x ist „True“, y ist „False“. „not y“ ist daher „True“. Dem-
z = x and not y nach ist die Variable z auch „True“
Hiermit haben wir einen Überblick zu den wichtigsten Bauteilen beim Rechnen
mit Variablen erhalten. Operatoren und Variablen sind Grundbausteine eines je-
den Programms und werden in vielfachen Kombinationen und Möglichkeiten
eingesetzt. Um die Operatoren und Variablen sinnvoll verwenden zu können,
schauen wir uns im nächsten Unterkapitel die Wirkungsweise von Funktionen in
Python an.
3.11. Funktionen
Funktionen wurden teilweise bereits eingeführt, beispielsweise die print()-Funk-
tion, welche Daten an der Konsole ausgibt. Den meisten sind Funktionen noch
aus dem Schulunterricht in Erinnerung geblieben: 𝑦 = 2 · 𝑥 + 1 ist ein Beispiel
einer Funktion.
Bei der Programmierung beschränkt sich eine Funktion jedoch nicht nur
auf Zahlen als Ein- oder Ausgabewerte.
Beispielsweise kann man einer Funktion einen Buchstaben oder ein ganzes Wort
anstelle einer Zahl übergeben. Der übergebene Wert wird als Argument bezeich-
net.
Eine Funktion wird über den Namen, gefolgt von zwei runden Klam-
mern, aufgerufen. Die Klammern enthalten die geforderten Argumente
der Funktion.
Der Funktion print() kann man Variablen, Terme oder Sätze übergeben.
Funktion print()
Abbildung 17 Funktionsaufruf
Die print()-Funktion ist nur ein Beispiel einer Funktion, als nächstes schauen wir
uns weitere, sehr nützliche Funktionen an.
Dabei handelt es sich, wie der Name schon sagt, um eine Liste, also eine Anei-
nanderreihung von Wörtern oder Zahlen, die zusammen in einer einzigen Vari-
ablen gespeichert werden.
Das Anlegen einer Liste erfolgt analog zum Anlegen einer Variablen, mit dem Un-
terschied, dass bei Beginn und am Ende der Liste eckige Klammern stehen.
Dadurch weiß der Interpreter, dass es sich um eine Liste handelt.
Die Elemente der Liste werden durch Kommata getrennt. Bei Wörtern
(strings) dürfen wiederum die Anführungszeichen nicht vergessen wer-
den.
datensatz = [ “Tom“, 26, 1.84]
Das Beispiel legt eine Liste mit den drei Elementen an und speichert die Liste in
die Variable datensatz. Die Variable besitzt jetzt den Datentyp liste. Tom steht
dabei für den Namen, 26 für das Alter und 1.84 für die Größe.
Normalerweise hätten wir drei gesonderte Variablen anlegen müssen. Der Vor-
teil von Listen liegt also auf der Hand.
Anhand des Beispiels können wir auch noch weitere Eigenschaften ableiten.
Wie man schnell sieht, kann eine Liste verschiedene Datentypen, hier
string/str, int und float enthalten. Jedes Element der Liste erhält dabei
automatisch einen Index, beginnend bei Null.
Möchte man einzelne Elemente einer Liste abfragen, muss der Index in Klam-
mern geschrieben werden.
Wie können wir den Index -1 und -2 interpretieren? Es gibt doch kein negatives
Listenelement, oder?
Nun, die Listen können schnell viele hunderte Elemente besitzen oder es können
ständig neue Elemente angehängt werden.
Möchten wir auf die letzten Elemente zugreifen, können wir den letzten Index
eingeben. Manchmal ist der Index jedoch nicht bekannt oder er ist sehr groß.
Deshalb kann man in Python mit negativen Indexen die zuletzt angefügten Ele-
mente auswählen.
liste = [0,1,….,999999999]
liste[999999999]# funktioniert
Obwohl Listen oftmals Wörter oder Sätze enthalten, kann man sie trotzdem ad-
dieren, multiplizieren oder verschachteln. Bei der Addition von Listen gilt folgen-
des zu beachten:
Wird ein einzelnes Element oder eine Liste zu einer anderen Liste ad-
diert, werden lediglich die einzelnen Elemente an das Ende der beste-
henden Liste gehängt.
datensatz1 = [ “Tom“, 26,1.84]
datensatz2 = [“Lisa“,28,1.67]
print(datensatz3)
print(datensatz3)
Bei der Multiplikation mit einer Zahl n wird die bestehende Liste n-mal
dupliziert und angehängt. Beispiel für n=3:
datensatz3 = datensatz1*3
print(datensatz3)
Mehrdimensionale Listen
Neben Wörtern und Variablen können die Elemente einer Liste selbst Listen sein.
Diese Listen können wiederum Listen als Elemente enthalten und so weiter und
so weiter.
Ruft man einzelne Werte der Liste ab, wird wie gewohnt das Element
ausgegeben. Diesmal ist das Element eine ganze Liste, sodass auch die
ganze Liste ausgegeben wird.
print(datensatz4[1])
Möchte man ein Element einer Unterliste, beispielsweise Kevin abfragen, wird
zunächst der Index der Unterliste und anschließend der Index des Elements an-
gegeben.
In dem Beispiel ist das Element Kevin in der dritten Unterliste (Index 2) und in
der Liste wiederum das erste Element (Index 0).
print(datensatz4[2][0])
Kevin
Als nächstes lernen wir weitere Methoden kennen, um eine Liste zu erstellen
oder zu bearbeiten.
Die Befehle sind nicht essenziell notwendig und wir können die gleiche Liste auch
händisch erstellen, jedoch sparen wir uns jede Menge Zeit, wenn wir die richtige
Abkürzung kennen.
Die Funktion range(x) erstellt eine Liste mit den Werten Null bis x. Der
Befehl
liste = range(10)
Abbildung 19 Variablen-Explorer
Alternativ können der range()-Funktion auch der Start und Endwert angegeben
werden.
Dabei wird der Endwert nicht miterzeugt!
liste = range(3,7)
Gibt die Werte [3,4,5,6] an die Liste weiter. Ohne die Sieben.
Die Funktion range() wird vor allem im nächsten Kapitel (Schleifen und Bedin-
gungen) noch von Bedeutung sein.
Methoden sind spezielle Funktionen, die nicht für alle Daten verwendet werden
können. Der genaue Unterschied wird im Kapitel Klassen erläutert, da dies für
das jetzige Verständnis und die Anwendung nicht erforderlich ist.
Mit dem Befehl del zum Löschen einer Liste wurde bereits eine Methode einge-
führt, jedoch nicht als solche gekennzeichnet.
Darüber hinaus gibt es viele weitere Methoden zur Bearbeitung einer Liste. Dazu
ist es wichtig, die Methodennamen zu kennen.
Um ein weiteres Element an das Ende einer Liste hinzuzufügen, ist das
mit dem Befehl append() möglich.
liste.append(‚Element‘)
Der Name der Liste wird gefolgt von einem Punkt und dem Methodennamen
aufgerufen.
Das Element, welches der Methode übergeben wird, wird an das Ende der Liste
„liste“ angehängt:
datensatz1 = ['Tom', 26,1.84]
datensatz1.append('Fußball')
Das vierte Element im Beispiel ist Fußball und wird zur Liste „datensatz1“ hinzu-
gefügt.
Darüber hinaus existieren noch weitere Methoden für die Verwendung mit dem
Datentyp Liste.
Beispielsweise können einzelne Elemente gesucht oder gelöscht werden. Für das
Suchen eines Elements wird der Befehl index() verwendet.
listenname.index(‘Element‘)
Der Methode wird ein Element, beispielsweise ein Wort, übergeben. Es wird an-
schließend die Liste durchsucht und der Index des passenden Elements als Rück-
gabewert der Methode index() dann ausgegeben.
print(datensatz1.index('Tom'))
gibt den Wert 0 an der Konsole aus, da Tom das Element mit dem Index Null ist.
.count() Gibt die Anzahl von vorhandenen Einträgen innerhalb der Liste zu-
rück
.extend() Hängt alle Elemente einer zweiten Liste an.
liste1=list(range(10))
liste1.index(11)
liste1.remove(5)
.sort() Sortiert die Liste den Werten nach, entweder aufsteigend (Zahlen)
oder alphabetisch (strings).
reverse() Spiegelt alle Werte einer Liste, der letzte Wert wird zum ersten, und
umgekehrt.
Weiterhin gibt es Operatoren, die auf Listen angewendet werden können. Wir
können diese Operatoren vergleichen mit den +,-* und / Operatoren, welche wir
auf Zahlen anwenden können.
Die nachfolgende Tabelle zeigt die Aufrufe und Funktion der Operatoren
4.3. Tupel
Listen enthalten stets variable Daten, was das Arbeiten mit ihnen sehr angenehm
macht, jedoch belegen diese variablen Daten auch zusätzlichen Speicherplatz.
Zudem muss immer mehr Speicherplatz freigehalten werden als zunächst benö-
tigt, falls sich die Variable ändert und größer wird.
Wenn wir jedoch nur unveränderliche Werte haben, verwenden wir anstatt den
Listen sogenannte Tupel. Tupel verhalten sich sehr ähnlich zu Listen. Jedoch kön-
nen die Werte der Elemente nicht verändert werden. Um ein Tupel zu erstellen,
werden die eckigen Klammern der Liste weggelassen. Die Kommata trennen wei-
terhin die Elemente voneinander.
tupel = “Tom“, 26, 1.84
Die Elemente können wie bei Listen durch Nennen des Index abgerufen
werden.
print(tupel[0]) # gibt Tom aus.
Möchte man beispielsweise ein Element mit dem del-Befehl löschen, wird ein
Error ausgegeben, dass die Tupel diesen Befehl nicht unterstützen.
del tupel[2]
Allerdings lassen sich weitere Elemente hinzufügen. Dazu wird, wie bei Listen,
das Pluszeichen verwendet.
Zu beachten ist jedoch, dass zu einem Tupel keine Liste oder Wörter, sondern
lediglich eine anderes Tupel addiert werden kann.
tupel1 ='Tom', 26, 1.84
tupel3 = tupel1+tupel2
Wie immer kommt es auf den konkreten Anwendungsfall an, ob Listen oder
Tupel zu bevorzugen sind. Das bringt uns auch zur dritten, sehr ähnlichen Art der
Datenspeicherung, den Dictionaries. Diese sind auch für gewisse Anwendungs-
bereiche extrem nützlich.
4.4. Dictionaries
Nachdem die Handhabung von Listen und Tupeln erläutert wurde, wird nachfol-
gend eine weitere, sehr ähnliche Variante zur Datenstrukturierung behandelt;
die Dictionaries.
Listen sind uns mittlerweile vertraut. Der große Nachteil von Listen ist, dass der
Benutzer wissen muss, wofür welcher Index steht.
Im Beispiel unseres Datensatzes von Tom wurde festgelegt, dass der Index 0 für
den Namen steht, Index 1 für das Alter und Index 2 für die Größe.
datensatz1 = ['Tom',26,1.84]
Es wäre deutlich geschickter, wenn man statt eines Index ein Suchbegriff ange-
ben könnte. Beispielsweise anstatt des Index „Null“ den Suchbegriff name
Als Beispiel legen wir wieder die gleiche Personendatei an. Die keys und values
werden in geschweifte Klammern geschrieben und mittels eines Doppelpunktes
einander zugeordnet. Die Wertepaare werden mit Kommata getrennt.
person1= {'Name':'Tom','Alter':'26','Größe':'1,84'}
Anstatt (wie bei Listen) den Index anzugeben, kann der gewünschte
Wert über den Schlüssel abgerufen werden.
print(person1['Name'])
print(person1['Alter'])
Die Verwendung der Dictionaries bietet sich aufgrund des logischen Zusammen-
hangs zwischen den keys und den values an.
Auch gibt es viele Hilfsfunktionen für Dictionaries. Man kann, wie bei Listen, be-
stimmte Elemente löschen, anhängen oder einfügen.
4.6. if-Bedingung
Die „Wenn-dann“ - Anweisung wird nur ausgeführt, wenn eine Bedingung
erfüllt ist. Die Bedingung wird nach dem Signalwort „if“ angeführt. Das
Wort „dann“ wird sozusagen durch einen Doppelpunkt ersetzt.
if x > 4:
Wichtig zu verstehen ist, dass die Bedingung „auf Wahrheit“ geprüft wird. Wer
selbst merkt, dass er hierbei noch Verständnisprobleme beim Interpretieren von
„True/False“ Aussagen hat, sollte nocheinmal die Operator-Tabelle aus dem Ka-
pitel Operatoren anschauen.
print(“Die Zahl ist größer als 4“) print(“Die Zahl ist größer als 4“)
Ist die Bedingung nicht erfüllt, wird die if-Anweisung übersprungen und
das Programm wird nach dem eingerückten Text fortgesetzt.
Möchten wir nicht nur zwei, sondern mehrere Bedingungen abfragen, funktio-
niert das mit der Erweiterung elif (Abkürzung für else-if). Dabei können wir be-
liebig viele elif-Szenarien einfügen, jedoch immer nur ein if- und ein else-Szena-
rio.
Die if-Bedingung kann auch in Verbindung mit einem String eingesetzt werden.
x='hallo'
if x == 'hallo':
print(" Hallo Welt") # wenn die Var. x die Zeichenkette „Hallo“ enthält
else:
print("Tschüss")
Die if-Bedingung benötigt zur Ausführung eine wahre Aussage. Das kön-
nen wir, wie im obigen Beispiel, durch eine Abfrage realisieren. Alterna-
tiv reicht eine Variable, welche bereits einen booleschen Wert
(True/False) besitzt.
x = True
if x:
else:
Im Beispiel ist x auf “True“ gesetzt, daher wird „x ist wahr“ ausgegeben.
if x:
„x ist wahr“
Prüfe selbst: Wann ist die if-Bedingung erfüllt und wann nicht?
If 3 > 5 :
if 3 < 5 :
if 3 :
if 0 :
if not 3 :
if 2==2 :
Lösung:
1. Nicht erfüllt. Da 3 kleiner als 5 ist, wird das if-Statement nicht ausgeführt.
3. Erfüllt. 3 ist eine Zahl ungleich Null, daher wird sie als „wahr“ interpretiert und
das if-Statement wird ausgeführt.
4. Nicht erfüllt. Die Zahl Null wird als „falsch“ interpretiert und das if-Statement
wird nicht ausgeführt.
5. Nicht erfüllt. Die Zahl drei wird als wahr interpretiert, jedoch negiert, daher wird
das if-Statement nicht ausgeführt.
Achtung, hier muss „==“ zur Prüfung einer wahren Aussage verwen-
det werden. Der Operator „=“ ist eine Zuweisung, keine Prüfung. If
2=2 würde ein Error (invalid syntax) ergeben. Ein häufiger Fehler!
7. Nicht erfüllt. Da sowohl 4 größer als 2 und 3 kleiner als 1 sein müssten, wird das
if-Statement nicht ausgeführt.
4.7. While-Schleife
Schleifen werden benötigt, um Rechenoperationen wiederholt auszuführen. Das
kann zeitlich vorgegeben sein, beispielsweise wenn man alle 15 Minuten die
Die Struktur der while-Schleife ist analog zur if-Bedienung. Die while-Schleife
wird durch den Schlüsselbegriff while eingeleitet. Anschließend wird die Bedin-
gung angegeben. Dahinter wird mit einem Doppelpunkt abgeschlossen.
Zunächst ist kein Unterschied zur if-Abfrage zu sehen. Jedoch fragt eine if-Ab-
frage nur ein einziges Mal, ob die Bedienung erfüllt ist.
Eine while-Schleife läuft immer weiter, bis die Bedingung “falsch“ wird.
Die Schleife kann auch unendlich laufen, wenn die Bedingung logisch im-
mer erfüllt wird.
So auch im nachfolgenden Beispiel. Die Variable temp1 wird nicht verändert. Ist
die Variable größer als 20, würde es eine Endlosschleife geben.
Abhilfe lässt sich zum Beispiel dadurch schaffen, indem die Variable innerhalb
der Schleife verändert werden kann.
In diesem Beispiel wird der Benutzer innerhalb der Schleife aufgefordert, eine
neue Temperatur einzugeben. Ist die eingegebene Temperatur 20 °C oder gerin-
ger, wird die Schleife bei der nächsten Abfrage nicht mehr durchlaufen. Oftmals
wird in Verbindung mit einer While-Schleife auch eine Zählvariable verwendet.
Dabei handelt es sich um eine Variable, meist i, ii oder j, welche pro Durchlauf
um Eins erhöht wird. Mit Hilfe der Zählvariablen kann die Anzahl der Durchgänge
erfasst werden und eine Abbruch-Bedinung eingeführt werden, beispielsweise
wenn die Zählvariable über einen bestimmten Wert steigt, wird die Schleife ab-
gebrochen.
i =1 # Zählvariable
print(“Durchlauf Nummer:“,i)
i=i+1
For-Schleifen werden vor allem in Kombination mit Listen und anderen Objek-
ten, welche mehrere Elemente enthalten, verwendet. Dabei wird jedes Element
geprüft. Sobald die for-Schleife keine passenden Elemente mehr finden kann,
Bei der for-Schleife ist das Signalwort for. Anschließend geben wir eine
beliebige Variable an. Danach folgen das Signalwort in sowie die Liste
bzw. die Sequenz von Elementen.
Solange ein Element vorhanden ist, ist die Bedingung erfüllt. Das Ele-
ment der Liste wird in der Variablen x gespeichert. Im anschließenden
Durchlauf wird das nächste Element geprüft. Die Ausgabe sieht insge-
samt aus wie folgt:
print (n)
Diese Liste wird an die for-Schleife übergeben. Die for-Schleife arbeitet die Ele-
mente ab. Deshalb finden insgesamt 10 Durchläufe (0-9) statt.
Oftmals möchten wir eine Schleife jedoch nicht vollständig ausführen, sondern
vorzeitig abbrechen.
Das einfachste Beispiel bildet dabei ein Suchalgorithmus. Dieser durchläuft eine
Liste, bis er das passende Element gefunden hat.
Das Abbrechen einer Schleife, Funktion oder Bedingung kann mit dem
Signalwort break realisiert werden. Sobald dieses innerhalb einer
Schleife auftaucht, wird sie abgebrochen.
automarken = ['VW','Audi','Porsche','BMW','Skoda']
for n in automarken:
Zunächst wird die Liste automarken angelegt und der for-Schleife übergeben.
Diese vergleicht das aktuelle Element der Liste mit der gewünschten Eingabe. Bei
einem Treffer (if n == suche) wird die for-Schleife abgebrochen. Ansonsten läuft
sie immer weiter und gibt alle Elemente der Liste aus.
Alle benötigten Funktionen und Methoden wurden bereits behandelt und kön-
nen bei Bedarf nachgeschlagen werden.
Erste Übungsaufgabe
Der Programmierer soll ein Programm für eine Lagerhalle eines Obstla-
dens erstellen. Für das Beispiel haben wir uns auf lediglich vier Früchte
beschränkt. Das Prinzip bleibt bei 100 Früchten das gleiche. Lediglich
der Programmieraufwand ist höher.
Frucht Bestand
Banane 501
Äpfel 112
Mango 52
Kiwi 96
Zunächst sollen die Bestände abgespeichert werden. Dazu empfiehlt sich eine
Liste oder ein Dictionary. Bei einer Liste realisiere die Abfrage mit input()-Funk-
tion und die Auswahl des Bestands über if- und elif- Anweisungen.
Anschließend soll der Benutzer aufgefordert werden, eine der Früchte einzuge-
ben. Das Programm soll dann den passenden Bestand ausgeben.
4.11. Lösung
Wie bei den meisten Programmieraufgaben gibt es auch hier keine Musterlö-
sung. Jeder Programmierer hat seine Vorlieben. Der eine arbeitet lieber mit Lis-
ten, der andere mit Dictionaries. Der eine Programmierer bevorzugt for-schlei-
fen, ein anderer while-Schleifen.
Daher gibt es, neben dem folgenden Code, viele verschiedene Lösungsmöglich-
keiten für die beschriebene Aufgabe. Wenn das Programm mit dem Ausführen
das gewünschte Ergebnis liefert, ist der Code korrekt.
Bei der Eingabe des Obstes muss die jeweilige Bezeichnung in Anfüh-
rungszeichen geschrieben werden, z.B. “Banane“.
elif x == "Äpfel":
Index=1
elif x == "Mango":
Index=2
elif x == "Kiwi":
Index=3
Zunächst legen wir die Liste an. Anschließend wird der Benutzer aufgefordert,
die gesuchte Frucht einzugeben. Da die Liste nur mit Indexen arbeitet, muss die
Frucht in den passenden Index umgerechnet werden. Dazu wird eine if-Abfrage
verwendet.
Deutlich einfacher wird die gleiche Aufgabe, wenn man Dictionaries ver-
wendet.
‘‘‘MIT DICTIONARIES'''
Bestand = {'Banane':501,'Äpfel':112,'Mango':52,'Kiwi':96 }
# Die Frucht entspricht dem Index und muss nicht umgerechnet werden
Wir können schnell sehen, dass für dieses Beispiel die Verwendung von
Dictionaries einen deutlichen Vorteil bietet. Die Funktion ist dabei die
gleiche.
# Anschließend wird der Bestand ausgegeben
Anschließend erscheint das Element mit dem Index, welcher zuvor festgelegt
wurde.
Danach wird die zuvor abgefragte Frucht, die in x oder Index gespeichert wurde,
ausgegeben. Als letztes wird die Zeichenkette vorhanden dargestellt. In der
Summe sieht die Ausführung des Programms wie folgt aus:
Wir können eine Funktion aufrufen, indem wir ihr ein oder mehrere Argumente
übergeben.
Innerhalb der Funktion werden daraufhin Befehle abgearbeitet und als Resultat
erhalten wir (nicht zwingend) einen oder mehrere Rückgabewerte. Auch wenn
es viele Standardfunktionen bereits gibt, kommt es vor, dass wir eine zuvor noch
nicht erstellte Funktion benötigen. Deshalb ist es sinnvoll und hilfreich, selbst
Funktionen schreiben zu können.
Eigene Funktionen sind nützlich, wenn wir innerhalb eines Programms Pro-
grammteile öfters verwenden.
Bei der Namensgebung gelten die gleichen Regeln wie für die Vergabe von
Variablennamen. Es ist auch hier von Vorteil, einen Namen zu vergeben, welcher
direkt auf den Einsatzzweck der Funktion schließen lässt.
Für die folgenden Abschnitte wird eine Funktion erstellt, welcher eine Zahl x
übergeben wird. Als Rückgabewert soll y=x² ausgegeben werden. Dafür gibt es
in Python den **-Operator, in diesem Beispiel soll der Befehl jedoch mit einer
Funktion realisiert werden. Ein sinnvoller Name für die Funktion wäre beispiels-
weise xsquare (x)
def xsquare(x):
Nach Angabe des Namens der Funktion werden runde Klammern ge-
setzt. In diese kann ein Übergabewert (ein Argument) geschrieben wer-
den.
Bei der xsquare Funktion ist das eine Zahl x. Diese werden wir später im Haupt-
programm anlegen.
Anschließend wird, wie bei der if-Abfrage und Schleifen, ein Doppelpunkt ge-
setzt. Die Befehle müssen auch hier eingerückt werden. Wir sehen, dass es wie-
derkehrende Formatierungsmuster in Python gibt.
Mit der übergebenen Variablen x kann innerhalb des Programms gearbeitet wer-
den. Es können beliebige Befehle ausgeführt werden.
def xsquare(x):
y=x*x
Der Übergabewert kann auch leer sein, beispielsweise bei der bereits
bekannten Funktion input(). Diese benötigt nicht zwingend einen Über-
gabewert.
Nachdem wir die Funktion erstellt haben, können wir die Funktion aufrufen. Für
das Beispiel wird die Zahl drei übergeben, d.h. die Funktion wird aufgerufen.
def xsquare(x):
y=x*x
def xsquare(x):
y=x*x
‘3‘
=> Argument/Übergabewert
xsquare(3 ) Konsolenausgabe
y=x*x
xsquare(3)
Aber warum? Schließlich wird die Variable x doch in der Funktion verwendet.
Dazu müssen wir uns den Unterschied zwischen lokalen und globalen Variablen
anschauen.
Bei der Erstellung von Funktionen ist es wichtig zu verstehen, dass die Variablen
x und y nicht außerhalb des Programms verwendet werden können. Sie sind auf
die Funktion beschränkt und können nur innerhalb dieser verwendet werden.
Man nennt sie daher auch lokale Variablen.
Eine Funktion bildet quasi eine Blackbox, der ein Wert übergeben werden kann.
Die Werte innerhalb der Blackbox kann man einsehen, aber nicht außerhalb der
Box verwenden.
Wenn man den Wert einer Variablen aus einer Funktion verwenden
möchte, muss dieser mit dem Befehl return zurückgegeben werden.
Der Befehl fordert den Benutzer auf einen String einzugeben. Der Rückgabewert
ist dabei der eingegebene String. Möchten wir den Rückgabewert abspeichern,
müssen wir ihn in eine Variable speichern.
eingabe= input(‘Bitte geben Sie eine Zahl ein‘)
Hier ist es wiederum wichtig zu verstehen, dass nur ein Wert zurückgegeben
wird und nicht die lokale Variable selber. Lokal bedeutet, dass wir außerhalb der
Funktion nicht auf sie zugreifen können.
4 wird zurückgegeben
Funktion
4
y
Den zurückgegebenen Wert kann man jedoch wieder in einer anderen, globalen
Variablen speichern. Diese kann sowohl im Hauptprogramm, sowie als auch in
den Funktionen verwendet werden.
Für die globale Variable kann sogar der gleiche Name der lokalen Variablen ver-
wendet werden, denn die lokale Variable ist außerhalb der Funktion nicht exis-
tent.
Als Beispiel wenden wir den return-Befehl auf die Funktion xsquare() an:
def xsquare(x):
y = x*x
return y
‘3‘ ‘9‘
=> Argument/Übergabewert => Rückgabewert
y = xsquare(3 )
Abbildung 31 Funktion xsquare mit return-Befehl
Wir sehen, dass die lokale Variable y den Wert x*x zugewiesen bekommt, wel-
cher anschließend als Wert von y zurückgegeben wird. Die Variable y kann dabei
nicht außerhalb der Funktion verwendet werden.
Das Beispiel kann noch kompakter geschrieben werden, indem der „Umweg“
über die lokale Variable y ausgelassen wird. Stattdessen wird direkt x*x zurück-
gegeben. In Python wird zunächst der mathematische Ausdruck x*x ausgerech-
net und das Ergebnis zurückgegeben.
def xsquare(x):
Wenn eine Funktion mit Hilfe des return-Befehls Werte zurückgibt, wird
die Funktion auch automatisch beendet. Daher muss der return-Befehl
immer der letzte Befehl der Funktion sein.
Schauen wir uns dafür ein weiteres Beispiel an, bei dem der return-Befehl ver-
wendet wird.
else:
‘‘‘ Hauptprogramm‘‘‘
Wir sehen, dass sich Rückgabewerte nicht nur auf Zahlen beschränken. Auch
Strings sind möglich. Jedoch ist der Rückgabewert dabei abhängig davon, ob die
if-Anweisung erfüllt ist oder nicht.
Dabei wird kein Argument übergeben. Das ist möglich, da die Funktion kein Ar-
gument erwartet oder indem wir innerhalb einer Funktion Standardwerte set-
zen, für den Fall, dass kein Argument angegeben wird. Mit Hilfe von Standard-
werten können eine Funktion und deren Aufruf vereinfacht werden. Komplexe
Funktionen besitzen teilweise mehrere Argumente, welche für Spezialfälle „re-
serviert“ sind. Bei diesen sind viele Standardwerte gesetzt.
Wenn man eine Funktion erzeugt, kann man den Argumenten Standard-
werte zuordnen. Wird beim Funktionsaufruf kein Wert übergeben, wird
der Standardwert übernommen. Wird ein Wert übergeben, wird der
Standardwert überschrieben.
Als Beispiel erweitern wir die Funktion xsquare(), sodass jede Potenz ausgerech-
net werden kann. Die Funktion berechnet folglich den Term
x hoch n 𝑦 = 𝑥 𝑛
Die Funktion benötigt dabei zwei Argumente, die Basis x und den Exponenten n.
def x_hoch_n(x,n):
return y
Als nächstes wollen wir n standardmäßig auf 2 legen, d.h. wenn man nur x über-
gibt, erhält n den Wert 2. Dafür wird beim Definieren der Funktion n=2 gesetzt.
def x_hoch_n(x,n=2):
y = x**n
return y
Wir rufen die Funktion auf, dabei übergeben wir nur einen Wert. Dieser wird in
der Funktion der lokalen Variablen x zugeordnet.
Der Funktionsaufruf
print(x_hoch_n(3)) # x=3 n=2 (Standard)
wird hingegen der Wert für n auch übergeben, wird der Standardwert von 2
überschrieben.
print(x_hoch_n(3,3)) # x=3 , n=3
gibt 27 aus, da 33 = 27
Dabei müssen wir darauf achten, dass alle Argumente mit Standardwerten am
Ende der Eingabe stehen.
Warum das so ist, kann man anhand des Beispiels leicht erklären:
def x_hoch_n(x=5,n):
Hier ist x als 5 gesetzt. Jetzt wäre anzunehmen, dass, wenn wir nur eine Zahl
übergeben, die Zahl automatisch der Variablen n zugeordnet wird. Das ist jedoch
nicht immer der Fall.
Der Aufruf
print(x_hoch_n(3)) # x =3 , n = undefiniert
Da im Anschluss kein weiterer Wert für n festgelegt wurde, erscheint eine Feh-
lermeldung, dass zu wenige Argumente übergeben worden sind.
SyntaxError: non-default argument follows default argument.
Die behandelten Funktionen waren dabei relativ simpel aufgebaut. Die Funktion
xsquare() besteht lediglich aus einigen Zeilen.
Im Hauptprogramm tauchen diese nur noch auf, wenn man sie aufruft. Dieses
Vorgehen optimiert die Übersicht und Struktur des Programms.
Um selbst eine Funktion auszulagern, legen wir eine neue Datei an, in die wir alle
Funktionen schreiben, welche wir auslagern wollen. Diese wird als modul_xsqu-
are.py abgespeichert.
Eine Datei, welche ausgelagerte Funktionen enthält, wird als Modul be-
zeichnet.
Als Beispiel für ein Modul wird die xsquare()-Funktion in die Datei modul_xsqu-
are.py geschrieben.
Im Beispiel enthält das Modul lediglich eine Funktion. Für gewöhnlich sind meh-
rere Funktionen in einem Modul zusammengefasst.
Das Programm fordert den Nutzer auf, eine Zahl einzugeben. Anschließend wird
die Funktion xsquare() aufgerufen, welche das Quadrat der eingegebenen Zahl
zurückgibt. Die Zahl und das Quadrat werden für die Konsole ausgegeben. Bevor
wir das Modul nutzen zu können, müssen wir es mit dem Signalwort import im-
portieren. Die Endung .py der Datei wird dabei weggelassen.
import modul_xsquare
Das Modul wurde importiert, jedoch kann die Funktion xsquare() nicht ohne An-
passung genutzt werden. Um die Funktion aus dem Modul verwenden zu kön-
nen, wird beim Aufruf der Funktion zunächst die Modulbezeichnung, dann ein
Punkt und anschließend der Funktionsname geschrieben.
import modul_xsquare
y =modul_xsquare.xsquare(x)
Dabei muss sichergestellt werden, dass das Modul und das Hauptpro-
gramm im gleichen Ordner liegen.
Alternativ kann ein Unterordner angelegt werden. Dann muss beim Importieren
des Moduls zusätzlich der Pfad des Unterordner vorangestellt werden. Das gleich
gilt für den Funktionsaufruf, auch hier muss der Pfad des Unterordners vorange-
stellt werden.
y= module.modul_xsquare.xsquare(x)
Abhängig von dem Speicherort der Funktion müssen wir ein Modul und ggf. ei-
nen Unterordner angeben.
Es ist offensichtlich, dass vor allem die dritte Variante schnell unübersichtlich
wird. Die Bezeichnung des abgespeicherten Moduls modul_xsquare ist nicht vor-
teilhaft gewählt. Bei jedem Funktionsaufruf muss der Modulname vorange-
schrieben werden. Dadurch werden die Funktionsaufrufe lang und unübersicht-
lich.
xsquare = module.modul_xsquare.xsquare
xsquare = module.modul_xsquare.xsquare
Der Vorteil dieser Vorgehensweise besteht darin, dass man nicht jedes Mal den
gesamten Modul-Pfad angeben muss. Jedoch wird beim Programmieren der Ur-
sprung der Funktion leicht übersehen, da aus dem Aufbau nicht mehr erkennbar
ist, dass sie aus einem Modul importiert wurde.
Wenn ein oder mehrere Module importiert werden, kann man ihnen
eine Abkürzung zuweisen. Das geschieht durch Hinzufügen der Bezeich-
nung „as“ nach dem Modulnamen sowie der gewählten Abkürzung.
Diese Angabe kann dabei frei gewählt werden. Auch hier dienen wieder
Punkte als Trennzeichen.
import modul_xsquare as xsq
Fortan muss bei einem Funktionsaufruf nicht mehr der vollständige Modulname
inklusive Pfad angegeben werden, sondern lediglich die Abkürzung.
y= xsq.xsquare(x) # Es muss kein Pfad angegeben werden
Es wurde bereits angesprochen, dass ein Vorteil von Modulen darin liegt, dass
man sie unabhängig vom Hauptprogramm weitergeben kann.
Daher ist es sinnvoll, bereits erstellte Module auch zu nutzen, und diese nicht
selbst zu schreiben.
Hier wird wieder ein Vorteil von Python deutlich. Es gibt eine enorme Commu-
nity rund um diese Programmiersprache. Deshalb sind sehr viele Standardmo-
dule und Funktionen bereits programmiert worden und stehen für alle zur freien
Verfügung.
Wenn mehrere Module gebündelt werden, spricht man auch von einer Biblio-
thek.
4.15. Bibliotheken
Bibliotheken (engl. libraries) sind ein Vorteil des open-source-Konzeptes, das Py-
thon verfolgt.
Dafür müssen wir jedoch genau wissen, wie man die richtigen Funktionen findet
und wie man sie korrekt implementiert.
Hinter einer Bibliothek verbergen sich meistens umfangreiche Codes, deren Ver-
ständnis jedoch zur Benutzung nicht erforderlich ist. Funktionen wie input() oder
print() können verwendet werden, ohne dass das dazugehörige Modul impor-
tiert wurde, da es sich hierbei um sogenannte Built-in-Funktionen handelt.
Diese werden so häufig verwendet, dass sie direkt in den Interpreter eingebaut
Übersetzung:
Der Python-Interpreter besitzt Funktionen und Typen, welche standardmäßig inkludiert und damit
immer verfügbar sind. Sie sind in der folgenden Tabelle alphabetisch aufgelistet.
Wir finden hier auch die bekannten Funktionen wie input(), eval(), print() oder
range() wieder.
Die Standardbibliotheken von Python bestehen zum größten Teil auch aus nor-
malen Modulen, wie sie im vorherigen Kapitel erklärt wurden. Wenn möglich
sollte man immer auf diese Bibliotheken zurückgreifen, da sich dadurch viel Ar-
beit ersparen lässt.
Alternativ findet man durch die Suchfunktion innerhalb der Python-Seite oder
über die Suchmaschinen meistens innerhalb kurzer Zeit die passende Funktion
für das Projekt.
NMa−münd + 2 · NMa−schrift
NMa =
3
Die Noten für die Übung sind bereits in der folgenden Tabelle aufgeführt.
Mathe_s entspricht dabei der schriftlichen Mathenote, Mathe_m der Mündli-
chen
- Übergebe den Funktionen die Noten der einzelnen Fächer, sodass die
Noten der Fächer sowie die Gesamtnote zurückgegeben werden.
- Gib sowohl die Noten der Fächer als auch die Gesamtnote aus.
4.17. Lösung
Wie immer gibt es mehrere Lösungsansätze. Das folgende Programm zeigt ledig-
lich einen möglichen Weg.
Zunächst speichern wir die Noten aus der Tabelle in einem Dictionary ab. Die
Schlüssel (keys) des Dictionaries sind dabei die Bezeichnungen der Fächer.
noten = {'ma_s':1.3,'ma_m':2,
'de_s':2.5,'de_m':2,
'en_s':3,'en_m':2.5
return (2*schrift+münd)/3
Der Funktion werden zwei Werte übergeben. Der Rückgabewert ist die Durch-
schnittsnote des Fachs.
Möchten wir beispielsweise die Mathenote ermitteln, rufen wir die Funktion
noteFach() auf und übergeben die entsprechenden Noten aus dem Dictionary.
Um den Wert der schriftlichen Mathenote (1,3) zu erhalten, wird der Schlüssel
angegeben
noten['ma_s']
Analog wird der Wert noten['ma_m'] für die mündliche Mathenote (2,0) aufge-
rufen.
Es ist sinnvoll, die Note auf maximal zwei Nachkommastellen zu runden. Der
Funktionsaufruf wird dadurch erweitert zu:
ma_ges=round(noteFach(noten['ma_s'],Noten['ma_m']),2)
en_ges=round(noteFach(noten['en_s'],noten['en_m']),2)
Damit haben wir die drei Noten der Fächer in den Variablen ma_ges, de_ges
und en_ges abgespeichert.
Anschließend kann die Funktion für die Bestimmung der Durchschnittsnote der
drei Fächer erstellt werden.
Die Funktion erhält den Namen noteGes() und ihr werden allgemein drei Fächer
übergeben.
def noteGes(fach1,fach2,fach3):
return (fach1+fach2+fach3)/3
Nach der Definition wird die Funktion aufgerufen. Dafür übergeben wir ihr die
drei zuvor errechneten Durchschnittsnoten der Fächer. Gleichzeitig runden wir
die Note wieder auf zwei Nachkommastellen.
n_ges=round(noteGes(ma_ges,de_ges,en_ges),2)
Zusatz:
Die beiden Funktionen noteFach() und noteGes() werden in ein Modul mit dem
Namen modul_noten.py gespeichert. Die Datei liegt im gleichen Ordner wie das
Hauptprogramm.
Um die Funktionen wieder nutzen zu können, müssen wir das Modul
im Hauptprogramm importieren.
import modul_noten
noteFach = modul_noten.noteFach
noteGes = modul_noten.noteGes
Damit ersparen wir uns bei jedem Funktionsaufruf das Angeben des Moduls.
Mit diesem Code wurde die Aufgabe gelöst und mit Hilfe der Tricks, welcher wir
uns bedienen, umfasst er nur wenige Zeilen.
Bei diesem Programm hält sich der Aufwand noch in Grenzen, allerdings kann
es bei komplexeren Aufgaben schnell unübersichtlich werden.
Daher empfiehlt es sich, sich die hier beschriebene Vorgehensweise von Anfang
an anzugewöhnen. Im nächsten Kapitel lernen wir ein Kernelement der Python-
Programmierung kennen, das objektorientierte Programmieren.
5.1. Klassen
Die Einteilung von Objekten aus der realen Welt in Klassen hilft unserem Gehirn,
effektiver zu arbeiten. Innerhalb von Bruchteilen einer Sekunde erkennt es Ge-
meinsamkeiten und Unterschiede.
Eine Klasse ist ein abstrakter Begriff, welcher die Gemeinsamkeiten im Verhalten
von Objekten beschreibt. Man spricht dabei von Klassifizierung. Als Beispiel neh-
men wir die Klasse Mensch.
Die Klasse Mensch kann beispielsweise mit den Attributen Name, Alter, Größe
etc. definiert sein und verschiedene Verhaltensweisen (Sprechen, Arbeiten,
Schlafen etc.) zeigen. Jeder individuelle Mensch ist dabei ein Objekt der Klasse.
Mit Hilfe der Klasse kann man beliebig viele Objekte (Menschen) erzeugen, wel-
che alle die gleichen Attribute besitzen.
Tom
26
1.84
Sprechen
Arbeiten
Schlafen
Mensch2
Klasse: Mensch Lisa
28
Attribute: 1,67
Name
Alter Sprechen
Größe Arbeiten
Schlafen
Verhaltensweisen
Sprechen
Arbeiten
Mensch3
Schlafen
Kevin
34
1,87
Sprechen
Arbeiten
Schlafen
Man beschränkt sich beim Erstellen einer Klasse auf die wesentlichen Merkmale,
welche dem Zweck dienlich sind. Diese sind je nach Aufgabe und Themenstellung
unterschiedlich.
Schauen wir uns an, wie man eine Klasse in Python erstellt und verwendet.
Vom Aufbau her erinnert eine Klasse an eine Mischung aus Funktionen und Dic-
tionaries. Zunächst wird das Signalwort class angeführt, danach der Name der
Klasse, gefolgt von einem Doppelpunkt.
class Mensch:
Anders als bei Funktionen benötigt die Klasse (noch) keine Übergabewerte. Dem-
entsprechend fallen auch die runden Klammern, wie wir sie von Funktionen ken-
nen, weg.
Als nächstes wird eine Funktion eingeführt, mit der ein Objekt initialisiert (er-
zeugt) werden kann. Dafür wird ein so genannter Konstruktor verwendet.
Ein Konstruktor ist eine Funktion zur Erstellung eines „Gerüsts“ für ein
Objekt. Er kann die Eigenschaft (Attribut) eines Objekts definieren,
ohne dass ihr ein Wert zugewiesen werden muss.
Für das Beispiel bedeutet das, dass man mit dem Konstruktor beispielsweise die
Eigenschaft Name festlegen kann, ohne einen konkreten Namen zu ergänzen.
Ohne diese Funktion müsste man einen festen Namen vergeben, welcher für je-
des Objekt der Klasse gilt. Würde man namen = Tom festlegen, würde jedes er-
zeugte Objekt automatisch den Namen Tom erhalten. Das wollen wir natürlich
nicht. Mit Hilfe des Konstruktors umgehen wir diesen Sachverhalt. Deshalb ver-
wenden wir bei jeder Klasse einen Konstruktor.
Da der Konstruktor eine Funktion ist, wird er mit def eingeleitet. Anschließend
folgt der Ausdruck __init__().
Achtung: Es sind jeweils zwei Unterstriche vor und nach init zu setzen.
Danach können der Funktion Werte übergeben werden, welche in runden Klam-
mern stehen. Eine Besonderheit dabei ist, dass der erste Übergabewert des Kon-
struktors der Ausdruck self sein muss. Der Ausdruck wird in der Benutzerober-
fläche Spyder automatisch erkannt und rot angezeigt.
self gibt dem Konstruktor vor, dass ein Objekt der eigenen Klasse über-
geben wird.
Innerhalb des Konstruktors legen wir die Attribute der Klasse fest, im vorliegen-
den Fall den Namen, das Alter und die Größe. Für jedes Element einer Klasse
muss die Bezeichnung self. vorangestellt werden.
Das zeigt dem Konstruktor, dass der Inhalt einer Objektvariablen zugeordnet
wird.
Die Programmierung ist anfangs gewöhnungsbedürftig, daher gehen wir das Er-
stellen einer Klasse anhand der Klasse Mensch durch.
In Beispiel Mensch sieht die Erstellung der Klasse und des Konstruktors wie folgt
aus:
def _init_(self,name,alter,größe,):
self.Alter=alter
self.größe=größe
class Mensch:
def _init_(self,name,alter,größe,):
'''
self.Alter=alter
self.größe=größe
Es ist sinnvoll, die Datentypen der Attribute und deren Funktion aufzuführen.
Wir haben jetzt zwar das Grundgerüst, jedoch noch kein Objekt angelegt. Mit
Hilfe der Klassen ist das jedoch sehr einfach. Dazu wird wieder ein individueller
Name angelegt. In unserem Beispiel erstellen wir Tom, welcher als Objekt
mensch1 bezeichnet wird.
Das Objekt mensch1 wird erzeugt, indem man die Klasse angibt und der Klasse
die Attribute des Konstruktors übergibt. Intern wird jetzt die -Konstruktor-Funk-
tion ausgeführt, die Attribute werden zugewiesen und das Objekt wird erstellt.
Somit wurde das erste Objekt der Klasse Mensch erstellt. Die einzelnen Attribute
des Objekts können wir durch Nennen des Objekts und der gewünschten Eigen-
schaft auslesen.
print(mensch1.Name)
print(mensch1.Alter)
print(mensch1.Größe)
Tom
26
1.84
Einzelne Werte des Objekts können auch nachträglich eingetragen oder über-
schrieben werden.
mensch1.Name="Tim"
In dem Beispiel wurde der Name von Tom in Tim geändert. Programmtechnisch
ist das kein Problem, logisch gesehen jedoch schon. Denn die Umbenennung ei-
nes Menschen ist (außer in Einzelfällen) nicht sinnvoll. Da ein Objekt einen realen
Gegenstand abbildet, müssen wir diese Problemstellung angehen.
Python bietet auch hierfür eine Methode, um bestimmte Attribute einer Klasse
zu schützen. Dafür schauen wir uns die Unterteilung von Attributen in public,
protected und private an.
Um Variablen vor der Außenwelt zu schützen, kann man diese auf „öf-
fentlich“ (public), „geschützt“ (protected), oder „privat“ (private) set-
zen.
Aber wie setzen wir das korrekt um? Die bisherige Definition von Attributen, in
der nur der Variablennamen angeführt wird, zeigt eine öffentliche Eigenschaft
des Objekts.
self.Name=name # dieses Attribut ist frei zugänglich/public
Setzt man jedoch einen Unterstrich vor die Variable, ist sie geschützt und kann
nur innerhalb der eigenen Klasse und in Unterklassen (siehe nächstes Kapitel)
verwendet werden.
Eine private Variable wird mit zwei Unterstrichen gekennzeichnet und steht nur
in der eigenen Klasse zur Verfügung. Bei beiden Fällen spricht man von Kapse-
lung.
Public
Name
Alter
Größe Kein direkter Zugriff
Privat/protect
Außenwelt
z.B. Passwort
Verhaltensweisen
sprechen
arbeiten
schlafen
Wie die Abbildung zeigt ist kein direkter Zugriff auf die Attribute möglich. Jedoch
kann dennoch über Umwege auf die Attribute zugegriffen werden, beispiels-
weise über Verhaltensweisen. Das ist auch gewollt. Lediglich der direkte, unkon-
trollierbare Zugriff soll verhindert werden. Innerhalb einer Verhaltensweise kann
das Passwort verwendet werden. Eine Verhaltensweise, in der das der Fall ist,
wäre z.B. „In Online-Banking einloggen“.
Die Kapselung erzeugt jedoch auch Probleme. Der Name kann nun nicht mehr
überschrieben werden, jedoch kann man ihn auch nicht mehr auslesen.
Der Befehl
print(mensch1.Name) #gibt (eigentlich) den Namen aus
Im Beispiel ist es nicht sinnvoll, den Namen zu ändern, jedoch ist auch kein Zu-
griff mehr möglich, sodass er auch nicht für andere Zwecke ausgegeben oder
ausgelesen werden kann. Man hat zwar an Sicherheit gewonnen, jedoch an
Funktionalität verloren. Das war nicht der Ursprungsgedanke, warum wir Vari-
ablen gekapselt haben.
Man kann innerhalb einer Klasse sogenannte Methoden einführen. Mit Metho-
den können auch gekapselte Attribute bearbeitet oder ausgegeben werden, wie
wir im folgenden Unterkapitel erfahren.
Da es sich um eine interne Funktion handelt, wird die Methode mit dem Sig-
nalwort def angelegt. Anschließend vergeben wir einen individuellen Namen der
Funktion. In unserem Fall soll die Klasse Mensch die Methode grüßen erhalten.
Der Methode können wieder in runden Klammern Argumente übergeben wer-
den.
Auch hier muss ebenfalls das Signalwort self als erster Wert übergeben werden.
Das zeigt dem Interpreter, dass es sich hierbei um eine interne Funktion, eine
Methode, handelt.
def grüßen(self):
Obwohl das Attribut selbst geschützt ist, kann man es innerhalb einer Methode
verwenden und ausgeben lassen.
'''
self.__Alter=alter
self.__Größe=größe
mensch1.grüßen()
Methoden sind weiterhin nützlich, um einem Objekte einer Klasse weitere Fä-
higkeiten zuzuordnen. Damit können Objekt mit dem Benutzer oder anderen Ob-
jekten kommunizieren.
Methoden können dabei wie Funktionen auch, selbst erstellt werden. In den
meisten Klassen werden Standardmethoden angelegt, um geschützte Attribute
zu ändern oder auszulesen. Deshalb lohnt es sich, diese genauer zu betrachten.
Das Attribut __Alter ist gekapselt, man kann nur durch die Methode ge-
tAlter auf das Attribut zugreifen, nicht über den Befehl mensch1.__Alter
print(mensch1.getAlter()) # Gibt das Alter aus
Ziel dabei ist es, wie im Kapitel Kapselung von Klassen bereits beschrieben, ledig-
lich einen kontrollierten Zugriff zuzulassen.
self.__Alter=alter_neu
Durch Methoden kann klar definiert werden, welche Regeln für Daten
innerhalb eines Objektes gelten. Es können Daten ausgegeben, verän-
dert oder unzugänglich gemacht werden.
Methoden können auch deutlich komplexer aufgebaut sein. Sie sind genau wie
Funktionen codetechnisch nicht limitiert.
Eine weitere Standard-Methode ist die del-Methode.
Das Objekt wird aus dem Speicher entfernt. Die Methode ist, ähnlich wie eine
Standard-Funktion, im Interpreter integriert und bei der Installation automatisch
eingefügt worden. Damit kann man die Methode auf jede Klasse anwenden, und
muss diese nicht in der Klasse definieren.
Wir können die Methode del innerhalb einer Klasse erweitern, um beispielsweise
weitere Aktionen anzustoßen, wenn ein Objekt gelöscht wird.
Dafür wird innerhalb der Methode eine Funktion angelegt mit dem Namen
__del__.
Das kann man nutzen, um beispielsweise eine Meldung auszugeben, dass das
Objekt gelöscht wurde.
Der Aufbau der del-Methode ist analog zu einer normalen Methode. Auch hier
ist der erste Übergabewert self.
def __del__(self):
del mensch1
Hiermit wurden die wichtigsten Eigenschaften von Klassen und Methoden erläu-
tert. Jetzt geht es an die nächste Übung, in der wir das Kapseln von Variablen
und das Anlegen von Methoden trainieren.
Erstelle anschließend eine Methode, welche nach Eingabe (Übergabe) des Pass-
worts alle gekapselten Attribute ausgibt. Wenn das Passwort falsch eingegeben
wurde, erscheint eine Fehlermeldung.
Die Unterscheidung, ob das Passwort richtig oder falsch ist, soll mit einer if-Ab-
frage realisiert werden.
5.7. Lösung
Zunächst erstellen wir die bekannte Klasse Mensch. Anschließend legen wir den
Konstruktor an und übergeben ihm die Attribute der Klasse. Zusätzlich fügen
wir das neue Attribut Passwort hinzu.
class Mensch:
'''
self.__Alter=alter
self.__Größe=größe
self.__Passwort=passwort
Da die Klasse um das Attribut Passwort erweitert wurde, muss auch ein Argu-
ment mehr übergeben werden. Im Beispiel sind alle Attribute privat. Notwen-
dig ist es lediglich beim Attribut Passwort.
Die Methode zur Abfrage des Passworts muss eine Variable passwort überge-
ben bekommen.
Nicht verwechseln, die Übergabevariable passwort wird aus dem
Hauptprogramm übergeben. Die Variable __Passwort ist eine private,
interne Variable der Klasse.
def checkPasswort(self,passwort):
'''
if passwort==self.__Passwort:
else:
Um die Methode zu testen, erstellen wir ein Objekt mensch1 der Klasse
Mensch. Das Attribut Passwort wird mit Python3 festgelegt.
Anschließend fordern wir den Benutzer auf, das Passwort einzugeben. Dieses
speichern wir in der Variablen pass_in.
pass_in = eval(input("Geben S ie das Passwort ein \n ",))
Danach wird die Methode ckeckPasswort aufgerufen. Ihr wird das zu prüfende
Passwort übergeben. Wir wenden die Methode auf das Objekt mensch1 an.
Als Rückgabewert erhalten wir die Daten des Objekts mensch1, oder eine Mel-
dung, dass das Passwort falsch war.
mensch1=Mensch("Tom", 26, 1.84,"Python3") #Das Passwort ist Python3
mensch1.checkPasswort(pass_in)
class Mensch:
'''
self.__Alter=alter
self.__Größe=größe
self.__Passwort=passwort
def checkPasswort(self,passwort):
'''
if passwort==self.__Passwort:
else:
mensch1.checkPasswort(pass_in)
Das Programm wird zweimalig ausgeführt. Zunächst wird ein falsches Passwort
eingegeben, anschließend das korrekte.
5.8. Klassenvariablen
Alle Variablen bzw. Attribute einer Klasse wurden bisher in der __init__ Methode
festgelegt. Dadurch gelten sie spezifisch für jedes erstellte Objekt. Das ist auch
logisch, schließlich besitzt jedes Objekt seine individuellen Attribute.
Es gibt jedoch auch Eigenschaften, die eine ganze Klasse als Einheit betreffen. In
unserem Beispiel Mensch wäre das die Anzahl an angelegten Personen. Die An-
zahl der existierenden Menschen ist eine Variable, welche nicht objektabhängig
ist, sondern für die ganze Klasse gilt.
In Python lässt sich im Hauptprogramm eine Zählvariable anlegen, die jedes Mal
beim Erzeugen eines neuen Objektes erhöht wird.
...
Die Variable anzahl ist zusätzlich bei jedem erstellten Objekt vorhanden, ohne
dass man sie extra übergeben muss.
mensch1=Mensch("Tom", 26, 1.84,"Python3")
print(mensch1.anzahl)
Die globale Variable anzahl ist noch für jedes Objekt gleich – Nämlich 0!
Noch wird die Variable nicht verändert und zeigt daher nicht die aktu-
elle Anzahl an erzeugten Objekten/Datensätzen.
Beispielsweise können die __init__ und __del__ Methode erweitert werden, so-
dass die Zählvariable beim Anlegen oder Löschen eines Objekts hoch- oder run-
tergezählt wird.
Mensch.anzahl =Mensch.anzahl +1
Für den Ausdruck x=x+1 kann man abgekürzt auch x+=1 schreiben und
analog für x=x-1 den Ausdruck x-=1
Jedes Mal, wenn ein Objekt initialisiert wird, wird zusätzlich diese Meldung mit
der neuen Anzahl ausgegeben.
Die Klasse Mensch wurde mit den Methoden und der Klassen-Variable erweitert.
class Mensch:
'''
self.__Alter=alter
self.__Passwort=passwort
def __del__(self):
del mensch1
Bei jeder Initialisierung wird Mensch.anzahl um eins erhöht und der Wert ausge-
geben. Anschließend wird beispielhaft ein Objekt gelöscht. Dabei wird die Klas-
senvariable um eins verringert und ebenfalls ausgegeben.
Bei der Erstellung eines neuen Objekts wird die Durchschnittsgröße neu berech-
net. Dafür benötigen wir die Variable anzahl, welche zuvor eingeführt wurde.
5.10. Lösung
Zunächst werden die Klassenvariablen angelegt und ihnen der Wert Null zuge-
ordnet. Die Variablen wurden dabei sinnvoll abgekürzt:
class Mensch:
Jedes Mal, wenn ein neues Objekt erstellt wird, wird die übergebene Größe auf-
summiert und eine neue Durchschnittsgröße berechnet.
def __init__(self, name, alter, größe, passwort):
'''
self.__Alter=alter
self.__Passwort=passwort
Mensch.gr_schnitt=Mensch.gr_ges/Mensch.anzahl
Zum Berechnen der Gesamtgröße aller Objekte verwenden wir die übergebene
Variable größe. Alternativ eignet sich auch self.__Größe, da die Variable zwei Zei-
len zuvor den gleichen Wert zugewiesen bekommen hat.
Die Werte werden aufsummiert und anschließend wird der Wert gr_schnitt be-
rechnet. Wir sehen, dass wir durch den Aufruf Mensch.gr_schnitt auf den ge-
wünschten Wert zugreifen können.
Optional können wir eine Ausgabe hinzufügen. Dabei wird die Durchschnitts-
größe wiederum auf zwei Nachkommastellen gerundet.
print('Die Durchschnittsgröße beträgt nun', round(Mensch.gr_schnitt,2),)
Anschließend führen wir das gleiche Prozedere für die __del__ Methode durch.
Diese wird durch die gleichen Befehle ergänzt. Zunächst wird die Gesamtgröße
berechnet und anschließend die Durchschnittsgröße.
def __del__(self):
Die Ausgabe wird durch die gleichen Aufrufe wie beim vorherigen Beispiel aus-
geführt.
mensch1=Mensch("Tom", 26, 1.84,"Python3")
del mensch1
5.11. Vererbung
Die Einteilung von Objekten aus der realen Welt in Klassen ist übersichtlich und
leicht zu verstehen. Sehen wir ein neues Objekt, beispielsweise eine neue Per-
son, sucht das Gehirn Gemeinsamkeiten und Unterschiede zu uns bereits be-
kannten, eingespeicherten Objekten. Diese Gemeinsamkeiten werden mit Erfah-
rungswerten abgeglichen, wodurch eine Einteilung, besser bekannt als „der
erste Eindruck“ einer Person innerhalb von wenigen Sekunden erfolgt.
Unsere Welt ist ein riesiges, komplexes System, bei dem viele Klassen sich ge-
genseitig beeinflussen. Deshalb ordnet unser Gehirn Objekte nicht nur in ein-
zelne Klassen, sondern verschiedene Unter- und Überklassen an.
Als Beispiel gibt es bei der Überklasse Mensch verschiedene Unterklassen. Dabei
kann die Einteilung nach geografischer Herkunft (Asiaten, Europäer, Afrikaner,
…), Alter (Babys, Kinder, Jugendliche, Erwachsene, …) oder anderen Aspekten wie
dem Beruf (Künstler, Ingenieure, Programmierer, …) eingeteilt werden. Man
spricht dabei auch von Kindsklassen und Elternklassen.
Die einzelnen Kindsklassen haben zum einen alle die gleichen Attribute wie die
Überklasse, können jedoch noch zusätzliche, individuelle Klassen-Attribute be-
sitzen.
Das Erstellen der Unterklasse ist vom Aufbau identisch mit dem Erstellen der
übergeordneten Klasse. Jedoch muss nach dem Klassennamen der Unterklasse
der Name der Überklasse angegeben werden.
Als Beispiel erstellen wir eine Unterklasse der Klasse Mensch. Diese beinhaltet
begeisterte Python-Fans, daher ist ein passender Name der Kindsklasse Pro-
grammierer.
class Programmierer(Mensch):
Nachdem die Unterklasse angelegt wurde, wird wieder der Konstruktor der
Klasse angeführt. In diesem werden die Argumente der Überklasse und optional
weitere für die Unterklasse übergeben. Im Beispiel erhält die Unterklasse Pro-
grammierer ein zusätzliches Attribut. Das Attribut prog_spr steht dabei für eine
Programmiersprache des Programmierers.
def __init__(self, name, alter, größe, prog_spr):
Nachdem das Objekt initialisiert wurde, kann das Attribut prog_spr definiert
werden.
self.Prog_spr=prog_spr
Bei Unterklassen ist die Dokumentation, also die Docstrings, noch mehr von Be-
deutung, da man schnell übersehen kann, dass es sich um eine Unterklasse han-
delt. Es empfiehlt sich immer, Kindsklassen u.ä. deutlich zu kennzeichnen.
Nachdem die Unterklasse definiert wurde, können wir wie gewohnt Methoden
erstellen, beispielsweise die set- und get-Methoden für den neuen Wert
prog_spr sowie die __del__ Methode. Die set- und get-Methoden sind hierbei
nicht zwingend notwendig, da die Variable prog_spr nicht gekapselt ist. Wir kön-
nen ihren Wert einfach überschreiben oder auslesen. Trotzdem werden beide
Methoden beispielhaft angelegt.
Beim folgenden Programmcode wird die Oberklasse auf das Wesentliche redu-
ziert. Die Passwort- und Durchschnittsgrößenerweiterung aus den Beispielen
und Übungen zuvor werden aufgrund der Übersichtlichkeit wieder entfernt.
Der Fokus liegt auf der untergeordneten Klasse.
Klassen-Variablen
'''
self.__Alter=alter
self.__Größe=größe
class Programmierer(Mensch):
''' Die Klasse Programmierer ist eine Unterklasse der Klasse Mensch
self.Prog_spr=prog_spr
def getProg_spr(self):
return self.Prog_spr
def setProg_spr(self,prog_spr_neu):
'''
'''
self.Prog_spr=prog_spr_neu
programmierer1=Programmierer('Tom',26,1.84,'Python')
print(programmierer1.getProg_spr())
del programmierer1
Als letztes wird die del Methode ausgeführt und das Objekt gelöscht.
In der Spyder-Benutzeroberfläche kann man aus diesem Grund den Quelltext der
Klassen ein- und ausklappen.
Diese Lösung funktioniert, jedoch ist die Optik bei mehreren Klassen immer noch
unschön und viele Benutzeroberflächen unterstützen diese Funktion nicht.
Die Klassen Mensch und die Unterklasse Programmierer werden dabei in eine
eigene Datei modul_klassen.py abgespeichert.
Dabei wird das gesamte Modul importiert. Um auf die Klassen zugreifen zu kön-
nen, muss der Pfad angegeben werden. Auch das ist uns bereits von Vorgehens-
weisen wie dem Auslagern von Funktionen in Module bekannt.
# Zugriff über Modulname.Klassenname
Dabei muss darauf geachtet werden, dass der Pfad anzugeben ist. Liegt
die Datei modul_klassen in einem Unterordner, muss dieser wiederum
vorangestellt sein.
Unterordner.Modulname.Klasse
Diese Notation ist sehr mühselig, daher gibt es noch alternative Varianten zum
Import der Klassen, welche sich auch auf Module mit Funktionen anwenden las-
sen.
Mit dem Befehl from Modulname import Klassenname kann eine einzelne Klasse
importiert werden.
from modul_klassen import Mensch
Der große Vorteil dabei ist, dass wir nicht den Pfad angeben müssen. Wir können
die Klasse verwenden, als stünde sie im selben Programm.
mensch1= Mensch("Tom", 26, 1.84)
Der Nachteil bei dieser Variante ist, dass man jede Klasse einzeln angeben muss.
Wenn man mehrere Klassen und Kinderklassen verwenden möchte, müssen alle
aufgeführt werden.
Eine Abkürzung für die Angabe aller Klassen bietet der Stern-Operator. Durch
den Befehl
from modul_klassen import*
werden alle Klassen des Moduls modul_klassen geladen und können ohne Anga-
ben des Moduls verwendet werden.
Der Nachteil beim Verwenden dieser Methode ist, dass man beim Importieren
von mehreren Modulen nicht weiß, in welchem Modul die verwendete Klasse
steht. Außerdem ist es für das Verständnis des Programmcodes verwirrend,
wenn in einer Zeile plötzlich ein Objekt mit einer Klasse angelegt wird, welche
vorher nirgends konkret zu sehen war. Dem kann man mit einer ausführlichen
Dokumentation entgegenwirken. Trotzdem empfiehlt es sich, wenn nur wenige
Klassen benötigt werden, diese durch konkretes Nennen des Namens zu impor-
tieren.
from modul_klassen import Mensch, Programmierer
Mit diesem Befehl ist klargestellt, dass die Klassen Mensch und Programmierer
aus dem Modul modul_klassen stammen. Außerdem weißt einen unsere Pro-
grammierumgebung Spyder durch eine Warnung (kein Error) hin, dass wir den
Sternoperator verwendet haben.
Das Auslagern von Klassen ist dem von Funktionen weitestgehend identisch. In
der nächsten Übung legen wir den Fokus noch einmal auf Klassen und Unterklas-
sen. Dabei wird ein bekanntes Glücksspiel hinzugezogen.
Beim Lotto 6 aus 49 werden nach dem Zufallsprinzip 6 Zahlen aus der Zahlen-
reihe von 1 bis 49 gezogen. Ergänzungen wie Zusatz- und Superzahlen werden
bei diesem Beispiel nicht berücksichtigt.
2. Lege danach eine Methode check_gewinn an, welche die eigenen Lottozahlen
mit den Gewinnzahlen vergleicht und die Anzahl der Treffer zurückgibt. Am ein-
fachsten kann man das durch eine for-Schleife realisieren, welche für jede Ge-
winnzahl eine if-Abfrage durchführt.
Der Befehl x in liste gibt True zurück, wenn das Element x in der Liste
liste vorkommt, ansonsten False. Damit können wir prüfen, ob eine Ge-
winnzahl mit den eigenen Zahlen übereinstimmt.
7. Lasse die Namen und die Anzahl an Treffern für jeden Spieler ausgeben.
Da neue Funktionen verwendet werden und die Abfolge der Befehle etwas kom-
plexer ist als die vorherigen Beispiele, kann die folgende Schablone als Hilfestel-
lung dienen. Es gibt, wie immer beim Programmieren, noch unzählige weitere
Möglichkeiten.
import random
class Lottospieler:
'''
Klassen-Variablen
'''
def __init__(self,name,zahlen):
'''
'''
def check_gewinn(self,gewinn_zahlen):
'''
'''
### HAUPTPROGRAMM###
lottozahlen =range(1,50)
5.14. Lösung
Zunächst importieren wir das Modul random, damit die Funktion sample() ver-
wendet werden kann. Das Modul ist beim Download von Anaconda automatisch
heruntergeladen worden. Da es nicht zu den Built-in-Bibliotheken gehört, müs-
sen wir es importieren.
import random
Anschließend wird die Klasse Lottospieler erstellt. Sie besitzt keine Klassenvari-
ablen.
Danach weisen wir in der Methode __init__ die Attribute name und zahlen zu.
import random
class Lottospieler:
Klassen-Variablen
'''
def __init__(self,name,zahlen):
'''
'''
self.Name=name
self.Zahlen=zahlen
Somit wurde zwar die Klasse angelegt, jedoch fehlt noch die Methode check_ge-
winn.
Der Methode werden die Gewinnzahlen in einer Liste mit sechs Elementen über-
geben.
Jedes Element der eigenen Liste Zahlen wird mit den Gewinnzahlen abgeglichen.
Dafür wird eine for-Schleife verwendet. Falls das Element gleich ist, wird die Zähl-
variable treffer um eins erhöht.
def check_gewinn(self,gewinn_zahlen):
'''
'''
treffer+=1 # Treffer +1
Anschließend erzeugen wir die Gewinnerzahlen mit der range() und der sample()
Funktion
lottozahlen =range(1,50) # Erzeugt eine Liste von 1 -49
gewinn_zahlen = random.sample(lottozahlen,6)
Diese erhalten sechs individuelle Glückszahlen, welche wir selbst festlegen kön-
nen. Im Beispiel wurden zur Vereinfachung sechs aufeinanderfolgende Zahlen
gewählt.
'''Erzeugen der Spieler'''
lottospieler1=Lottospieler('Tom',[1,2,3,4,5,6])
lottospieler2=Lottospieler('Lisa',[7,8,9,10,11,12])
lottospieler3=Lottospieler('Kevin',[13,14,15,16,17,18])
auf den Namen des Spielers zugegriffen und die Anzahl der Treffer seiner Zahlen
durch den Methodenaufruf
lottospieler1.check_gewinn(gewinn_zahlen)
geprüft. Das alles wird in einen print-Befehl für alle Spieler gleichermaßen aus-
gegeben.
'''Ausgabe der Gewinner'''
print("Gewinnerzahlen sind:",gewinn_zahlen)
print(lottospieler1.Name,"hat",lottospieler1.check_gewinn(gewinn_zahlen),"richtige
Zahlen")
print(lottospieler2.Name,"hat",lottospieler2.check_gewinn(gewinn_za hlen),"richtige
Zahlen")
print(lottospieler3.Name,"hat",lottospieler3.check_gewinn(gewinn_zahlen),"richtige
Zahlen")
Damit sind wir auch schon am Ende aller wichtigen Elemente und Bausteine der
Python Programmierung. Variablen, Listen, Schleifen, Klassen, Vererbung - wir
haben alle Themengebiete behandelt und kleinere Beispiele dazu programmiert.
Alles, was jetzt folgt, ist lediglich das Importieren und Anwenden von bereits be-
stehenden Funktionen. Darauf liegt auch der Fokus von Python. Wir können be-
stehende Module verwenden, um nahezu jede Problemstellung zu lösen.
Nachdem wir die Grundlagen behandelt haben, beschäftigen wir uns mit der op-
tischen Gestaltung des Programms, beispielsweise anhand von grafischen Benut-
zeroberflächen. Dafür müssen wir lediglich vorhandene Funktionen bzw. Metho-
den korrekt anwenden können. Hierzu stehen uns viele verschiedene Möglich-
keiten und Bibliotheken zur Verfügung. Im folgenden Kapitel wird auf die meist-
verwendete Bibliothek zurückgegriffen, welche zudem am geeignetsten für An-
fänger ist.
Deshalb behandeln wir in diesem Kapitel eine Bibliothek, welche eine grafische
Oberfläche erzeugen kann.
zu importieren.
Das Erstellen eines Fensters (window) setzt ein Objekt voraus. Der dazugehörige
Befehl ist entsprechend:
window = Tk()
Nachdem das Objekt erstellt wurde, können verschiedene Methoden auf das Ob-
jekt angewandt werden.
Die essenziellste Methode aus der Klasse Tk ist die Methode main-
loop(). Sie öffnet das Objekt window. Der Befehl muss daher im Haupt-
programm immer als letztes, nach den Einstellungen wie Fenstergröße,
Schrift etc. ausgeführt werden.
window.mainloop()
Nachdem das window-Objekt erstellt wurde, kann die Größe festgelegt werden.
Die benötigte Funktion dafür lautet geometry(). Ihr wird ein String mit der ge-
wünschten Pixelbreite und Pixelhöhe übergeben.
window.geometry(500x200) # 200 Pixel hoch, 500 Pixel breit
Tkinter ist wie eine Art Baukasten aufgebaut. Das Objekt window bildet die Basis.
Auf dieses Objekt können andere Objekte gesetzt werden.
Um ein label-Objekt zu erstellen, wird die Klasse Label aus der Tkinter-Bibliothek
verwendet.
Dem Label werden das Objekt, auf welchem der Text gesetzt wird, und der an-
zuzeigende Text übergeben. Das geschieht, indem man der Variablen text den
gewünschten string übergibt.
Ähnlich wie das Fenster muss man anschließend das Label noch aktivieren. Dafür
wird die Funktion pack() verwendet.
label = Label(window,text=“Python Tkinter“)
label.pack(expand=1)
Der Methode Frame() werden das Objekt window sowie die Rahmenart und die
Rahmenbreite übergeben. Danach wird der Rahmen mit dem pack() Befehl akti-
viert. Diesmal müssen die Werte fill='both' und expand=1 aufgerufen werden.
Die Variablen sorgen dafür, dass sowohl die Schrift als auch das eigentliche Fens-
ter eingerahmt wird. Die detaillierte Arbeitsweise ist für den Benutzer unwichtig.
frame.pack(fill='both',expand=1)
Nachdem das window, die Beschriftung und der Rahmen erstellt wurden, kön-
nen wir das Programm das erste Mal ausführen. Der vollständige Programmcode
lautet:
from tkinter import* #importiert alle Funktionen des Moduls
label.pack(expand=1)
frame = Frame(window,relief='ridge',borderwidth=20)
frame.pack(fill='both',expand=1)
window.mainloop()
Zugegeben, dieses ist jedoch noch sehr trist aufgebaut. Es gibt keine Flächen,
Aufforderungen an den Benutzer oder ähnliches. Das wollen wir nun ändern.
Als nächstes wird ein Button erstellt, mit dem man das Fenster wieder schließen
kann. Buttons können für eine breite Palette an Funktionen eingesetzt werden.
Ihr Vorteil liegt in der leichten Programmierung und der benutzerfreundlichen
Optik. Beim Klick auf einen Button wird eine Aktion ausgeführt.
Dafür werden der Methode Button() das Objekt window, der Text des Buttons
sowie die Höhe und Breite übergeben.
button=Button(window,text='EXIT',width=10,height=2)
Es ist wichtig, das übergeordnete Objekt, in diesem Fall das window oder den
frame, zu übergeben.
Anschließend wird der button über den bekannten pack() Befehl aktiviert. Dem
pack() Befehl übergeben wir dabei die Variable side=‘bottom‘. Dadurch wird das
Objekt button am unteren Rand platziert. Es ist auch möglich, ihn oben (top)
oder links und rechts (left / right) zu platzieren.
button.pack(side='bottom')
Führen wir den Programmcode aus, wird der Button angezeigt. Dieser Button
hat jedoch noch keine Funktion. Wir können ihn anklicken und es wird ein opti-
sches Feedback gegeben, jedoch wird keine Funktion ausgeführt.
Als letztes benötigt der Button nämlich noch eine Funktion bzw. Methode, wel-
che beim Anklicken ausgeführt wird.
Diesen Befehl müssen wir beim Klicken auf den Button ausführen.
Das dazugehörige Attribut, welches wir im Objekt button setzen müssen, heißt
command. Command wird immer beim Klicken des Buttons automatisch ausge-
führt. Setzen wir command=window.destroy, wird das Fenster geschlossen, so-
bald wir den Button anklicken.
button=Button(window,text='EXIT',width=10,height=2,command=window.destroy)
Wir haben dem Button die Funktion destroy zugeordnet. Beim Drücken des
Knopfs schließt sich das Fenster.
Es ist auch möglich, eine eigene Funktion mit dem Button zu verknüp-
fen.
Als Beispiel soll jedes Mal, wenn der Button gedrückt wird, eine Konsolenaus-
gabe stattfinden.
Nachdem wir die Funktion zugewiesen haben, rufen wir das Fenster auf. Bei je-
dem Klick wird die gewünschte Ausgabe angestoßen.
Als nächstes wird das Programm erweitert. Statt eines print()-Befehls soll der Be-
nutzer aufgefordert werden, Daten einzugeben.
eingabe.pack()
abrufbar. Diese Abfrage wird in eine Funktion verpackt, welche den Wert gleich
wieder an der Konsole ausgibt.
def einlesen():
print(eingabe.get())
Damit wird beim Klicken des Buttons der eingelesene Text an der Konsole aus-
gegeben.
Der eingelesene Text wird als string abgespeichert. Möchte man eine
Zahl einlesen, um später mit ihr zu rechnen, muss der Datentyp in int()
oder float() geändert werden.
x= eingabe.get() #Eingelesene Zahl wird als String abgespeichert
Außerdem ändern wir den Text des Buttons von EXIT zu Einlesen. Der gesamte
Code ergibt sich so zu:
from tkinter import* #importiert alle Funktionen des Moduls
def ausgabe():
print(eingabe.get())
label.pack(expand=1)
frame = Frame(window,relief='ridge',borderwidth=20)
frame.pack(fill='both',expand=1)
button=Button(window,text='Einlesen',width=10,height=2,command=einlesen)
button.pack(side='bottom')
eingabe.pack()
window.mainloop()
Wir starten das Programm, das Fenster öffnet sich. Darin sind der Button sowie
ein Eingabefenster zu sehen. Wir geben einen Beispieltext ein. Beim Klicken des
Buttons wird der Text an der Konsole ausgegeben.
Die Klasse Entry enthält ein Attribut insert. Wenn wir ihr einen String
übergeben, erscheint dieser in der Eingabebox. Dafür muss als erstes
Element eine Null übergeben werden, als zweites Element der ge-
wünschte Text oder die gewünschte Zahl.
eingabe.insert(0,'Standardwert') #Setzt den Wert in das Feld
löschen. Das ist sinnvoll, wenn man mehrere Aktionen durchführt und sonst die
Eingabe/Ausgabebox überläuft.
Als nächstes werden wir noch eine Scrollbar hinzufügen. Das ist ein Feld mit vor-
definierten Auswahlmöglichkeiten. Durch Scrollen im Feld kann man das pas-
sende Element auswählen.
aufgerufen. Die Funktion Scrollbar(), welche ebenfalls Element des Tkinter Mo-
duls ist, erhält das Objekt window als Übergabewert. Innerhalb des Feldes soll
eine Box mit einer Liste von Elementen angezeigt werden. Dazu greifen wir auf
die Listbox() Funktion zurück, welche eine Eingangsvariable yscrollcommand
verlangt. Dieser müssen wir unsere Variable scrollbar zuordnen, wobei zusätzlich
ein set-Befehl angehängt werden muss.
listbox=Listbox(window,yscrollcommand=scrollbar.set)
Unsere listbox wurde erstellt. Wir müssen sie jetzt nur noch mit Werten füllen.
Das funktioniert am einfachsten durch den insert-Befehl. Die Elemente sollen an
das Ende gesetzt werden, deshalb übergeben wir den Wert END.
Wir legen eine Liste mit beliebigen Elementen an. Anschließend hängen wir mit
Hilfe einer for-Schleife die einzelnen Elemente der Liste an unsere Listbox an.
listbox=Listbox(window,yscrollcommand=scrollbar.set)
Als nächstes müssen wir die scrollbar noch konfigurieren. Das bedeutet, dass wir
sicherstellen, dass sich das Feld beim Scrollen mit der Maus auch gleichzeitig än-
dert. Das bereits bekannte command-Attribut wird hier zu listbox.yview gesetzt
scrollbar.config(command=listbox.yview)
scrollbar=Scrollbar(window)
listbox=Listbox(window,yscrollcommand=scrollbar.set)
scrollbar.config(command=listbox.yview)
listbox.pack(side="left")
window.mainloop()
Nach Ausführung des Programms erhalten wir das gewünschte Scrollfeld mit un-
serer Liste als Elemente zum Auswählen.
Wenn wir das ausgewählte Element nachvollziehen wollen, können wir den In-
dex des Elements bzw. die Reihe, in der die Zahl steht über die Funktion
erhalten.
Als nächstes schauen wir uns die Programmierung von checkboxen bzw. check-
buttons an. Eine checkbox ist ein Feld, das der Benutzer bei einer Abfrage ent-
weder anklicken (checken) oder offen lassen kann. Da die Checkbox lediglich
zwei Zustände besitzen kann (gecheckt oder nicht), wird das Ergebnis eine Vari-
able vom Typ bool, also 1 für True oder 0 für False sein. Diese Variable muss
zuerst angelegt werden. Dafür wird die Funktion IntVar() verwendet.
check=IntVar()
Anschließend wird die eigentliche Checkbox erstellt. Diese benötigt als Überga-
bewerte das Fenster, die Variable check und eine Funktion. Die Funktion wird
immer ausgeführt, sobald die Checkbox angeklickt oder die Auswahl wieder ge-
löscht wird.
check=IntVar()
checkbutton=Checkbutton(window,text="Python3",variable=check,command = ein-
lesen)
if check.get():
else:
Als letztes wird die Checkbox mit dem pack() Befehl wieder aktiviert.
checkbutton.pack()
else:
check=IntVar() #Check-Variable
checkbutton=Checkbutton(window,text="Python3",variable=check,command = ein-
lesen)
checkbutton.pack()
window.mainloop()
Die Checkbox wird an und abgewählt. Die Konsole gibt währenddessen folgen-
des aus:
Bei jeder Auswahl oder Abwahl wird die Funktion einlesen() ausgeführt und eine
Konsolenausgabe angestoßen.
label.pack(expand=1)
checkbutton=Checkbutton(window,
text="Python3",
variable=check,command = einlesen)
Mit Hilfe des grid-Managers können wir die Anordnung der Elemente, also der
Buttons sowie der Eingabe- oder Textfelder, bestimmen.
Zur optischen Darstellung des Rastersystems erstellen wir uns vier Buttons (but-
ton1 - button4) und ordnen sie mit Hilfe des grid-Befehls an.
from tkinter import* #importiert alle Funktionen des Moduls
button1=Button(window,text='Button1',width=10)
button1.grid(row=0,column=0)
button2=Button(window,text='Button2',width=10)
button2.grid(row=0,column=1)
button3=Button(window,text='Button3',width=10)
button3.grid(row=1,column=0)
button4=Button(window,text='Button4',width=10)
button4.grid(row=1,column=1)
window.mainloop(
Die Buttons werden in insgesamt zwei Reihen und zwei Spalten angelegt.
Wenn wir den grid-Manager verwenden, platziert er die Objekte an die ge-
wünschten Stellen. Damit benötigen wir den pack() Befehl nicht mehr.
Wir dürfen niemals den grid() und pack() Befehl im gleichen Fenster ver-
wenden. Ansonsten wird ein Error angezeigt.
Neben den Angaben zu Spalte und Zeile kann auch festgelegt werden, über wie
viele Spalten und Reihen das Element gelegt werden soll. Die Befehle dafür lau-
ten:
columnspan = 2, rowspan = 2 # Element über zwei Reihen und Spalten platziert
Als Beispiel erweitern wir unsere vier Buttons. Zwischen den Buttons wird ein X-
Abstand von 10 und ein Y-Abstand von 10 eingefügt. Um die passenden Ab-
stände herauszufinden, müssen wir etwas rumprobieren, bis es optisch anspre-
chend ist.
button1=Button(window,text='Button1',width=10)
button1.grid(row=0,column=0,padx=10,pady=10)
button2=Button(window,text='Button2',width=10)
button2.grid(row=0,column=1,padx=10,pady=10)
button3=Button(window,text='Button3',width=10)
button3.grid(row=1,column=0,columnspan=2,padx=10,pady=10)
window.mainloop()
Mit Hilfe der Strukturierung der Elemente können wir ein Fenster deut-
lich benutzerfreundlicher aufbauen.
6.4. Place-Manager
Wir haben die Platzierung von Elementen mit Hilfe eines Rasters besprochen.
Eine noch flexiblere Möglichkeit ist das Platzieren von Objekten mit Hilfe des
Place-Managers. Bei diesem gibt man die konkreten x- und y-Koordinaten an, an
die das Objekt ausgerichtet werden soll. Der Nullpunkt ist dabei die obere, linke
Ecke des Fensters.
Wir nehmen das vorherige Beispiel und realisieren es mit Hilfe des Place-Mana-
gers:
from tkinter import* #importiert alle Funktionen des Moduls
button1=Button(window,text='Button1',width=10)
button1.place(x=50, y=20)
button2=Button(window,text='Button2',width=10)
button2.place(x=150, y=20)
button3=Button(window,text='Button3',width=10)
button3.place(x=100, y=70)
window.mainloop()
Wenn wir ein Bild anzeigen wollen, muss dieses zunächst als PNG-Datei gespei-
chert werden. Jpg-Dateien sind alternativ auch möglich. Andere Datenformate
werden nur über Umwege unterstützt. Der Pfad der Datei muss dabei bekannt
sein. Für das Beispiel ist das Bild python.png im Pfad
C:\Python_Uebungen\python.png
gespeichert.
Um das Bild zu laden, wird eine variable img angelegt. Ihr wird das Foto überge-
ben. Das ist mittels des Befehls PhotoImage() möglich. Dabei müssen wir file=r
(read) setzen, und den Pfad des zu ladenden Bilds angeben.
img = PhotoImage(file = r"C: \Python_Uebungen\python.png")
verwendet werden.
Damit wird die Auflösung und somit die Größe des Bildes reduziert.
Wenn wir ein anderes Bild verwenden, muss dieser Befehl entspre-
chend angepasst werden.
Ausprobieren hilft dabei meistens. Für das Beispiel ist der Befehl nicht erforder-
lich. Das Bild ist in der Variablen img1 gespeichert. Um es auf dem Fenster an-
zeigen zu lassen, verwenden wir die Label() Klasse. Ihr übergeben wir die Vari-
able.
label_img=Label(window, image = img)
Label_img.grid()
window = Tk()
label.grid()
mainloop()
Mit dem Importieren von Bildern ist zum ersten Mal wortwörtlich etwas Farbe
in die Darstellung gekommen. Genau dort wollen wir weiter ansetzen, indem wir
Objekte wie Textfelder farbig hervorheben.
Die Klassen wie beispielsweise die Label() Klasse besitzt bereits Attribute zur
Festlegung der Farbe des Objekts. D.h. ohne nähere Angabe wird standardmäßig
der bekannte Grauton verwendet. Jedoch kann man sowohl die Farbe des Hin-
tergrunds als auch die Farbe der Schrift definieren sowie die Größe und sogar die
Schriftart.
bg – Hintergrundfarbe: red,green,yellow,pink,…
Die Attribute für fg und bg werden als String übergeben. Font benötigt die
Schriftart als string und die Größe als Zahl.
window,text='Groß',fg='white',bg='red',font=('Arial',48)
Als Beispiel werden drei verschiedene Textfelder angelegt, wobei jedes eine an-
dere Hintergrundfarbe, Schriftfarbe, Schriftgröße und Schriftstil erhält.
from tkinter import*
label1 = Label(window,text='Groß',fg='white',bg='red',font=('Arial',48))
label2 = Label(window,text='Mittel',fg='pink',bg='green',font=('Roman',32))
label3 = Label(window,text='Klein',fg='black',bg='yellow',font=('Bold',16))
label1.grid(row=0,column=0, pady=10)
label2.grid(row=1,column=0,pady=10)
label3.grid(row=2,column=0, pady=10)
window.mainloop()
Das oberste Feld hat einen roten Hintergrund mit weißer Schrift. Die Schriftart
ist Arial und die Schrift ist 48 Punkte groß.
Das letzte Feld hat einen gelben Hintergrund mit schwarzer Schrift. Die Schriftstil
ist Bold und die Schrift ist 16 Punkte groß.
https://docs.python.org/3/library/tk.html
Bei vorhandenen Objekten können die Attribute auch ausgelesen oder über-
schrieben werden.
Zum Auslesen eines Attributs wird die Methode cget verwendet. Das Überschrei-
ben eines Wertes erfolgt mit der Methode config.
print(label1.cget('font')) # Font Werte werden ausgelesen und ausgegeben
Damit haben wir die wichtigsten Bausteine für die Darstellung einer GUI durch-
genommen. In der folgenden Übungsaufgabe wenden wir das Gelernte an, um
eine optisch ansprechende GUI zu erstellen.
6.7. Übung-Taschenrechner
Im Folgenden soll die grafische Darstellung von anhand der Erstellung eines Ta-
schenrechners geübt werden. Die Aufgabenstellung hierfür lautet wie folgt:
3. Erstelle vier Check-Boxen mit den Bezeichnungen plus, minus, mal und geteilt.
Mit der Wahl der Checkbox wird der zu verwendende Operator festgelegt.
5. Erstelle einen Button, welcher bei Bestätigung das Ergebnis errechnet und in
das Eingabefeld einfügt.
6.8. Lösung
Zunächst legen wir das Grundgerüst an. Die Bibliotheken werden importiert.
window= Tk() #Erstellt das Objekt
Als nächstes definieren wir die Überschrift label1, unsere vier Checkbuttons 1-4,
die zwei Eingabefelder eingabe1 und eingabe2, unseren Bestätigungs-Button
button1 sowie das Ausgabefeld ausgabe1. Bevor wir die Checkbuttons anlegen
können, müssen wir noch vier Variablen check1-4 erstellen, welche den Inhalt
der jeweiligen Box speichern.
check1=IntVar() #Check-Variable Plus
Danach können wir alle Elemente anlegen. Den einzelnen Elementen wurde
gleichzeitig verschiedenen Größen, Hintergrundfarben und Schriftfarben zuge-
ordnet.
label1 = Label(window,text='Taschenrechner',fg='white',bg='grey',font=('Arial',32))
button1=Button(window,text='Rechne',width=10,height=2,command=ausgeben,
fg='white',bg='green',font=('Arial',10))
eingabe2=Entry(fg='black',bg='yellow',font=('Arial',12))
ausgabe1=Entry(fg='black',bg='green',font=('Arial',15))
checkbutton2=Checkbutton(window,text="Minus",variable=check2)
checkbutton3=Checkbutton(window,text="Mal",variable=check3)
checkbutton4=Checkbutton(window,text="Geteilt",variable=check4)
Bei den Checkboxen müssen wir keine Funktion übergeben, da beim An- oder
Abwählen einer Box nichts passieren soll. Lediglich beim Klick auf den button1
soll die Funktion ausgeben() ausgeführt werden.
Die Funktion ausgeben() überprüft zunächst, ob mehr als eine Box aktiviert
wurde. Dazu wird überprüft, ob die Summe aller check-Variablen größer als 1 ist.
Ist das der Fall, wird die Ausgabevariable ausgabe zu 'Mehrere ausgewählt' ge-
setzt.
def ausgeben():
if (check1.get()+check2.get()+check3.get()+check4.get() >1):
ausgabe='Mehrere ausgewählt'
Ist nur eine Checkbox aktiv, werden die Werte in den Eingabefeldern eingelesen.
Da sie als String abgespeichert werden, muss noch eine Typumwandlung in Inte-
ger erfolgen.
else:
zahl1=int(eingabe1.get())
zahl2=int(eingabe2.get())
ausgabe = zahl1+zahl2
elif check2.get():
ausgabe = zahl1-zahl2
elif check3.get():
ausgabe = zahl1*zahl2
ausgabe = round(zahl1/zahl2,2)
else:
Falls keine der vier Boxen ausgewählt wurde, wird die Ausgabevariable mit
'Wähle aus: +,-,*,/' überschrieben.
In jedem Fall wird das Ausgabefeld gelöscht und anschließend das Ergebnis (oder
der Fehler) ausgegeben.
ausgabe1.delete(0,'end')
ausgabe1.insert(0,ausgabe)
Als letztes werden alle Objekte platziert. Dafür wurde der grid-Manager verwen-
det. Der place-Manager funktioniert genauso. Der gesamte Programmcode ent-
wickelt sich dabei wie folgt:
def ausgeben():
ausgabe='Mehrere ausgewählt'
else:
zahl2=int(eingabe2.get())
if check1.get():
ausgabe = zahl1+zahl2
elif check2.get():
ausgabe = zahl1-zahl2
elif check3.get():
ausgabe = zahl1*zahl2
elif check4.get():
ausgabe = round(zahl1/zahl2,2)
else:
ausgabe1.insert(0,ausgabe)
label1 = Label(window,text='Taschenrechner',fg='white',bg='grey',font=('Arial',32))
button1=Button(window,text='Rechne',width=10,height=2,command=ausgeben,
fg='white',bg='green',font=('Arial', 10))
eingabe1=Entry(fg='black',bg='yellow',font=('Arial',12))
eingabe2=Entry(fg='black',bg='yellow',font=('Arial',12))
ausgabe1=Entry(fg='black',bg='green',font=('Arial',15))
'''CHECKFELDER'''
checkbutton1=Checkbutton(window,text="Plus",variable=check1)
checkbutton2=Checkbutton(window,text="Minus",variable=check2)
checkbutton3=Checkbutton(window,text="Mal",variable=check3)
checkbutton4=Checkbutton(window,text="Geteilt",variable=check4)
'''GRID-MANAGER'''
label1.grid(row=0,column=1,padx=10,pady=10,colu mnspan=2)
eingabe1.grid(row=1,column=1,padx=10,pady=10)
eingabe2.grid(row=1,column=2,padx=10,pady=10)
checkbutton1.grid(row=2,column=0,padx=10,pady=10)
checkbutton2.grid(row=2,column=1,padx=10,pady=10)
checkbutton3.grid(row=2,column=2,padx=10,pady=10)
checkbutton4.grid(row=2,column=3,padx=10,pady=10)
button1.grid(row=3,column=1,columnspan=2,pady=10)
ausgabe1.grid(row=4,column=1,columnspan=2,pady=10)
Das war nicht nur das Ende der Übung, sondern auch dieses Buches – fast! Denn
ein Kapitel, welches immer mehr an Bedeutung gewinnt, soll nicht unerwähnt
bleiben. Es zeigt die Möglichkeiten, die mit Python einfach zu realisieren sind.
Die Rede ist von künstlicher Intelligenz und neuronalen Netzen. Die meisten Un-
ternehmen verwenden Python bereits als Industriestandard für neuronale Netze
und machine learning.
Der Begriff neuronale Netze bezeichnet hingegen eine Art, wie die lernenden Al-
gorithmen aufgebaut sind. Maschinelles Lernen, machine learning, deep learn-
ing etc. beschreibt der Vorgang des Verbesserns eines neuronalen Netzes, also
das stetige Anpassen des Netzes: Das Netz „lernt“.
Bevor wir zum Aufbau eines neuronalen Netzes kommen, sehen wir uns zunächst
an, worin die Vorteile bei der Anwendung von künstlicher Intelligenz liegen.
Das Ziel der folgenden Kapitel ist es nicht, das Konstrukt der künstlichen Intelli-
genz bis ins kleinste Detail verstanden zu haben. Das würde den Rahmen dieses
Buches mehr als sprengen. Stattdessen werden die grundlegenden Prinzipien er-
klärt und Beispiele in Python behandelt, sodass man sich bei Interesse detaillier-
ter mit dem Themengebiet auseinandersetzen kann.
Die genauen Faktoren kennt niemand zu 100%, es könnte theoretisch auch sein,
dass eine Aktie bei gutem Wetter eher steigt als fällt. Das hört sich abwegig an,
aber es existieren zahlreiche Faktoren, die einen potenziellen Einfluss auf den
Kurs einer Aktie haben könnten.
Diese Menge an Einflüssen kann ein einfacher Mensch nicht überschauen. Und
genau hier könnte eine KI zum Einsatz kommen.
Würden wir einer KI alle Daten, die es jemals gegeben hat, einspeisen
und würden wir sie unendlich lange trainieren, würde die KI alles vor-
hersagen können, was jemals passieren wird. Sie wäre allwissend. Sie
könnte die Aktienkurse vorhersagen, wann und wo ein Mensch geboren
wird oder wie lange wir alle noch leben werden.
Wir wissen nun also, wozu eine KI fähig ist und welche Vorteile sie bietet. Sehen
wir uns nun an, wie eine KI bzw. ein neuronales Netz aufgebaut ist.
Ein künstliches, neuronales Netz ist nach diesem Vorbild aufgebaut. Es werden
verschiedene Neuronen erstellt, welche lernen, wie sie miteinander verknüpft
werden müssen, um das optimale Ergebnis zu einer definierten Aufgabe zu
finden. Das Erstellen dieser Verknüpfungen benötigt Daten, Zeit und
Rechenleistung.
Ein Neuron wird dabei auch als Tensor bezeichnet. Die Neuronen sind in
verschiedenen Ebenen (layer) aufgebaut.
Eine davon ist, dass nicht nur die vorherigen Neuronen einen Einfluss auf die
nächste Schicht haben, sondern dass die einzelnen Neuronen sich selbst
beeinflussen können. Für das generelle Verständnis sind die konkrete
Ausführung und der Aufbau der verschiedenen Strukturen irrelevant. Die
Prinzipien lassen sich auf alle Strukturen anwenden.
ausgang=[3,6,9,12,15]
Der Zusammenhang zwischen den beiden Reihen dürfte jedem auf Anhieb klar
sein. Jedes Element der zweiten Reihe ist das Dreifache des passenden Elements
der ersten Reihe. Eine KI weiß das zu Beginn jedoch nicht.
1. Durchlauf
„Raten“
1 Neuronales Netz 5
1 Neuronales Netz 1
Dabei werden zunächst auch unsinnige, zufällige Verbindungen gebildet, die spä-
ter wieder aufgelöst werden. Nach und nach bilden sich Verknüpfungen, die im-
mer näher an das gewünschte Ergebnis herankommen. Mit jedem neuen Durch-
lauf wird das Ergebnis genauer und nähert sich den richtigen Werten an.
In einem realen neuronalen Netz wird nicht, wie in der Abbildung, jede
Zahl einzeln durchlaufen, sondern immer alle Zahlen gleichzeitig, um
Quer-Abhängigkeiten miteinzubeziehen. In unserem Beispiel wäre das
die Prüfung, ob die anderen Daten der Datenreihe, beispielsweise die
Zahlen [2,3,4,5], ebenfalls einen Einfluss auf das Ergebnis 2 haben.
Wenn wir, nachdem das Netz trainiert wurde, neue, bisher unbekannte Daten
einspeisen, beispielsweise die Zahl 10, muss das Netz die passende Antwort auf
diese Zahl selbst errechnen.
Das Netz wird durch die bereits bekannten Daten eine Näherung des Ergebnisses
ermitteln, bei uns wäre das optimalerweise die Zahl 30. In der Praxis wird das
Ergebnis etwas davon abweichen, wobei die Abweichung mit der Anzahl der
Durchläufe immer geringer wird.
Prinzipiell ist somit bereits der Aufbau einer künstlichen Intelligenz erklärt. Es
wird ein neuronales Netz aus mehreren Schichten und vielen Neuronen aufge-
spannt. Anschließend müssen dem Netz Daten eingespeist werden. Durch das
Trainieren verbessert das Netz die internen Verbindungen und nähert das Ergeb-
nis für zukünftige Werte immer weiter dem wahren Wert an.
Natürlich zeigt das Beispiel die einfachste Form eines neuronalen Netzes mit nur
einer Eingangs- und einer Ausgangsliste. In der Realität sind die Daten komplex,
Als nächstes sehen wir uns die Realisierung in Python an. Dafür verwenden wir
bestehende Module.
Die Bibliothek tensorflow ist von Google gestaltet worden. Im Vergleich zu einer
privaten Bibliothek hat Google als Großkonzern quasi unbegrenzte finanzielle
Mittel. Die Bibliothek wurden von professionellen Entwicklern erstellt. Ten-
sorflow ist sehr zuverlässig und wird regelmäßig auf dem Laufenden gehalten. In
der open source deep-learning Bibliothek Keras, einer auf tensorflow aufbau-
enden Unterbibliothek, sind die Funktionen aufgeführt, welche wir zum Aufbau
eines neuronalen Netzes benötigen.
Keras kann auch unabhängig von tensorflow importiert werden. Bei Keras han-
delt es sich um eine private Bibliothek.
Die Bibliotheken sind nicht im Python Interpreter installiert. Daher müssen wir
die gewünschte Bibliothek zunächst installieren und den folgenden Befehl direkt
in die Konsole eingeben.
pip install keras
Falls der Befehl nicht funktionieren sollte, kann alternativ der Befehl
conda install -c conda keras
Anschließend wird die Eingabe mit Enter bestätigt. Gegebenenfalls müssen wir
davor und danach das Programm Spyder neu starten.
Es werden automatisch die Bibliotheken keras und tensorflow sowie weitere in-
stalliert.
Nach der Installation der Bibliotheken können wir die beiden wie gewohnt im-
portieren. Damit wir nicht jedes Mal den vollständigen Modulnamen tensorflow
bzw. keras angeben müssen, importieren wir alle Funktionen
from tensorflow import*
Damit haben wir unser erstes neuronales Netz erstellt. Dieses beinhaltet noch
keine Schichten und keine Neuronen. Das Netz ist das Grundgerüst, in das wir
Schichten und Neuronen einfügen können. Bevor wir die Schichten und Neuro-
nen anlegen, müssen wir zunächst wissen, wie viele Input-Neuronen wir benöti-
gen. Wir erinnern uns, dass die Input-Schicht die allererste Schicht bildet, die die
Eingangsdaten aufnimmt.
ausgang=[3,6,9,12,15]
Die Datensätze bestehen aus 5 Elementen. Bei der Anzahl der Neuronen
kommt es jedoch nicht auf die Anzahl, sondern auf die Dimension der
Daten an! In unserem Fall dürfen der Eingang der ersten Schicht sowie
der Ausgang der letzten Schicht lediglich ein Neuron beinhalten!
Die Dimension einer Liste ist immer 1! Streng genommen arbeiten die
Layer nicht mit Listen, sondern mit Arrays. Die Listen werden dabei in
ein eindimensionales Array überführt. Später lernen wir noch Arrays
und neuronale Netze mit mehr als einem Eingangsneuron kennen.
Als erstes legen wir den ersten Layer, den Input-Layer, an.
Dafür werden der add() Befehl sowie die layer() Funktion verwendet.
#Input-Layer
model.add(layers.Dense(units=3,input_shape=[1]))
Durch den Befehl wird dem Netz ein Layer vom Typ Dense hinzugefügt. Dense
steht für ein dichten Layer. Das bedeutet, dass jedes Neuron innerhalb des Lay-
ers mit jedem Neuron des nächsten Layers verknüpft ist, und nicht beispiels-
weise mit nur jedem zweiten. Außerdem geben wir die Anzahl an Neuronen
(units) an, in unserem Fall wählen wir drei Neuronen.
Als nächstes legen wir einen weiteren Layer an. Wir wählen zwei Neuronen.
#Zwischenlayer
model.add(layers.Dense(units=2))
model.add(layers.Dense(units=1))
Als letztes müssen wir unser neuronales Netz noch compilen. Das ist ein zusätz-
licher, erforderlicher Schritt. Der compile()-Funktion muss eine loss-Funktion
hinzugefügt werden.
Die loss Funktion gibt an, wann eine Abweichung als „gut“ oder „schlecht“ be-
trachtet werden soll. Als Schätzungsmethode verwenden wir die Annahme, dass
der mittlere quadratische Fehler (eng. mean square error) kleinstmöglich wer-
den soll.
Das bedeutet, ein Wert wird als „gut“ bezeichnet, wenn die Abwei-
chung vom Mittelwert zum Quadrat minimal wird. Der mittlere quadra-
tische Fehler wird sehr häufig in der Datenverarbeitung angewandt und
ist eine anerkannte Schätzmethode der mathematischen Statistik. Er
gewichtet Ausreißer aus einer Messreihe weniger stark als andere
Schätzmethoden.
Neben dem Gütekriterium für das Schätzen des Fehlers benötigt der compiler
noch einen optimizer. Dem optimizer übergeben wir eine Optimierungsme-
thode, standardmäßig verwenden wir hier SGD (stochastic gradiant decent). Die
genaue Wirkungsweise eines Optimizers ist für uns dabei unwichtig. Wir müssen
lediglich wissen, dass es verschiedene Optimierungsverfahren gibt.
model.compile(loss='mean_squared_error',optimizer='sgd')
Damit ist das neuronale Netz compliliert und bereit, trainiert zu werden. Dafür
übergeben wir dem Netz unsere beiden Datensätze mit Hilfe der fit-Funktion.
Der Input, welcher unsere Liste eingang bildet, wird als x, die Ausgangsliste aus-
gang als y bezeichnet.
Jetzt können wir das Netz das erste Mal laufen lassen. In der Konsole werden die
Durchläufe in wahnsinniger Geschwindigkeit angezeigt. Nach einigen Sekunden
sollten alle 1000 Durchläufe geschafft sein. Am Ende jeder Zeile können wir den
loss-Wert sehen. Dieser ist am Anfang noch sehr groß und strebt mit der Anzahl
der Durchläufe gegen Null.
Als letztes wollen wir unser trainiertes Netz verwenden, um Zahlen vorherzusa-
gen. Dazu verwenden wir den predict()-Befehl und übergeben ihm jeweils eine
Zahl, im Beispiel rufen wir drei predict()-Befehle mit den Zahlen 6, 7 und 8 auf.
print(model.predict([6]))
print(model.predict([7]))
print(model.predict([8]))
Bevor wie das Programm starten, sehen wir uns den gesamten Code an.
from keras import*
model=Sequential()
model.add(layers.Dense(units=3,input_shape=[1]))
#Zwischenlayer
model.add(layers.Dense(units=2,input_shape=[1]))
model.add(layers.Dense(units=1,input_shape=[1]))
eingang=[1,2,3,4,5]
ausgang=[3,6,9,12,15]
model.compile(loss='mean_squared_error',optimizer='sgd')
model.fit(x=eingang,y=ausgang,epochs=1000)
print(model.predict([6]))
print(model.predict([7]))
print(model.predict([8]))
Anschließend starten wir das Programm. Das neuronale Netz wird trainiert und
nach kurzer Zeit werden die vorherzusehenden Daten ausgeben.
Die gewünschten Zahlen waren bei uns 18, 21 und 24. Wir sehen also, dass das
neuronale Netz noch deutlich besser werden muss.
Das neuronale Netz wird genauer, indem wir ihm mehr Daten zur Ver-
fügung stellen oder es öfters durchlaufen lassen.
Erhöhen wir beispielsweise die Anzahl an Durchläufen von 1000 auf 10.000, wird
das Ergebnis schon deutlich genauer. Auch der Loss-Wert wird noch einmal er-
kennbar kleiner.
Wenn der loss-Wert oder das Ergebnis „nan (Not a Number)“ anzeigt,
liegt ein numerischer Fehler vor. Das kann bei neuronalen Netzen rela-
tiv schnell passieren. Es gibt keine einheitliche Lösung für diesen Fehler.
In diesem Fall sollten alle Schritte, die zu diesem Fehler führen, rück-
gängig gemacht werden.
Auch das Angeben eines anderen Optimizer-Verfahrens (sgd) kann Abhilfe schaf-
fen. Eine Alternative wäre beispielsweise optimizer=‘adam‘
Als nächstes werden wir etwas komplexere Daten verarbeiten. Dafür müssen wir
zunächst verstehen, dass das neuronale Netz in Python Arrays verarbeitet und
keine Listen.
In Spyder können wir die Unterschiede sehr gut darstellen. Dazu importieren wir
die Bibliothek numpy, die viele numerischen Funktionen enthält. Darunter sind
bekannte Funktionen wie die Expotentialfunktion, Logarithmen oder Sinus- und
Cosinusfunktionen. Numpy gehört zu den Standardbibliotheken, die im Interpre-
ter eingebunden sind. Daher müssen wir numpy lediglich importieren. Da wir nur
die array()-Funktion benötigen, wird nur diese importiert.
from numpy import array
Als nächstes schauen wir uns den konkreten Unterschied zwischen mehrdimen-
sionalen Listen und Arrays an. Dazu legen wir einen Datensatz an, welcher das
32 4 10 0 3400
44 2 20 0 3200
60 6 34 0 5500
20 2 2 1 2300
24 4 0 1 2700
44 5 21 1 3200
52 2 32 1 3200
Wir legen in Python die Daten zunächst als zweidimensionale Liste an.
datensatz1=[
[18, 2, 0, 0, 2100],
[20, 2, 2, 1, 2300],
[24, 4, 0, 1, 2700],
Als nächstes verwenden wir die Funktion array(), um aus der Liste ein Array zu
formen.
Wir sehen die verschiedenen Datentypen Array of int32 (Integer mit 32 Bit) und
list. Noch anschaulicher wird der Unterschied, wenn wir auf die Variable daten-
satz sowie auf die Variable data_array klicken und diese damit öffnen.
Für uns ist es wichtig zu verstehen, dass neuronale Netze mit Arrays ar-
beiten und wir daher unsere Listen in Arrays umwandeln müssen.
Als nächstes legen wir den Datensatz an und erstellen eine Eingangsvariable und
eine Ausgabevariable. Die Eingangsvariable enthält alle Daten, die Ausgabevari-
able das Gehalt der Person.
eingang=data_array[0:8,0:4] #Alle Zeilen (Index 0-7) Spalte 0-3
Wir geben in eckige Klammern unsere gewünschten Zeilen und unsere ge-
wünschten Spalten an, jeweils mit einem Komma als Trennzeichen. Mit Hilfe der
Doppelpunkte werden alle Elemente ausschließlich des Indexes verwendet.
Diesmal erstellen wir insgesamt vier Layer: einen Input- und einen Output-Layer
sowie zwei Zwischenlayer. Außerdem weisen wir diesmal deutlich mehr Neuro-
nen pro Layer zu: 16 für die Eingangsschicht, 64 für die mittleren Schichten und
eines für die Ausgangsschicht.
model=Sequential()
model.add(layers.Dense(units=16,input_shape=[4]))
#Zwischenlayer
model.add(layers.Dense(units=64))
model.add(layers.Dense(units=64))
model.add(layers.Dense(units=1))
Als nächstes compilieren wir das Netz und trainieren es anschließend. Diesmal
wird der Optimizer adam verwendet. Außerdem wurden die Zyklen auf 5000 er-
höht. Je nach Rechenleistung kann das Trainieren entsprechend einige Minuten
dauern.
model.compile(loss='mean_squared_error',optimizer= 'adam')
model.fit(x=eingang,y=ausgang,epochs=5000)
Als letztes kommt der spannende Teil. Wir wollen das Gehalt einer Person ab-
schätzen, welche nicht im Datensatz vorkommt.
Dazu legen wir uns zwei Testpersonen, pers1 und pers2, an.
Tom ist männlich, 18 Jahre alt, hat eine einjährige Ausbildung und entsprechend
ein Jahr Berufserfahrung.
Lisa ist weiblich, 52 Jahre alt, hat eine siebenjährige Ausbildung und bereits 20
Jahre Berufserfahrung.
#Vorhersagen der Zahlen
tom=array([[18,1,1,0]])
lisa=array([[52,7,20,1]])
print(model.predict(tom))
print(model.predict( lisa))
Wenn wir das Programm starten, wird das Netz trainiert. Als Ergebnis erhalten
wir anschließend:
Das geschätzte monatliche Gehalt für Tim beträgt 1920€ und für Lisa 4838 €.
Unser neuronales Netz hat die vier Faktoren ausgewertet und anhand
dieser Daten ein potenzielles Gehalt abgeschätzt.
Ist anhand des Datensatzes eine ungleiche Bezahlung aufgrund des Geschlechts
festzustellen? Um diese These zu prüfen, erstellen wir wiederum zwei Personen,
Niklas und Jennifer. Beide sind 30 Jahre alt, haben eine dreijährige Berufsausbil-
dung und sieben Jahre Berufserfahrung. Der einzige Unterschied, den wir in den
Daten setzen, ist das Geschlecht.
jennifer=array([[30,3,7,1]])
print(model.predict(niklas))
print(model.predict(jennifer))
Wiederum lassen wir das neuronale Netz durchlaufen und erhalten ein monatli-
ches Gehalt für Niklas von 3059 € und für Jennifer von 2570 €.
Der Zusammenhang, dass sich das Geschlecht auf das Gehalt auswirkt, kann
ohne Zweifel reproduziert werden. Anhand der Messdaten war das nicht eindeu-
tig nachzuweisen.
Dabei müssen wir immer im Hinterkopf behalten, dass alle Schätzungen lediglich
auf Basis der Stichproben getroffen werden. Vielleicht hatten wir zufälligerweise
nicht-repräsentative Stichproben herausgesucht.
Damit beenden wir den Einblick in die Welt der neuronalen Netze. Wir haben
gelernt, wie ein neuronales Netz aufgebaut ist und wie man ein einfaches, neu-
ronales Netz in Python programmiert. Außerdem haben wir gesehen, dass die
Genauigkeit erheblich vom Rechenaufwand und von den eingespeisten Daten
abhängt.
Natürlich ist das Python-Universum noch deutlich umfangreicher und es gibt un-
zählige Module, Schnittstellen zu anderen Programmen und vieles mehr. Auf je-
den Fall sollte jetzt, nach der Lektüre dieses Buchs, mehr als der Grundstein ge-
legt sein. In diesem Sinne: Gutes Programmieren!
Deshalb biete ich beim Kauf des Buches das eBook gratis als PDF-Datei an. Dort
sind alle Bilder hochauflösend und man erhält immer die aktuelle Version.
Dazu schicke eine Nachricht mit dem Betreff „Python3-eBook“, sowie einen
Screenshot des Kaufs oder einen Nachweis über die Bestellung bei Amazon an
die E-Mail:
BenjaminSpahic@pbd-verlag.de
Ich werde dir das eBook und die Programmcodes umgehend zukommen lassen.
Wenn dir etwas fehlt, nicht gefallen hat oder du Verbesserungsvorschläge oder
Fragen hast, schreib mir gerne eine E-Mail.
Ansonsten, wenn dir das Buch gefallen hat, würde ich mich auch über eine posi-
tive Bewertung bei Amazon freuen. Das hilft der Sichtbarkeit des Buchs und ist
das größte Lob, welches ein Autor bekommen kann.
Dein Benjamin
Der Autor übernimmt keinerlei Gewähr für die Aktualität, Vollständigkeit und
Richtigkeit der bereitgestellten Informationen. Außerdem kann keine Garantie
für das Erreichen der beschriebenen Fähigkeiten übernommen werden.
Bildnachweise:
https://icons8.de/icon/113140/kugelbirne
https://icons8.de/icon/79638/obligatorische
https://icons8.de/icon/78038/math
https://icons8.de/icon/42314/taschenrechner
Alle nicht-genannten Inhalte wurden vom Autor selbst erstellt. Er ist daher Urheber der Grafiken und hat
die Verwendungs- sowie Verbreitungsrechte.
*: https://docs.python.org/3/library/functions.html
*: https://www.python.org/community/logos/
**: https://en.wikipedia.org/wiki/File:Datove_centrum_TCP.jpg
**: https://pixabay.com/de/vectors/schaltungen-gehirn-netzwerk-chip-5076888/
* Diese Datei wird unter der GNU-Lizenz für freie Dokumentation zur Verfügung gestellt.
https://commons.wikimedia.org/wiki/Commons:GNU_Free_Documentation_License,_version_1.2
Es können Änderungen vorgenommen sein.
** Diese Datei wird unter der Creative-Commons-Lizenz „CC0 1.0 Verzicht auf das Copy-
right“ zur Verfügung gestellt.
https://creativecommons.org/publicdomain/zero/1.0/deed.de
Es können Änderungen vorgenommen sein.