diff --git a/Bugs.md b/Bugs.md
new file mode 100644
index 0000000..1557ade
--- /dev/null
+++ b/Bugs.md
@@ -0,0 +1,54 @@
+# Bugs und Fehlerbehebung
+Grundsätzlich müssen drei Arten von Fehlern unterschieden werden: Syntaxfehler, Laufzeitfehler und Semantikfehler.
+
+## Syntaxfehler
+Syntaxfehler sind ähnlich zu verstehen wie Rechtschreibfehler. Ein Befehl wurde nicht richtig geschrieben, eine Zeile nicht richtig eingerückt, eine Klammer nicht geschlossen. Syntaxfehler werden dabei gemeldet, bevor das eigentliche Programm ausgeführt wird.
+```
+ File "bug.py", line 1
+ print("Test)
+ ^
+SyntaxError: EOL while scanning string literal
+
+```
+Hier wurde ein String nicht beendet. Die Fehlermeldung zeigt die Datei und die Zeile an, in der der Fehler aufgetreten ist, sowie eine Meldung um was für einen Fehler es sich handelt.
+
+```
+ File "bug.py", line 2
+ print("True")
+ ^
+IndentationError: expected an indented block
+```
+Hier wurde die Einrückung weggelassen, was die Fehlermeldung auch mitteilt ("IndentationError"). Zudem wird wieder die Datei und die Zeile angezeigt.
+
+
+Syntaxfehler sind einfach zu beheben, da sie schnell gefunden sind und die Fehlermeldung sehr genaue Auskunft darüber gibt, was passiert ist. Viele Texteditoren bieten zudem die Funktion an offene Klammern hervorzuheben, um schon die Entstehung von leicht vermeidbaren Fehlern zu vermeiden.
+
+## Laufzeitfehler
+Laufzeitfehler finden, dem Namen nach, zur Laufzeit statt. Dabei gibt es verschiedene Fehlerquellen. Um die Fehlermeldung verständlicher zu machen werden die verschiedenen Arten von Laufzeitfehlern klassifiziert.
+
+### ValueError
+
+```
+Traceback (most recent call last):
+ File "", line 1, in
+ int("a")
+ValueError: invalid literal for int() with base 10: 'a'
+
+```
+
+Hier wurde versucht den String "a" in einen Integer umzuwandeln. Spezifischer in einen Integer mit der Basis 10, welches die Standardbasis für die Umwandlung in einen integer ist. Dies ist ein Beispiel für einen `ValueError`. Diese Fehler können auftreten, wenn zum Beispiel die Nutzereingaben nicht überprüft wurden.
+
+Laufzeitfehler zu finden ist weiterhin sehr einfach, da die Fehlermeldung sehr genau angibt, wo man zu suchen hat, weitaus schwieriger kann es allerdings werden einen Laufzeitfehler zu beheben, da dabei geklärt werden muss, ab wann das Programm den gewollten Zustand verlassen hat.
+
+### RecursionError
+
+```
+File "", line 2, in recursion
+ return recursion(x+1)
+RecursionError: maximum recursion depth exceeded
+```
+
+Hier wurde eine rekursive Funktion ohne Abbruchbedingung gestartet. Die wird bis zu einem Limit an Durchläufen durchlaufen und wirft dann einen `RecursionError`. Dieser ist zweifelsohne ein sehr spezieller Fehler.
+
+## Semantikfehler
+Semantikfehler sind von den beschriebenen drei Fehlerarten die weitaus schwierigste Kategorie, da sie vom Compiler oder Interpreter nicht angezeigt werden. Bei semantische Fehler, macht der Quellcode alles richtig, leider macht er nicht das, was er tun soll. Dabei sind Semantische Fehler sehr leicht zu erreichen. Wenn ich zum Beispiel in einer verschachtelten Schleife eine Anweisung in der falschen Einrückungsebene platziere, wird der Code wahrscheinlich noch funktionieren, allerdings nicht mehr das tun, was er soll. Somit ist beim Finden von Semantischen Fehlern sehr wichtig den erwarteten Output mit dem tatsächlichen Output zu vergleichen.
\ No newline at end of file
diff --git a/Glossar.md b/Glossar.md
new file mode 100644
index 0000000..d83aa86
--- /dev/null
+++ b/Glossar.md
@@ -0,0 +1,85 @@
+# Glossar
+## Level 0:
+### Programmiersprache
+Eine Programmiersprache ist eine formalisierte Form um den Computer in menschen-lesbarer Form Anweisungen zu geben.
+Diese Anweisungen werden bei höheren Programmiersprachen vom Compiler bzw. Interpreter in eine vom Computer lesbare Sprache übersetzt. Höhere Programmiersprachen brauchen dieses Zwischenschritt um vom Computer verstanden werden zu können.
+### Interpreter
+Ein Interpreter ist ein Programm, dass Anweisungen in einer Programmiersprache entgegennimmt und verarbeitet. Dabei arbeitet es eine Anweisung nach der anderen ab. Somit wird der Programmcode zur Laufzeit geschrieben. Im Interpreter lassen sich sehr leicht kleine Codestücke testen.
+### Compiler
+Ein Compiler übersetzt Programmcode einer höheren **[Programmiersprache](#programmiersprache)** aus einer Datei in eine, vom Computer lesbare Sprache und speichert diese Übersetzung. Somit wird der Programmcode erst in eine Datei geschrieben, was es ermöglicht komplizierteren Code zu schreiben und zu schreiben. Da der Programmcode in Menschen lesbarer Form gespeichert wird, ist es möglich das Programm auf verschiedenen Systemen und an verschiedenen Zeitpunkten auszuführen.
+## Level 1:
+### Ausdruck
+Ein Ausdruck (alternativ: Expression) ist ein grundlegender Bestandteil jedes Programms. Ein Ausdruck beschreibt einen **[Wert](#wert)** durch das Verknüpfen von **[Funktionen](#funktion)** oder **[Operatoren](#operator)** in Verbindung mit Werten oder **[Variablen](#variable)**. Ein Ausdruck ist dabei immer Bestandteil einer **[Anweisung](#anweisung)**.
+### Anweisung
+Eine Anweisung (alternativ: Befehl) ist grundlegender Bestandteil jedes Programms. Eine Anweisung kann verschiedene **[Ausdrücke(#ausdruck)** miteinander durch Funktionsaufrufe oder **[Operatoren](#operator)** verbinden aber auch einer **[Variable](#variable)** zuweisen. Im Allgemeinen enthält eine Codezeile eine Anweisung.
+### Variable
+Eine Variable zeigt auf einen **[Wert](#wert)**. Eine Variable hat immer einen Namen und einen Wert. In Python gibt es, anders als in anderen **[Programmiersprachen](#programmiersprache)**, keine Variablen mit einem festen **[Typ](#typ)**, das heißt einer Variable kann ein beliebiger Wert, mit einem beliebigen Typen zugeordnet werden. Die Arbeit mit Variablen erleichtert das Schreiben von Code stark. Zum Beispiel ist es möglich komplexe Anweisungen in kleinere Anweisungen zu kapseln und das Ergebnis dieser Anweisungen in Variablen zwischen zu speichern, dadurch wird der Code deutlich lesbarer. Durch geschickte Namenswahl einer Variable lässt sich die Lesbarkeit des Codes weiter erhöhen.
+### Wert
+Ein Wert ist sehr, abstrakt, ein Stück Information und in der Programmierung etwas sehr Grundlegendes. Ein Wert hat in Python immer einen **[Typen](#typ)**, der fest mit dem Wert verankert ist. So ist die `1` immer ein **[Integer](#integer)** und `True` immer ein **[Boolean](#boolean)**.
+### Typ
+Ein Typ wird definiert durch den Wertebereich und die möglichen Operationen, die mit **[Werten](#wert)** dieses Typs möglich sind. Zum Beispiel spezifiziert der Typ **[Integer](#integer)** den Wertebereich der ganzen Zahlen und als Operationen verschiedene Grundrechenarten und Vergleichsoperationen. Neben den Typen, die von Python mitgeliefert werden, ist es auch möglich eigene Typen zu definieren. Von veränderlichen oder dynamischen Typen spricht man, wenn das Ergebnis eines Ausdrucks den Wert verändert und keinen neuen Wert erzeugt.
+### Schlüsselwort
+Schlüsselwörter dienen der Strukturierung des Programmcodes und können daher nicht als Namen für **[Variablen](#variable)** verwendet werden.
+### Integer
+Ein Integer ist ein **[Typ](#typ)**, der von Python mitgeliefert wird und die ganzen Zahlen behandelt. Er bietet als Operationen die Grundrechenarten, sowie die Modulodivision, die Negation und Vergleichsoperationen. Ein Integer wird im Python-Code durch die entsprechende Zahl ausgedrückt.
+### Float
+### String
+Ein String ist ein **[Typ](#typ)**, der von Python mitgeliefert wird. Die **[Werte](#wert)** eines Strings sind Zeichenketten beliebiger Länge. In Python wird ein String durch eine Zeichenkette in doppelten `""` oder einfach `''` Anführungszeichen ausgedrückt.
+### Kommentare
+Kommentare dienen der Lesbarkeit des Codes und werden von **[Compiler](#compiler)** und **[Interpreter](#interpreter)** ignoriert. Kommentare können benutzt werden um den Code zu erklären und sollten nicht nur wiederholen, was der Code tut. Im Grunde sollten Kommentare die Frage nach dem "Warum?" und nicht nach dem "Was?" klären. In Python kann ein Kommentar an einer beliebigen Stelle im Code mit einem "#" bis zu Ende der Zeile eingesetzt werden.
+### Syntax
+### Operator
+## Level 2:
+### Boolean
+Der Boolean ist ein weiterer **[Typ](#typ)** der von Python mitgeliefert wird. Der Wertebereich besteht aus den beiden Werten `True` und `False`. Dabei erbt Boolean von **[Integer](#integer)**, besitzt also neben den Vergleichsoperatoren auch die Operatoren der Grundrechenarten, wobei `True` als 1 und `False` als 0 interpretiert wird. Der Ausdruck in der Definition einer **[if-Bedingung](#bedingung)** oder einer **[while-Schleife](#while-schleife)** wird in einen Boolean übersetzt und ausgewertet.
+### Kommandostruktur
+Eine Kommandostruktur ist essentieller Bestandteil von einer **[Programmiersprache](#programmiersprache)**, da für die meisten Programme Kommandostrukturen wie **[Bedingungen](#bedingung)** und **[Schleifen](#schleife)** zwingend benötigt werden. Eine weitere Kommandostruktur sind **[Funktionen](#funktion)**.
+### Bedingung
+Eine if-Bedingung nimmt einen Ausdruck entgegen, wandelt diesen in einen **[boolschen](#boolean)** **[Wert](#wert)** um und führt daraufhin einen Codeblock aus, wenn der Ausdruck `True`ergibt, andernfalls prüft es eventuelle weitere Bedingungen (`elif`) und oder oder führt den `else` Codeblock aus. Dabei sind alle weitere Bedingungen und der `else` Codeblock optional. Diese **[Kommandostruktur](#kommandostruktur)** dient dazu auf Eingaben oder andere Begebenheiten zu reagieren und ist für viele Algorithmen notwendig.
+## Level 3:
+### Element
+Der Begriff Element wird häufig für **[Werte](#wert)** verwendet, die in einer **[Liste](#liste)** oder einem **[Tupel](#tupel)** gespeichert werden.
+### Index
+Als Index bezeichnet man die Position, bei 0 beginnend, eines **[Elementes](#element)** in einer **[Liste](#liste)** oder einem **[Tupel](#tupel)**.
+### Liste
+Eine Liste ist ein **[Typ](#typ)**, der in Python mitgeliefert wird. In einer Liste können beliebig viele **[Werten](#wert)** mit beliebigen **[Typen](#typ)** gespeichert werden. Dabei kann ein Wert beliebig häufig in der selben Liste auftreten. Ebenso können Werte verschiedenen Typs in der selben Liste gespeichert werden. Häufig werden die Werte in einer Liste als **[Elemente](#element)** bezeichnet. Auf die Elemente einer Liste wird über deren Position in der Liste (ihren **[Index](#index)**) zugegriffen. Die Zählung der Indexe beginnt dabei bei `0`, d.h. das erste Element einer Liste mit `n` Elementen hat den Index `0` und das letzte Element den Index `n-1`. Zu beachten ist, das im Gegensatz zu den Typen **[Integer](#integer)**, **[String](#string)**, **[Float](#float)** und **[Boolean](#boolean)** die Liste ein dynamischer Typ ist.
+### Tupel
+Ein Tupel ist ein **[Typ](#typ)**, der von Python mitgeliefert wird. Er besitzt ähnliche Eigenschaften wie der Typ **Liste**. Der markante Unterschied zwischen diesen
+beiden Typen ist, dass ein Tupel unveränderlich ist, sowohl bezüglich der Anzahl der **[Elemente](#element)** als auch bezüglich der Elemente. Der Zugriff geschieht wie bei dervListe über den **[Index](#index)** eines Elements.
+### Dictionary
+Ein Dictionary ist ein **[Typ](#typ)**, der von Python mitgeliefert wird. Es ist ebenso wie die **[Liste](#liste)** oder das **[Tupel](#tupel)**, ein iterativer Typ. Im Gegensatz zu diesen beiden Typen wird auf ein **[Element](#element)**, dass in einem Dictionary gespeichert wird nicht über einen **[Index](#index)**, sondern über ein Schlüssel zugegriffen.
+### Schleife
+Eine Schleife ist eine **[Kommandostruktur](#kommandostruktur)** und dient dazu eine Folge von Anweisungen wiederholt auszuführen, bis eine **[Bedingung](#bedingung)** erreicht ist. Diese Bedingung nennt man Abbruchbedingung. In Python gibt es zwei Arten von Schleifen, die in ihren Möglichkeiten gleichwertig sind, sie unterscheiden sich jedoch in der **[Syntax](#syntax)**, und Handhabung.
+#### while Schleife
+Eine while-Schleife ist eine **[Schleife](#schleife)** , die einen **[boolschen](#boolean)** Ausdruck entgegennimmt, diesen auf Wahrheit prüft und dann einen Codeblock wiederholt ausführt. Nach jedem Durchlauf wird der boolsche Ausdruck erneut geprüft. Sollte der Ausdruck nicht mehr den **[Wert](#wert)** `True`ergeben, wird das Durchlaufen der Schleife beendet.
+#### for Schleife
+Eine for-Schleife ist eine **[Schleife](#schleife)** die ein iterierbares **[Objekt](#objekt)** durchläuft. Beispielsweise lassen sich somit **[Strings](#string)**, **[Listen](#liste)**, **[Tupel](#tupel)** oder **[Dictionaries](#dictionary)** durchlaufen. Durch die `range()` **[Funktion](#funktion)** lassen sich sehr Zählschleifen implementieren.
+## Level 5:
+### Funktion
+
+### Rekursion
+
+## Level 6:
+### Objekt
+
+### Klasse
+
+### Modul
+
+### Instanz
+
+### Methode
+
+### Attribut
+
+## Level 7:
+### Iterator
+
+### Generator
+
+### Decorator
+
+## Unsortiert:
+### Exception
+
+### Syntaxfehler
diff --git a/Level_00/README.md b/Level_00/README.md
new file mode 100644
index 0000000..62787cb
--- /dev/null
+++ b/Level_00/README.md
@@ -0,0 +1,46 @@
+# Level 0:
+
+## Was ist ein Programm?
+
+
+## Was ist eine Programmiersprache?
+Eine Programmiersprache dient dazu, dass ein Benutzer dem Computer durch Befehle (commands) und eine Syntax,
+einen Algorithmus (oder Aufgaben) ausführen lässt. Die Programmiersprache ist eine formale Sprache, die
+es ermöglicht, dem Computer präzise zu kommunizieren, was er tun soll. Allerdings ist die Programmiersprache
+nur ein Zwischenschritt, da der Computer die Programmiersprache nochmal in eine Maschinensprache übersetzt.
+Da diese Maschinensprache allerdings für den Menschen schwer lesbar ist, wird eine Programmiersprache wie
+Python, Java, oder C benutzt. Es gibt viele verschiedene Programmiersprachen, die jedoch teilweise aufeinander
+aufbauen, trotzdem kann man Programmiersprachen klassifizieren (Typisierung, Art der Ausführung, Syntax).
+
+Zum Beispiel ist Python eine stark und dynamisch typisierte Sprache, die sowohl im Interpreter als auch als Skript
+ausgeführt werden kann. Sie wird meistens objektorientiert und imperativ verwendet. Was genau diese Attribute bedeuten, wird später noch erläutert.
+
+## Was genau ist Python?
+Python ist eine Programmiersprache, die darauf ausgerichtet wurde, leicht benutzbar zu sein. Um dieses Ziel zu
+erreichen verzichtet Python auf gewisse Eigenheiten anderer Programmiersprachen, die teilweise oft schwer
+verständlich sind und häufig gerade Anfänger verwirren. Das bedeutet aber auch, dass andere Programmiersprachen
+in bestimmten Anwendungsfällen besser geeignet sind als Python, weil sie zum Beispiel darauf optimiert wurden.
+Trotzdem ist es sinnvoll, um eine Programmiersprache zu lernen, mit Python anzufangen, da zwischen den vielen
+Programmiersprachen große Ähnlichkeiten bestehen. Sollte man eine weitere Sprache lernen wollen, versteht
+man schon das Grundgerüst und muss sich nur noch mit der Syntax und den Eigenheiten der neuen Sprache
+auseinandersetzen.
+
+## Wie programmiere ich mit Python?
+Um mit Python zu programmieren, gibt es grundsätzlich zwei Möglichkeiten:
+1. Ich führe in der Konsole den Interpreter aus und gebe live meine Befehle ein.
+2. Ich schreibe mein Programm in eine Textdatei mit der Endung .py und rufe in der
+ Konsole die Textdatei mit Python auf.
+
+
+Die erste Methode ist sehr praktisch, um kleine Codestücke zu testen oder kurze Programme auszuführen, ist jedoch
+unkomfortabel, um große Programme zu schreiben, da das Programm nach Beenden des Interpreters weg ist.
+Die zweite Methode ermöglicht es, große Programme zu schreiben, diese abzuspeichern und zu verteilen. Es ermöglicht
+auch langfristiges Arbeiten an einem Programm.
+
+Für beide Methoden muss allerdings Python auf dem Betriebssystem installiert sein - sowohl auf dem Betriebssystem,
+das ein Python-Programm ausführen soll, als auch das Betriebssystem, auf dem ein Python-Programm entwickelt wird.
+Wir helfen euch gerne bei der Installation von Python auf Linux oder Windows. Solltet ihr Python selber
+installieren, beachtet bitte, dass wir Python 3.x benutzen, da dies die aktuelle Version ist.
+
+## Wie führe ich Python aus?
+siehe "Wie programmiere ich mit Python?"
diff --git a/Level_01/Beispielcode/calculator01.py b/Level_01/Beispielcode/calculator01.py
index 8fbc60b..104d120 100644
--- a/Level_01/Beispielcode/calculator01.py
+++ b/Level_01/Beispielcode/calculator01.py
@@ -1,4 +1,4 @@
-u"""
+"""
Das folgende Programm soll eine einfacher Taschenrechner sein.
Das Programm nimmt zwei Zahlen entgegen und führt daraufhin einige Berechnungen
@@ -29,8 +29,8 @@
pro_xy = x * y # Produkt
quo_xy = x / y # Quotient
quo_yx = y / x # Quotient
-mod_xy = x % y # Modulo Divison
-mod_yx = y % x # Modulo Divison
+mod_xy = x % y # Modulo Division
+mod_yx = y % x # Modulo Division
x_sqrt = math.sqrt(x) # Quadratwurzel
y_sqrt = math.sqrt(y) # Quadratwurzel
diff --git a/Level_01/Beispielcode/greeting.py b/Level_01/Beispielcode/greeting.py
new file mode 100644
index 0000000..3734bc9
--- /dev/null
+++ b/Level_01/Beispielcode/greeting.py
@@ -0,0 +1,7 @@
+"""
+Das Programm soll den Benutzer mit einer Grußnachricht begrüßen.
+"""
+
+username = input("Please input your name: ") # Eingabe des Nutzernamens
+greeting = "Hello " + username # Verarbeitung des Nutzernamens
+print(greeting) # Ausgabe der Grußbotschaft
\ No newline at end of file
diff --git a/Level_01/Ein_Ausgabe.py b/Level_01/Ein_Ausgabe.py
deleted file mode 100755
index ff4efb9..0000000
--- a/Level_01/Ein_Ausgabe.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env python3
-
-from getpass import getpass # hilfreich für Passwortabfragen
-
-
-## Ausgabe
-
-print("Dieser Text wird ausgegeben.")
-
-# Man kann auch mehrere Dinge gleichzeitig ausgeben.
-print(1, 2, "Apfel", "Birne")
-
-# Man kann auch Variablen ausgeben:
-x = 5 # type: int
-print(x)
-text = "Hallo, Welt!" # type: str
-print(text)
-print(x, text)
-
-
-## Eingabe
-
-print("Bitte etwas eingeben:")
-eingabe = input() # type: str
-
-print("Die Eingabe war: ")
-print(eingabe)
-
-# Das geht natürlich auch etwas kürzer:
-eingabe = input("Bitte etwas eingeben: ")
-print("Die Eingabe war:", eingabe)
-
-## Eingabe ohne die Eingabe anzuzeigen:
-passwort = getpass() # type: str # Standardprompt: "Password: "
-print("Eingabe:", passwort)
-
-passwort = getpass("Bitte Passwort eingeben: ")
-print("Eingabe:", passwort)
diff --git a/Level_01/Level_1.ipynb b/Level_01/Level_1.ipynb
index bb1d409..6436628 100644
--- a/Level_01/Level_1.ipynb
+++ b/Level_01/Level_1.ipynb
@@ -9,14 +9,22 @@
},
"source": [
"# Level 1\n",
- "In diesem Level werden wir unsere ersten Zeilen Python kennenlernen. Wir werden lernen, was ein integer, ein float, ein string ist, wie wir mit Python Text ausgeben und einlesen können, erste Berechnungen anstellen können, die Ergebnisse von Berechnungen in Variablen speichern und wie wir unseren Code kommentieren können."
+ "\n",
+ "In diesem Level lernst du die Grundlagen des Programmierens kennen. Du lernst unter anderem:\n",
+ "\n",
+ "* einfache mathematischen Operationen durchzuführen\n",
+ "* die Datentypen `int`, `float` und `string` kennen\n",
+ "* was eine Variable ist und wie du Werte darin speicherst\n",
+ "* wie du mit Hilfe der `input()` Funktion Eingaben aus der Konsole entgegen nehmen kannst"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "## Ausgabe"
+ "## Ausgabe\n",
+ "\n",
+ "Die `print()`-Funktion hast du ja bereits in Level 0 kennengelernt. Diese Funktion gibt die ihr übergebenen Werte in der Konsole aus."
]
},
{
@@ -33,31 +41,36 @@
}
],
"source": [
- "# Für die Standardausgabe benutzen wir die print() Funktion\n",
+ "# Ein einfaches Beispiel für die Verwendung der print Funktion zum\n",
+ "# Ausgeben eines strings\n",
"print(\"Hallo Welt!\")"
]
},
{
"cell_type": "code",
- "execution_count": 29,
+ "execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "foo bar\n"
+ "foo bar\n",
+ "pi 3.14\n"
]
}
],
"source": [
- "# Wir können mit Kommata getrennt auch mehrere Werte ausgeben:\n",
- "print(\"foo\", \"bar\")"
+ "# Du kannst auch mehrere Werte ausgeben lassen, wenn du diese mit Kommata trennst\n",
+ "print(\"foo\", \"bar\")\n",
+ "\n",
+ "# Dabei müssen die Werte nicht vom selben Typ sein\n",
+ "print(\"pi\", 3.14)"
]
},
{
"cell_type": "code",
- "execution_count": 30,
+ "execution_count": 3,
"metadata": {},
"outputs": [
{
@@ -80,46 +93,52 @@
}
],
"source": [
- "# Mit der help() Funktionen zeigen wir uns\n",
- "# die Hilfe der print() Funktion an:\n",
+ "# Mit der help() Funktion kannst du dir die Hilfe zu einem Objekt anzeigen lassen\n",
"help(print)"
]
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Die Hilfe der `print()` liefert dir wichtige Informationen darüber, wie du die Funktion benutzen kannst. So kannst du einen Separator angeben um zu definieren, welcher string zwischen zwei angegebenen Werten ausgegeben werden soll. Gibst du diesen Separator nicht explizit an handelt es sich um ein Leerzeichen. Ebenfalls kannst du einen end string angeben, der definiert, welcher string am Ende der Ausgabe ausgegeben werden soll. Gibst du diesen end string nicht explizit an, handelt es sich um `\\n`, das Steuerzeichen für einen Zeilenumbruch."
+ ]
+ },
{
"cell_type": "code",
- "execution_count": 31,
+ "execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "foo#bar\n"
+ "Apfel - Birne - Banane\n"
]
}
],
"source": [
- "# Ausgabe mit Seperatoren:\n",
- "print(\"foo\", \"bar\", sep=\"#\")"
+ "# Ausgabe mit einem definiertem Separator\n",
+ "print(\"Apfel\", \"Birne\", \"Banane\", sep=\" - \")"
]
},
{
"cell_type": "code",
- "execution_count": 32,
+ "execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "foo bar##\n",
+ "foo bar\n",
"test\n"
]
}
],
"source": [
- "# Ausgabe mit end-string:\n",
- "print(\"foo\", \"bar\", end=\"##\\n\")\n",
+ "# Ausgabe mit einem definiertem end-string:\n",
+ "print(\"foo\", \"bar\", end=\"\\n\")\n",
"print(\"test\")"
]
},
@@ -127,9 +146,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "## Einfache Operationen\n",
- "Im Python Interpreter werden Kommandos zeilenweise eingegeben und vom Interpreter zeilenweise interpretiert und ausgeführt. Der Interpreter gibt dabei immer das Ergebnis (genauer den Rückgabewert des Ausdrucks) zurück.\n",
- "Das bedeutet, wir können den Interpreter benutzen um erste Berechnungen durchzuführen und die mathematischen Operatoren kennenlernen."
+ "## Ganze Zahlen und mathematische Operationen\n",
+ "\n",
+ "Bisher hast du gelernt, wie du Text in der Konsole ausgeben kannst. Im folgenden geht es darum, wie du Berechnungen durchführen kannst. Du kannst einfache mathematische Operationen direkt im Interpreter durchführen. Gib dafür im Interpreter einfach deinen Term ein."
]
},
{
@@ -156,13 +175,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Genauer betrachtet besteht die Zeile `4 + 34` aus zwei _Literalen_ (`4` und `34`) und einem _Operator_ (`+`), die kombiniert den Ausdruck ergeben. Ein Literal ist die direkte Darstellung eines Wertes. Operatoren verknüpfen Werte und geben Werte zurück.\n",
- "Bei den Werten im obigen Beispiel handelt es sich um Werte vom Typ __integer__. Diese stellen ganze Zahlen dar."
+ "Die obige Zeile besteht aus einem Literal (englisch: \"literal\") `4` einem Operator (englisch: operator) `+` und einem weiteren Literal `34`. Zusammen bilden diese beiden Literale und der Operator einen Ausdruck (englisch: expression). Ein Literal ist die direkte Darstellung eines Wertes. Ein Operator wird auf einen oder mehrere Werte angewandt und gibt dabei einen Wert zurück. Dabei ist es wichtig zu beachten, dass die Werte definieren wie der Operator mit ihnen umgeht und nicht umgekehrt.\n",
+ "\n",
+ "Die beiden Literale in dem obigen Beispiel haben den Typ `integer`. Der integer ist ein Datentyp, welcher die Menge der ganzen Zahlen implementiert. Ganze Zahlen sind sowohl positive als auch negative Zahlen ohne Nachkommastellen. Für diesen Datentyp sind verschiedene Operatoren definiert, diese bilden unter anderem die mathematischen Grundrechenarten ab."
]
},
{
"cell_type": "code",
- "execution_count": 34,
+ "execution_count": 9,
"metadata": {},
"outputs": [
{
@@ -175,21 +195,38 @@
"1\n",
"1\n",
"1.5\n",
- "16\n",
- "8\n",
- "2\n",
- "4\n"
+ "16\n"
]
}
],
"source": [
+ "# Grundrechenarten\n",
"print(3 + 4) # Addition\n",
"print(4 - 6) # Subtraktion\n",
"print(3 * 7) # Multiplikation\n",
"print(3 // 2) # Ganzzahlige Division\n",
"print(3 % 2) # Division mit Rest\n",
"print(3 / 2) # Division\n",
- "print(2 ** 4) # Potenz, alternativ pow(2, 4)\n",
+ "print(2 ** 4) # Potenz, alternativ pow(2, 4)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "8\n",
+ "2\n",
+ "4\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Bitweise Operationen\n",
"print(4 << 1) # Bitshift nach links, alternativ 4 * (2 ** 1)\n",
"print(4 >> 1) # Bitshift nach rechts, alternativ 4 // (2 ** 1)\n",
"print(5 ^ 1) # bitweises XOR"
@@ -199,57 +236,69 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Oben sind die wichtigsten Operatoren für Werte des Integer Typs aufgelistet. Bemerkenswert ist, dass es drei Arten der Divison gibt: die ganzzahlige Division, die (ganzzahlige) Division mit Rest und die \"normale\" Division. Die ganzzahlige Division liefert ein abgerundetes Ergebnis als Integer, die Division mit Rest liefert den Rest der ganzzahligen Divison und die \"normale\" Division liefert einen Wert des Typen __float__."
+ "Beachte, dass es drei Arten der Division gibt:\n",
+ "\n",
+ "* die ganzzahlige Division (`3 / 2`) liefert stets einen integer als Ergebnis, wobei nicht gerundet wird, weshalb es zu Genauigkeitsverlust kommen kann\n",
+ "* die module Division (`3 % 2`) liefert den Rest einer ganzzahligen Division\n",
+ "* die \"normale\" Division (`3 / 2`) liefert als Ergebnis eine Fließkommazahl (englisch: float)\n",
+ "\n",
+ "Im wiki findest du [weitergehende Informationen zum Thema \"Operatoren\"](https://github.com/pythonfoo/pythonfooLite/wiki/Operatoren)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Fließkommazahlen\n",
+ "\n",
+ "Wie bereits erwähnt implementiert der Datentyp `float` Fließkommazahlen. Diese können benutzt werden um mit Dezimalzahlen und ihren Nachkommastellen rechnen zu können. Ebenso wie für den `integer`-Datentyp sind auch für Fließkommazahlen die mathematischen Operatoren definiert. Du kannst auch in einem Ausdruck ganze Zahlen, Fließkommazahlen und verschiedene Operatoren miteinander verknüpfen. Dabei wird das Ergebnis des Ausdrucks stets eine Fließkommazahl sein, um Genauigkeitsverluste zu verhindern."
]
},
{
"cell_type": "code",
- "execution_count": 35,
+ "execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "8.3\n"
+ "rough estimate for circle area of radius 5\n",
+ "78.525\n"
]
}
],
"source": [
- "print(4.5 + 3.8)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Ein float repräsentiert Fließkommazahlen. Dieselben Operatoren, die oben auf Integer angewandt wurden, können auch auf floats angewendet werden. Wichtig ist, dass dabei das Ergebnis stets vom Typ float ist."
+ "print(\"rough estimate for circle area of radius 5\")\n",
+ "print(5 ** 2 * 3.141)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "Zum Umwandeln bieten die Typen Funktionen an, so kann ein Objekt mit der `int()` Funktion in einen integer und mit der`float()` Funktion in einen float umgewandelt werden. Beim Umwandeln eines integers in einen float gehen allerdings etwaige Nachkommastellen verloren."
+ "Im Allgemeinen bietet jeder Datentyp eine Funktion um beliebige Werte (falls möglich) in diesen Typen umzuwandeln. So kann die `int()`-Funktion benutzt werden um einen Wert (beispielsweise eine Fließkommazahl) in eine ganze Zahl umzuwandeln. Bei dieser Umwandlung kommt es zu Genauigkeitsverlust. Die `float()`-Funktion hingegen kannst du dafür benutzen um aus einem beliebigen Wert eine Fließkommazahl zu machen."
]
},
{
"cell_type": "code",
- "execution_count": 36,
+ "execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "3\n",
- "4.0\n"
+ "5\n",
+ "2.0\n",
+ "15\n"
]
}
],
"source": [
- "print(int(3.5))\n",
- "print(float(4))"
+ "print(int(3.5) + 2)\n",
+ "print(float(4) / 2)\n",
+ "print(int(\"5\") * int(\"3\"))"
]
},
{
@@ -259,51 +308,62 @@
"## Variablen\n",
"> Readability counts. - Zen of Python\n",
"\n",
- "Variablen werden benutzt, um Werte für die spätere Wiederbenutzung zu speichern. Dabei zeigt die Variable lediglich auf einen Wert. Eine Variable hat dabei keinen festen Typ, nur die Werte"
+ "Bisher musstest du die Ausdrücke, welche du ausgeben wolltest in einen Aufruf der `print()`-Funktion einbetten oder direkt im Interpreter eingeben. Gerade bei komplexeren Berechnungen ist dies nicht länger praktikabel. Die Benutzung von Variablen löst dieses und noch viele weitere Probleme.\n",
+ "\n",
+ "Eine Variable speichert einen Wert beliebigen Typs. Auf diesen gespeicherten Wert kann bei Bedarf beliebig oft zugegriffen werden. Die Variable dient insofern als Alias für den ihr gespeicherten Wert.\n",
+ "\n",
+ "Ein Wert wird in einer Variable gespeichert, indem man einem Variablennamen dieses Wert zuweist, weshalb dieser Vorgang \"Zuweisung\" genannt wird. Beachte bei der Vergabe von Variablennamen die Groß- und Kleinschreibung. Die Variable `pi` ist eine andere als die Variable `Pi` oder `PI`. Du solltest deine Variablennamen stets so wählen, dass aus dem Namen klar die beabsichtigte Bedeutung oder Rolle des gespeicherten Wertes hervorgeht. Zahlen können in Variablennamen benutzt werden, allerdings nicht als erstes Zeichen."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "radius = 5\n",
+ "pi = 3.14"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Sobald du einen Wert in einer Variablen gespeichert hast, kannst du auf diesen Wert innerhalb von Ausdrücken mit Hilfe der Variable zugreifen."
]
},
{
"cell_type": "code",
- "execution_count": 37,
+ "execution_count": 17,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "4 12\n",
- "2.99 0.49\n",
- "\n",
- "ham: 11.96\n",
- "egg: 5.88\n",
- "sum: 17.84\n"
+ "78.525\n"
]
}
],
"source": [
- "ham = 4\n",
- "egg = 12\n",
- "ham_price = 2.99\n",
- "egg_price = 0.49\n",
- "print(ham, egg)\n",
- "print(ham_price, egg_price)\n",
- "print()\n",
- "print(\"ham: \", ham * ham_price)\n",
- "print(\"egg: \", egg * egg_price)\n",
- "summ = ham * ham_price + egg * egg_price\n",
- "print(\"sum: \", summ)"
+ "radius = 5\n",
+ "pi = 3.141\n",
+ "area = pi * radius ** 2\n",
+ "print(area)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- " Bei der Benennung von Variablen sollte darauf geachtet werden, kurze aber verständliche Variablennamen zu benutzen, da so klar ist wozu die Variable benutzt wird. Auf keinen Fall sollten Variablennamen wie `l`, `O` oder `I` benutzt werden, da diese, je nach Schriftart, wie `0` oder `1` aussehen können."
+ "## type()-Funktion\n",
+ "\n",
+ "Falls du dir mal nicht sicher bist, was dür einen Typ von Wert eine Variable enthält, kannst du dir den Typen eines beliebigen Wertes oder Ausdrucks mit Hilfe der `type()`-Funktion anzeigen lassen."
]
},
{
"cell_type": "code",
- "execution_count": 38,
+ "execution_count": 18,
"metadata": {
"scrolled": false
},
@@ -314,6 +374,7 @@
"text": [
"\n",
"\n",
+ "\n",
"\n"
]
}
@@ -322,7 +383,10 @@
"# den Typen eines Wertes können wir mit type() bestimmt werden:\n",
"print(type(\"a\"))\n",
"print(type(2))\n",
- "print(type(4.8))"
+ "print(type(4.8))\n",
+ "\n",
+ "# auch die Typ-Bestimmung von Ausdrücken ist möglich\n",
+ "print(type(3.14 * 10))"
]
},
{
@@ -334,7 +398,7 @@
"1. Eine Variable kann auf Werte verschiedenen Typs zeigen.\n",
"2. Jedes Objekt hat einen Typ.\n",
"\n",
- "Bei jeder neuen Zuweisung wird der Wert einer Variable überschrieben, dabei kann sich der Typ des Werts ändern."
+ "Sobald du einer Variable, der du bereits einen Wert zugewiesen hast, einen neuen Wert zuweist, wird der ursprüngliche Wert überschrieben und steht dir fortan nicht mehr zur Verfügung. Bei dieser Neuzuweisung ist es egal, welche Typen alter und neuer Wert haben."
]
},
{
@@ -363,7 +427,12 @@
"metadata": {},
"source": [
"## Strings\n",
- "Ein String ist eine Zeichenkette und wird repräsentiert Text. Ein String kann mit `\"\"` oder `''` definiert werden."
+ "Ein String ist eine Zeichenkette und wird repräsentiert Text.\n",
+ "Diese Zeichenkette kann ein Wort, einen Satz, einen Text, eine Seite oder sogar\n",
+ "ein Buch enthalten, wichtig ist nur, dass in einem String Text enthalten ist. Dies macht den String zu eine sehr\n",
+ "variablen Typen. Python unterstützt Unicode, was bedeutet, dass auch Sonderzeichen und Umlaute in einem String benutzt werden können.\n",
+ "\n",
+ "Ein String kann mit `\"\"` oder `''` definiert werden."
]
},
{
@@ -504,12 +573,135 @@
"print(s)"
]
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Die \"umgekehrte\" Operation geht natürlich auch, aber wir können nicht einfach jeden String in einen Integer umwandeln:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "ValueError",
+ "evalue": "invalid literal for int() with base 10: 'abcdef'",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
+ "\u001b[0;32m/tmp/ipykernel_287561/681081256.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"5\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"abcdef\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
+ "\u001b[0;31mValueError\u001b[0m: invalid literal for int() with base 10: 'abcdef'"
+ ]
+ }
+ ],
+ "source": [
+ "x = int(\"5\")\n",
+ "int(\"abcdef\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Die Fehlermeldung weist uns auf ein ganz spannendes Feature hin: Wir können die Basis angeben.\n",
+ "Bisher haben wir (standardmäßig) Dezimalzahlen verwendet (Basis 10). Wir können aber z.B. auch Hexadezimalzahlen (Basis 16) verwenden:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "11259375\n",
+ "0xabcdef\n"
+ ]
+ }
+ ],
+ "source": [
+ "x = int(\"abcdef\", 16)\n",
+ "print(x)\n",
+ "print(hex(x))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Analog zu `hex` existieren auch `bin` (binär, Basis 2) und `oct` (oktal, Basis 8).\n",
+ "Diese drei sind so häufig, dass sich auch Literale damit formulieren lassen (`0x` für hexadezimal, `0b` für binär, `0o` für oktal):"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "0o777\n",
+ "0b1011\n",
+ "0xc0ffee\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(oct(0o777))\n",
+ "print(bin(0b1011))\n",
+ "print(hex(0xc0ffee))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Wir können mit Strings noch viel mehr tun. Ein paar Funktionen zeigen wir hier, mehr folgen später:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "LOREM IPSUM\n",
+ "lorem ipsum\n",
+ "Lorem ipsum\n"
+ ]
+ }
+ ],
+ "source": [
+ "t = \"loREm ipSUm\"\n",
+ "\n",
+ "# Alle Buchstaben groß:\n",
+ "print(t.upper())\n",
+ "\n",
+ "# Alle Buchstaben klein:\n",
+ "print(t.lower())\n",
+ "\n",
+ "# Den ersten Buchstaben groß:\n",
+ "print(t.capitalize())"
+ ]
+ },
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Eingabe\n",
- "Die `input()`Funktion wird benutzt um Eingaben über die Standardeingabe zu erhalten. Dabei liefert die `input()`Funktion immer einen string."
+ "Die `input()`Funktion wird benutzt um Eingaben über die Standardeingabe zu erhalten. Dabei liefert die `input()`-Funktion immer einen String zurück.\n",
+ "\n",
+ "Da die Eingabe fast immer weiterverarbeitet werden soll, bietet es sich an, die Rückgabe in einer Variable zu speichern."
]
},
{
@@ -535,6 +727,32 @@
"print(type(eingabe))"
]
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Wenn wir statt `input()` `getpass()` verwenden, dann verhält es sich quasi genau so, nur die Eingabe wird nicht angezeigt:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "geheim\n"
+ ]
+ }
+ ],
+ "source": [
+ "from getpass import getpass\n",
+ "password = getpass(\"Passwort: \")\n",
+ "print(password)"
+ ]
+ },
{
"cell_type": "markdown",
"metadata": {},
@@ -654,18 +872,11 @@
"source": [
"import this"
]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
}
],
"metadata": {
"kernelspec": {
- "display_name": "Python 3",
+ "display_name": "Python 3.10.6 64-bit",
"language": "python",
"name": "python3"
},
@@ -679,7 +890,12 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.6.7"
+ "version": "3.10.6"
+ },
+ "vscode": {
+ "interpreter": {
+ "hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1"
+ }
}
},
"nbformat": 4,
diff --git a/Level_01/Aufgaben/addierer.py "b/Level_01/L\303\266sungen/addierer.py"
similarity index 62%
rename from Level_01/Aufgaben/addierer.py
rename to "Level_01/L\303\266sungen/addierer.py"
index 63e952f..d902178 100755
--- a/Level_01/Aufgaben/addierer.py
+++ "b/Level_01/L\303\266sungen/addierer.py"
@@ -1,8 +1,8 @@
#!/usr/bin/env python3
-# Dies ist eine Beispielslösung für die Aufgabe 1 aus Level 1:
+# Dies ist eine Beispiellösung für die Aufgabe 1 aus Level 1:
-# 1. Schreibe ein Programm, das die Zahlen 23 und 42 addiert:
+# 1. Schreibe ein Programm, das die Zahlen 23 und 42 addiert:
print(23 + 42) # Erfüllt die Anforderung komplett.
@@ -15,12 +15,12 @@
print(a + b)
-# 3. Ändere das Programm so ab, dass die Zahlen vom Benutzer eingegeben werden können:
+# 3. Ändere dein Programm so ab, dass die Zahlen interaktiv eingegeben werden können:
inp_a = input("Bitte geben Sie den ersten Summanden ein: ") # type: str
inp_b = input("Bitte geben Sie den zweiten Summanden ein: ")
# Da input() immer einen String zurückgibt muss dieser in einen Integer umgewandelt werden,
-# dabei ensteht eine Fehlerquelle, da ein Fehler auftritt, wenn der Benutzer keine gültige
+# dabei entsteht eine Fehlerquelle, da ein Fehler auftritt, wenn der Benutzer keine gültige
# Zahl eingibt.
a = int(inp_a)
b = int(inp_b)
diff --git a/Level_01/Aufgaben/print_string.py "b/Level_01/L\303\266sungen/print_string.py"
similarity index 70%
rename from Level_01/Aufgaben/print_string.py
rename to "Level_01/L\303\266sungen/print_string.py"
index 7e45ba0..bdda207 100755
--- a/Level_01/Aufgaben/print_string.py
+++ "b/Level_01/L\303\266sungen/print_string.py"
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
-# Dies ist eine Beispielslösung für die Aufgabe 2 aus Level 1:
+# Dies ist eine Beispiellösung für die Aufgabe 2 aus Level 1:
# 1. Schreibe ein Programm, das den String "foo" ausgibt
print("foo") # Sehr ähnlich dem "hello world" Code
@@ -18,14 +18,14 @@
print(5*"foo")
-# 4. Ändere das Programm so ab, dass der Benutzer eingeben kann welcher String 5 mal in der
-# selben Zeile ausgegeben werden soll.
+# 4. Ändere das Programm so ab, dass interaktiv eingegeben werden kann,
+# welcher String 5 mal in der selben Zeile ausgegeben werden soll.
string = input("Welcher String soll ausgegeben werden? ")
print(5*string)
-# 5. Ändere das Programm so ab, dass der Benutzer angeben kann, wie oft der angegebene String
-# ausgegeben werden soll.
+# 5. Ändere das Programm so ab, dass interaktiv eingegeben werden kann,
+# wie oft der angegebene String ausgegeben werden soll.
string = input("Welcher String soll ausgegeben werden? ")
wiederholung = input("Wie oft soll '" + string + "' ausgegeben werden? ")
# Hier wird in dem Aufruf von input() ein String zusammen gebaut
diff --git a/Level_01/README.md b/Level_01/README.md
new file mode 100644
index 0000000..dc1ce36
--- /dev/null
+++ b/Level_01/README.md
@@ -0,0 +1,30 @@
+# Level 1
+
+In Level 0 hast du Python installiert und mit `hello_world.py` dein erstes Python-Programm geschrieben.
+In Level 1 geht es unter anderem darum zwei grundlegende Funktionen für die Ein- und Ausgabe kennenzulernen, die Funktionen `input()` und `print()`.
+Ebenso wirst du in diesem Level die einfachen Datentypen `int`, `float` und `str` kennenlernen.
+Du wirst lernen Werte in Variablen zu speichern und auf diese Variablen später zuzugreifen.
+
+Um mit diesem Level zu starten, navigiere zur [Level1.ipynb](https://github.com/pythonfoo/pythonfooLite/blob/master/Level_01/Level_1.ipynb) Datei.
+
+## Aufgaben
+
+Um deine erworbenen Kenntnisse anwenden und testen zu können, haben wir für dieses Level ein paar Aufgaben erstellt. Die Aufgabenstellungen sind dabei an den Inhalt des Levels angepasst. Falls du dennoch Probleme oder Fragen zu diesem Level oder den Aufgaben hast, kannst du dich gerne an uns wenden. Jede Aufgabe hat eine eindeutige Nummer zur Identifizierung und meistens auch einen Namen.
+
+### 1.1 addierer.py
+
+In dieser Aufgabe geht es darum ein Programm zu schreiben, welches zwei ganze Zahlen addiert. Diese Aufgabe ist dabei in Teilaufgaben gegliedert, wobei folgende Teilaufgaben die bestehenden Anforderungen erweitern. In der ersten Aufgabe erstellst du also einen Prototypen, dessen Funktionalität du Schritt für Schritt erweiterst.
+
+1. Schreibe ein Programm, das die Zahlen 23 und 42 addiert und das Ergebnis ausgibt.
+2. Ändere dein Programm so ab, dass die Zahlen in zwei Variablen gespeichert werden.
+3. Ändere dein Programm so ab, dass die Zahlen interaktiv eingegeben werden können.
+
+### 1.2 print_string.py
+
+Diese Aufgabe beschäftigt sich mit der `print()` Funktion. Wie in Aufgabe **1.1** wird auch hier mit jeder Teilaufgabe das bestehende Programm erweitert.
+
+1. Schreibe ein Programm, das den String "foo" ausgibt
+2. Ändere das Programm so ab, dass der String "foo" 5 mal ausgegeben wird.
+3. Ändere das Programm so ab, dass der String 5 mal in der selben Zeile ausgegeben wird.
+4. Ändere das Programm so ab, dass interaktiv eingegeben werden kann, welcher String 5 mal in der selben Zeile ausgegeben werden soll.
+5. Ändere das Programm so ab, dass interaktiv eingegeben werden kann, wie oft der angegebene String ausgegeben werden soll.
diff --git a/Level_01/Aufgaben/buggy01.py b/Level_01/buggy01.py
similarity index 100%
rename from Level_01/Aufgaben/buggy01.py
rename to Level_01/buggy01.py
diff --git a/Level_01/integer.py b/Level_01/integer.py
deleted file mode 100644
index 50e6cde..0000000
--- a/Level_01/integer.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env python3
-
-x = 5 # type: int
-z = -3
-basis = 2
-exponent = 5
-print(x, "in binär:", bin(x), "in hexadezimal:", hex(x))
-
-# Daten andere Typen in Integer umwandeln
-# Achtung: Dies kann fehlschlagen!
-y = int("6")
-y = int("110", 2) # 110 ist 6 in binär.
-
-# Operatoren auf Integer anwenden:
-# (für mehr Informationen siehe die Wiki-Seite zu Operatoren)
-summe = x + y
-produkt = x * z
-quotient = 9 / 3 # type: float
-differenz = x - z
-potenz = pow(basis, exponent) # type: int
-# Oder: basis ** exponent, Falsch ist basis ^ exponent
diff --git a/Level_01/strings.py b/Level_01/strings.py
deleted file mode 100644
index 2013f1e..0000000
--- a/Level_01/strings.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env python3
-
-# Zur Bedeutung von `print` siehe Ein_Ausgabe.py
-
-ein = "Dies ist ein einzeiliger String." # type: str
-print(ein)
-
-mehr = """
-Dies ist ein mehrzeiliger String.
-
- Leerzeilen, Zeilenumbrüche und Einrückung
- werden mit in den String übernommen.
-""" # type: str
-
-print(mehr)
-
-f = "foo"
-b = "bar"
-
-# Operatoren auf Strings anwenden:
-# (für mehr Informationen siehe die Wiki-Seite zu Operatoren)
-print(f + b)
-print(5 * f)
-print(5 * (f + " "))
-
-# Daten anderer Typen in Strings umwandeln:
-s = str(5)
-print(s)
-
-# Groß- und Kleinschreibung:
-h = "haMSter"
-
-# Alle Buchstaben groß:
-print(h.upper()) # OUT: HAMSTER
-
-# Alle Buchstaben klein:
-print(h.lower()) # OUT: hamster
-
-# Den ersten Buchstaben groß:
-print(h.capitalize()) # OUT: Hamster
-
-# Länge
-print(len(h)) # OUT: 7
diff --git a/Level_02/Beispielcode/calculator02.py b/Level_02/Beispielcode/calculator02_if.py
similarity index 91%
rename from Level_02/Beispielcode/calculator02.py
rename to Level_02/Beispielcode/calculator02_if.py
index e25eb40..de9abf0 100644
--- a/Level_02/Beispielcode/calculator02.py
+++ b/Level_02/Beispielcode/calculator02_if.py
@@ -1,11 +1,11 @@
-u"""
+"""
Das folgende Programm ist ein einfacher Taschenrechner.
Nach dem Eingeben zweier Zahlen kann eine Operation ausgewählt werden.
"""
# Für die Berechnung der Quadratwurzel wird die math Bibliothek benötigt,
-# desweiteren wird zum vorzeitigen Beenden die sys Bibliothek benötigt.
+# des Weiteren wird zum vorzeitigen Beenden die sys Bibliothek benötigt.
import math
import sys
@@ -56,8 +56,8 @@
print("y / x =", y / x) # Quotient
elif choice == "5":
- print("x % y =", x % y) # Modulo Divison
- print("y % x =", y % x) # Modulo Divison
+ print("x % y =", x % y) # Modulo Division
+ print("y % x =", y % x) # Modulo Division
elif choice == "6":
print("sqrt(x) =", math.sqrt(x)) # Quadratwurzel
diff --git a/Level_03/Beispielcode/calculator03.py b/Level_02/Beispielcode/calculator02_while.py
similarity index 91%
rename from Level_03/Beispielcode/calculator03.py
rename to Level_02/Beispielcode/calculator02_while.py
index f5ae37f..90ded72 100644
--- a/Level_03/Beispielcode/calculator03.py
+++ b/Level_02/Beispielcode/calculator02_while.py
@@ -1,4 +1,4 @@
-u"""
+"""
Das folgende Programm ist ein einfacher Taschenrechner.
Nach dem Eingeben zweier Zahlen kann eine Operation ausgewählt werden.
@@ -6,7 +6,7 @@
"""
# Für die Berechnung der Quadratwurzel wird die math Bibliothek benötigt,
-# desweiteren wird zum vorzeitigen Beenden die sys Bibliothek benötigt.
+# des Weiteren wird zum vorzeitigen Beenden die sys Bibliothek benötigt.
from math import sqrt
import sys
@@ -29,7 +29,7 @@
print()
# Das Programm läuft in einer Endlosschleife und wird durch eine entsprechende
-# Usereingabe beendet.
+# Nutzereingabe beendet.
while True:
choice = input("Bitte eine Operation auswählen: ")
@@ -68,8 +68,8 @@
elif choice == "5":
print("Rest:")
- print("x % y =", x % y) # Modulo Divison
- print("y % x =", y % x) # Modulo Divison
+ print("x % y =", x % y) # Modulo Division
+ print("y % x =", y % x) # Modulo Division
elif choice == "6":
print("Quadratwurzel: sqrt(x) =", sqrt(x)) # Quadratwurzel
diff --git a/Level_02/Beispielcode/cinema_if.py b/Level_02/Beispielcode/cinema_if.py
new file mode 100644
index 0000000..f19dde2
--- /dev/null
+++ b/Level_02/Beispielcode/cinema_if.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python3
+
+age_str: str = input("Wie alt bist du? ")
+
+if age_str.isdigit():
+ age_int: int = int(age_str)
+else:
+ print("Bitte gib eine Zahl als Alter ein.")
+ exit()
+
+fsk_shrek = 6
+fsk_avengers = 12
+
+print("Folgende Filme könntest du dir ansehen: ")
+
+if age_int >= fsk_avengers:
+ print("Marvel: The Avengers")
+
+elif age_int >= fsk_shrek:
+ print("Shrek")
+else:
+ print("Leider haben wir keine Filme für dich im Angebot.")
diff --git a/Level_02/Beispielcode/cinema_while.py b/Level_02/Beispielcode/cinema_while.py
new file mode 100644
index 0000000..88dc130
--- /dev/null
+++ b/Level_02/Beispielcode/cinema_while.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python3
+fsk_shrek = 6
+fsk_avengers = 12
+
+counter: int = 0
+while counter < 3:
+ age_str: str = input("Wie alt bist du? ")
+
+ if age_str.isdigit():
+ age_int: int = int(age_str)
+ break
+
+ else:
+ print("Bitte gib eine Zahl als Alter ein.")
+
+ counter += 1
+else:
+ age_int: int = 7
+ print("Wenn du uns dein Alter nicht sagen möchtest, müssen wir es schätzen.")
+ print(f"Du bist wohl {age_int} Jahre alt.")
+
+print("Folgende Filme könntest du dir ansehen: ")
+
+if age_int >= fsk_avengers:
+ print("Marvel: The Avengers")
+
+elif age_int >= fsk_shrek:
+ print("Shrek")
+
+else:
+ print("Leider haben wir keine Filme für dich im Angebot.")
diff --git a/Level_03/ggT.py b/Level_02/Beispielcode/ggT.py
similarity index 100%
rename from Level_03/ggT.py
rename to Level_02/Beispielcode/ggT.py
diff --git a/Level_02/Level_2.ipynb b/Level_02/Level_2.ipynb
index ce0f695..83f5b58 100644
--- a/Level_02/Level_2.ipynb
+++ b/Level_02/Level_2.ipynb
@@ -20,33 +20,22 @@
},
"source": [
"## Einstieg\n",
- "In diesem Level werden wir lernen, wie die Ausführung von bestimmten Code an Bedingungen knüpfen. Dafür werden wir erst den Typ des __boolean__ und im Anschluss unsere ersten Kontrollstrukturen, die if-Bedingung und die while-Schleife einführen. Dabei werden wir die Schlüsselwörter `True`, `False`, `if`, `elif`, `else`, `is`, `while`, `break` und `continue` kennenlernen.\n",
"\n",
- "Die if-Bedingung wird es uns ermöglichen Code auszuführen, wenn eine Bedingung erfüllt ist.\n",
- "Die while-Schleife wird es uns ermöglichen Code __solange__ auszuführen, wie eine Bedingung erfüllt ist."
+ "In diesem Level lernst du mit dem `boolean` einen neuen Datentypen kennen. Ebenso lernst du zwei neue Kontrollstrukturen kennen: die `if`-Bedingung und die `while`-Schleife.\n",
+ "Diese Kontrollstrukturen ermöglichen es dir nach Abschluss dieses Levels komplexere Algorithmen zu implementieren und anspruchsvollere Python-Skripte zu schreiben."
]
},
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": null,
"metadata": {
- "scrolled": false,
"slideshow": {
- "slide_type": "-"
+ "slide_type": "slide"
}
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Bitte etwas eingeben: 3\n",
- "3\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
- "eingabe = input(\"Bitte etwas eingeben: \")\n",
+ "eingabe = input(\"Bitte eine Zahl eingeben: \")\n",
"zahl = int(eingabe)\n",
"print(zahl)"
]
@@ -59,8 +48,7 @@
}
},
"source": [
- "Schauen wir uns obigen Code an. Wir erwarten eine Eingabe und versuchen aus dieser Eingabe einen integer zu entnehmen. Dies klappt auch, wenn der Benutzer eine ganze Zahl eingibt - gibt er jedoch stattdessen zum Beispiel eine Zeichenkette ein, wird ein `ValueError` geworfen. Ebenso wird ein Fehler geworfen, wenn der Benutzer nichts eingibt.\n",
- "Im Verlauf dieses Levels werden wir, lernen Benutzereingaben zu prüfen und entsprechend zu reagieren."
+ "Zum Einstieg betrachte den obigen Code-Ausschnitt. Es soll eine Zahl vom Benutzer eingegeben werden. In Level 1 hast du gelernt, dass die `input()`-Funktion stets einen string zurückliefert. Daher wird im obigen Beispiel die Eingabe mittels der `int()`-Funktion in einen integer umgewandelt. Probleme treten auf, wenn der Benutzer keine gültige Zahl eingibt. Die Verarbeitung einer fehlerhaften Eingabe ist durch eine `if`-Bedingung möglich. Doch zuerst solltest du einmal verstehen was ein `boolean` ist."
]
},
{
@@ -72,33 +60,33 @@
},
"source": [
"## Der Typ boolean\n",
- "Der __boolean__ ist ein Typ, der genau zwei Werte besitzt: `True` und `False`. In Python3 sind diese beiden Literale Schlüsselwörter und können somit nicht als Variablennamen benutzt werden. Mit der `bool()`Funktion kann ein Wert in einen boolean umgewandelt werden."
+ "\n",
+ "Ein __boolean__ ist ein Datentyp, der einen Wahrheitswert enthält. Valide Werte für einen boolean sind die Literale `True` und `False`.\n",
+ "Wie die Werte anderer Datentypen kannst du diese beiden Werte in einer Variablen speichern.\n",
+ "\n",
+ "```python\n",
+ "wahr = True\n",
+ "falsch = False\n",
+ "```\n",
+ "\n",
+ "Ebenso wie für die Datentypen, die du bisher kennengelernt hast, gibt es auch für den boolean eine Funktion, welche einen beliebigen Ausdruck in einen boolean-Wert umwandelt. In diesem Fall die `bool()` Funktion. Im folgendem siehst du ein paar Beispiele für Umwandlungen dir bekannter Datentypen."
]
},
{
"cell_type": "code",
- "execution_count": 2,
- "metadata": {
- "scrolled": false,
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "\n"
- ]
- }
- ],
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
"source": [
- "b1 = True\n",
- "b2 = False\n",
- "print(type(b1))\n",
- "print(type(b2))"
+ "# True\n",
+ "print(f'bool(23): {bool(23)}')\n",
+ "print(f'bool(4.2): {bool(4.2)}')\n",
+ "print(f'bool(\"pythonfoo\"): {bool(\"pythonfoo\")}')\n",
+ "\n",
+ "# False\n",
+ "print(f'bool(0): {bool(0)}')\n",
+ "print(f'bool(0.0): {bool(0.0)}')\n",
+ "print(f'bool(\"\"): {bool(\"\")}')"
]
},
{
@@ -109,32 +97,19 @@
}
},
"source": [
- "Der Typ eines Objektes bestimmt, wie dieses in einen boolean umgewandelt wird. Für die bisherigen Typen integer, float und string gilt:\n",
- "* ein integer ist `True`, solange er nicht `0` ist\n",
- "* ein float ist `True`, solange er nicht `0.0` ist\n",
- "* ein string ist `True`, solange er nicht leer, d.h. `''` ist"
+ "Ob ein Wert umgewandelt in einen boolean `True` oder `False` zurückgibt, hängt dabei vom Typen des Wertes ab. \n",
+ "Für die Datentypen, die du bisher kennengelernt hast, kannst du dir merken:\n",
+ "\n",
+ "1. Ein integer ist `True`, solange er nicht `0` ist\n",
+ "2. Ein float ist `True`, solange er nicht `0.0` ist\n",
+ "3. Ein string ist `True`, solange er nicht leer, d.h. `''` ist"
]
},
{
"cell_type": "code",
- "execution_count": 3,
- "metadata": {
- "scrolled": false,
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n",
- "False\n",
- "False\n"
- ]
- }
- ],
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
"source": [
"print(bool(\"\"))\n",
"print(bool(0))\n",
@@ -149,40 +124,44 @@
}
},
"source": [
- "Genauso wie integer und floats gibt es auch für booleans Operatoren:\n",
- "* `and` das logische \"und\"\n",
- "* `or` das logische \"oder\"\n",
- "* `not` die logische Negation\n",
+ "Ein Anwendungsfall von boolean-Werten, der dir sehr häufig begegnen wird, sind Vergleichsoperatoren. Du kennst sicherlich Vergleiche wie \"größer als\" oder \"kleiner gleich\" aus der Mathematik. Diese kannst du ebenfalls in Python benutzen. Im folgenden siehst eine Auflistung der Vergleichsoperatoren und jeweils ein wahres und ein falsches Beispiel.\n",
"\n",
- "Außerdem lässt sich auch xor (`^`) auf booleans anwenden."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {
- "scrolled": false,
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "not True: False\n",
- "True or False: True\n",
- "True and False: False\n",
- "True ^ False: True\n"
- ]
- }
- ],
- "source": [
- "print(\"not True:\", not True)\n",
- "print(\"True or False:\", True or False)\n",
- "print(\"True and False:\", True and False)\n",
- "print(\"True ^ False:\", True ^ False)"
+ "1. Äquivalenz: `==` prüft ob zwei Ausdrücke denselben Wert haben.\n",
+ " ```python\n",
+ " 23 == 15 + 8 # True\n",
+ " 23 == 27 # False\n",
+ " ```\n",
+ "2. Nicht-Äquivalenz: `!=` prüft ob zwei Ausdrücke einen unterschiedlichen Wert haben.\n",
+ " ```python\n",
+ " 23 != 42 # True\n",
+ " 23 != 23 # False\n",
+ " ```\n",
+ "3. Größer: `>` prüft ob der erste Ausdruck echt größer als der zweite Ausdruck ist.\n",
+ " ```python\n",
+ " 23 > 2.3 # True\n",
+ " 23 > 24 # False\n",
+ " ```\n",
+ "4. Kleiner: `<` prüft ob der erste Ausdruck echt größer als der zweite Ausdruck ist.\n",
+ " ```python\n",
+ " 23 < 42 # True\n",
+ " 23 < 2.7 # False\n",
+ " ```\n",
+ "5. Größer gleich: `>=` prüft ob der erste Ausdruck größer oder gleich dem zweiten Ausdruck ist.\n",
+ " ```python\n",
+ " 23 >= 23 # True\n",
+ " 23 >= 24 # False\n",
+ " ```\n",
+ "6. Kleiner gleich: `<=` prüft ob der erste Ausdruck kleiner oder gleich dem zweiten Ausdruck ist.\n",
+ " ```python\n",
+ " 23 >= 42 # True\n",
+ " 23 >= 42 # False\n",
+ " ```\n",
+ "7. Gleichheit: `is` ist ein Schlüsselwort und prüft ob zwei Ausdrücke gleich sind.\n",
+ " ```python\n",
+ " 23 is 23 # True\n",
+ " 23 is 23.0 # False\n",
+ " ```\n",
+ " Das Schlüsselwort `is` findet bei primitiven, unveränderlichen Datentypen kaum Anwendung, da es sich bei diesen nicht vom Äquivalenzoperator `==` unterscheidet."
]
},
{
@@ -193,22 +172,19 @@
}
},
"source": [
- "Häufig möchte man Werte mit einander vergleichen, dafür gibt es die Vergleichsoperatoren, die für viele Typen definiert sind:\n",
+ "Genauso wie integer und floats gibt es auch für booleans Operatoren:\n",
"\n",
- "* `==`: prüft auf Äquivalenz\n",
- "* `!=`: prüft auf Nicht-Äquivalenz\n",
- "* `>`: echtes größer\n",
- "* `<`: echtes kleiner\n",
- "* `>=`: größer gleich\n",
- "* `<=`: kleiner gleich\n",
- "* `is`: prüft auf Gleichheit\n",
+ "1. `and` das logische \"und\"\n",
+ "2. `or` das logische \"oder\"\n",
+ "3. `not` die logische Negation\n",
"\n",
- "Diese Operatoren liefern alle einen boolschen Wert, d.h. einen Wert vom Typ boolean zurück."
+ "Außerdem lässt sich auch xor (`^`) auf booleans anwenden. \n",
+ "Die Operatoren `and` und `or` lassen sich nicht nur auf booleans anwenden. Bei Anwendung mit anderen Datentypen weisen sie eien erweiterte Funktion auf."
]
},
{
"cell_type": "code",
- "execution_count": 5,
+ "execution_count": 2,
"metadata": {
"scrolled": false,
"slideshow": {
@@ -220,103 +196,86 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "False\n"
+ "not True: False\n",
+ "True or False: True\n",
+ "True and False: False\n",
+ "True ^ False: True\n"
]
}
],
"source": [
- "print(5 < 3)"
+ "print(\"not True:\", not True)\n",
+ "print(\"True or False:\", True or False)\n",
+ "print(\"True and False:\", True and False)\n",
+ "print(\"True ^ False:\", True ^ False)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "### \"==\" und \"is\"\n",
- "`==` prüft, ob die Objekte, auf die die Variablen zeigen, äquivalent sind. \n",
- "`is` prüft, ob die Variablen auf dasselbe Objekt zeigen."
+ "## if-Bedingung\n",
+ "\n",
+ "Nachdem du den Datentyp boolean kennengelernt hast, lernst du nun, wie du eine `if`-Bedingung benutzt. Eine `if`-Bedingung dient dazu einen Code-Abschnitt nur auszuführen, wenn eine Bedingung erfüllt ist. Bei dieser Bedingung handelt es sich um einen boolschen Ausdruck. Im folgendem Code-Ausschnitt siehst du eine beispielhafte if-Bedingung.\n",
+ "\n",
+ "```python\n",
+ "if True:\n",
+ " print(\"True\")\n",
+ "```\n",
+ "\n",
+ "### Einrückung und Gültigkeitsbereiche\n",
+ "\n",
+ "Beachte, dass der Code, welcher von der Bedingung beeinflusst werden soll um vier Leerzeichen eingerückt ist. Das ist kein Zufall. Anders als andere Programmiersprachen erkennt Python die Gültigkeitsbereiche nicht anhand von Klammern (Java benutzt zum Beispiel `{` und `}`), sondern anhand der Einrückung am Anfang der Zeile. Zu einem Gültigkeitsbereich gehören dabei alle aufeinanderfolgenden Zeilen gleicher Einrückung.\n"
]
},
{
"cell_type": "code",
- "execution_count": 6,
+ "execution_count": null,
"metadata": {
"scrolled": false
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "==: True\n",
- "is: False\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
- "print(\"==:\", 10**3 == 1000)\n",
- "print(\"is:\", 10**3 is 1000)"
+ "eingabe = input(\"Bitte etwas eingeben: \")\n",
+ "if eingabe: # alternativ: bool(eingabe) oder eingabe != \"\"\n",
+ " print(eingabe)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "## if-Bedingung\n",
- "Nun da wir gelernt haben, was boolean-Werte sind, können wir diese in einer if-Abfrage benutzen: Codeteile nur dann ausführen, wenn eine Bedingung erfüllt ist. Sehen wir uns zunächst die Syntax einer if-Abfrage in Python an:\n",
+ "Im obigen Beispiel siehst du ein interaktives Beispiel für eine einfache if-Bedingung. In dem Fall soll überprüft werden, ob die Eingabe leer ist. Beachte, dass die als Bedingung lediglich die Variable `eingabe` also ein string benutzt wird. Dies ist deshalb möglich, da der Python-Interpreter intern auf den Ausdruck, welchen du als Bedingung angibst, versucht mittels der `bool()`-Funktion in einen `boolean` umzuwandeln. \n",
+ "\n",
+ "Eine if-Bedingung kann auch beliebig viele (optionale) `elif`-Zweige und einen (ebenfalls optionalen) `else`-Zweige enthalten. Das Schlüsselwort `elif` ist eine Abkürzung für `else if`. In einem `elif`-Zweig kannst du weitere Bedingungen prüfen. Es wird aber stets der erste Zweig ausgeführt, dessen Bedingung wahr ist. Der `else`-Zweig wird nur dann ausgeführt, wenn keine Bedingung wahr ist. Unten siehst du den schematischen Aufbau einer if-Bedingung (Achtung es handelt sich *nicht* um validen Python-Code).\n",
"```python\n",
"if Bedingung:\n",
- " Befehle\n",
- "```\n",
- "Wir starten mit dem Schlüsselwort `if`, dann kommt eine Bedingung, diese sollte einen boolschen Ausdruck zurückgeben, wir können diesen explizit angeben, der Interpreter ruft allerdings auf unsere Bedingung `bool()` auf und führt unsere Befehle aus, wenn dies `True`zurück gibt. Nach der Bedingung folgt ein Doppelpunkt `:`. Die nächste Zeile wird nun eingerückt, hierbei hat man sich auf __vier Leerzeichen__ geeinigt."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {
- "scrolled": false
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Bitte etwas eingeben: 3\n",
- "3\n"
- ]
- }
- ],
- "source": [
- "eingabe = input(\"Bitte etwas eingeben: \")\n",
- "if eingabe: # alternativ: bool(eingabe) oder eingabe != \"\"\n",
- " print(eingabe)"
+ " Anweisungen\n",
+ "\n",
+ "elif Bedingung:\n",
+ " Anweisungen\n",
+ "\n",
+ "...\n",
+ "\n",
+ "else:\n",
+ " Anweisungen\n",
+ "```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "Im obigen Codebeispiel prüft die if-Bedingung, ob der String `eingabe` leer ist. Dies geschieht implizit, d.h. es wird ausgenutzt, dass der Interpreter die Bedingung in einen boolean umwandelt. In dem Kommentar sind alternative Bedingungen beschrieben, die daselbe erreichen, allerdings umständlicher sind. \n",
- "Wenn wir uns aber an unser Problem aus der Einleitung erinnern, war unser Ziel eine Zahl aus der Eingabe zu lesen und Fehler durch falsche Benutzereingaben abzufangen. Wir wollen also darauf reagieren, wenn nichts eingegeben wurde, wenn eine Zahl eingegeben wurde und wenn eine Zeichenkette eingegeben wurde, die nicht als integer interpretiert werden kann."
+ "Wenn du dich an das Problem im [Einstieg](#einstieg) erinnerst kannst du nun die if-Bedingung anwenden, um einen `Value-Error` bei Eingabe von falschen Werten zu vermeiden."
]
},
{
"cell_type": "code",
- "execution_count": 8,
+ "execution_count": null,
"metadata": {
"scrolled": false
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Bitte etwas eingeben: 3\n",
- "3\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"eingabe = input(\"Bitte etwas eingeben: \")\n",
"\n",
@@ -332,83 +291,75 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Wie wir sehen können, passiert im obigen Codebeispiel eine Menge auf einmal, gehen wir es also in Ruhe durch.\n",
- "In der if-Abfrage wird mit der `str.isdigit()` Methode geprüft, ob der string `eingabe` nicht leer ist und nur aus Ziffern besteht; wenn dem so ist, erstellen wir einen integer `zahl` aus der Eingabe und geben diesen aus. In einem `else` Zweig, der ausgeführt wird, wenn die Bedingung der if-Abfrage nicht zutraf, geben wir dem Benutzer Feedback über seine falsche Eingabe zurück."
+ "Im obigen Beispiel wird die `str.isdigit()` Methode verwendet. Diese Methode gibt `True` zurück, sobald alle Zeichen in dem string Nummern sind. Durch Benutzung dieser Methode kannst du verhindern, dass dein Programm wegen eines `ValueError`s abstürzt. Du kannst natürlich auch zusätzlich prüfen, ob die Eingabe leer ist:"
]
},
{
"cell_type": "code",
- "execution_count": 9,
+ "execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "Bitte eine Zahl eingeben: 3\n",
- "3 ist eine gültige Zahl.\n"
+ "23 ist eine gültige Zahl.\n"
]
}
],
"source": [
"eingabe = input(\"Bitte eine Zahl eingeben: \")\n",
"\n",
- "if eingabe:\n",
- " # die Eingabe ist nicht leer.\n",
- " if eingabe.isdigit():\n",
- " zahl = int(eingabe)\n",
- " print(zahl, \"ist eine gültige Zahl.\")\n",
- " else:\n",
- " print(\"Die Eingabe ''\" + eingabe + \"' ist keine gültige Zahl\")\n",
+ "if eingabe.isdigit():\n",
+ " # die Eingabe ist eine gültige Zahl\n",
+ " zahl = int(eingabe)\n",
+ " print(zahl, \"ist eine gültige Zahl.\")\n",
+ "\n",
+ "elif not eingabe:\n",
+ " # die Eingabe ist leer\n",
+ " print(\"Die Eingabe ist leer\")\n",
+ "\n",
"else:\n",
- " print(\"Die Eingabe ist leer.\")"
+ " # die Eingabe ist nicht leer, aber auch keine\n",
+ " # gültige Zahl\n",
+ " print(\"Die Eingabe '\" + eingabe + \"' ist keine gültige Zahl\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "if-Bedingungen können auch verschachtelt werden, d.h. wir können also in einer if-Bedingung eine weitere if-Bedingung definieren. Allerdings können wir dies durch die Benutzung des Schlüsselwortes `elif` vereinfachen:"
+ "Du kannst if-Bedingungen auch ineinander verschachteln. Das kann bei komplexeren Bedingungen hilfreich sein. Unten siehst du das Beispiel von oben als verschachtelte if-Bedingung. Gerade bei längeren Bedingungen kann es hilfreich sein, diese zu verschachteln. Beachte beim Verschachteln von if-Bedingungen die Einrückung!"
]
},
{
"cell_type": "code",
- "execution_count": 10,
+ "execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "Bitte eine Zahl eingeben: 3\n",
- "3 ist eine gültige Zahl.\n"
+ "Die Eingabe 23 ist eine gültige Zahl.\n"
]
}
],
"source": [
"eingabe = input(\"Bitte eine Zahl eingeben: \")\n",
"\n",
- "if eingabe.isdigit():\n",
- " # die Eingabe ist eine gültige Zahl\n",
- " zahl = int(eingabe)\n",
- " print(zahl, \"ist eine gültige Zahl.\")\n",
- " \n",
- "elif not eingabe:\n",
- " # die Eingabe ist leer\n",
- " print(\"Die Eingabe ist leer\")\n",
- " \n",
+ "if eingabe:\n",
+ " if eingabe.isdigit():\n",
+ " # die Eingabe ist eine gültige Zahl\n",
+ " zahl = int(eingabe)\n",
+ " print(\"Die Eingabe\", zahl, \" ist eine gültige Zahl.\")\n",
+ " else:\n",
+ " # die Eingabe ist keine gültige Zahl\n",
+ " print(\"Die Eingabe\", eingabe, \" ist keine gültige Zahl\")\n",
+ "\n",
"else:\n",
- " # die Eingabe ist nicht leer, aber auch keine\n",
- " # gültige Zahl\n",
- " print(\"Die Eingabe '\" + eingabe + \"' ist keine gültige Zahl\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Eine if-Bedingung enthält einen if-Zweig, beliebig viele optionale elif-Zweige und optional einen else-Zweig. Dabei wird immer der erste Zweig, dessen Bedingung zutrifft ausgeführt und nachher keine weiteren.\n",
- "Daher ist es wichtig auf die Reihenfolge der Zweige zu achten."
+ " # die Eingabe ist leer\n",
+ " print(\"Die Eingabe ist leer.\")"
]
},
{
@@ -416,19 +367,26 @@
"metadata": {},
"source": [
"## while-Schleife\n",
- "Bisher ist es sehr schwierig Code mehrfach auszuführen, wenn wir unsere Programme wiederholen müssen wir sie neu starten. Nicht nur das, sondern haben wir keine Möglichkeit Befehle beliebig häufig auszuführen. Die Möglichkeit Code wiederholt auszuführen ist allerdings für viele Programme ein elementarer Bestandteil. Daher möchten wir uns im dritten Abschnitt dieses Levels mit der while-Schleife beschäftigen, die diese Probleme löst.\n",
"\n",
- "Die while-Schleife ist im Aufbau ähnlich der if-Bedingung:\n",
+ "Bisher hattest du keine Möglichkeit Programmcode wiederholt auszuführen. Das wäre aber sehr hilfreich, damit du nicht wiederholt den selben Code schreiben musst. In Python wird dies (wie in vielen anderen Programmiersprachen auch) mit Schleifen realisiert. In Python gibt es zwei Arten von Schleifen: `While`-Schleife und die `for`-Schleife. In diesem Level lernst du die `while`-Schleife kennen. Du wirst feststellen, dass sie große Gemeinsamkeiten mit der `if`-Bedingung aufweist.\n",
+ "\n",
+ "Hier siehst du den Aufbau der `while`-Schleife:\n",
+ "\n",
"```python\n",
"while Bedingung:\n",
" Befehle\n",
"```\n",
- "Der Unterschied ist, dass unsere Befehle, solange wiederholt werden, wie die Bedingung gültig (d.h. == True) ist. Hierbei ist Vorsicht geboten, da es zu Endlosschleifen kommen kann."
+ "\n",
+ "Im Schleifenkopf legst du eine Bedingung fest. Diese Bedingung ist ein boolscher Ausdruck und wird auf seinen Wahrheitswert geprüft. Ist die Bedingung wahr, werden die Befehle im Schleifenrumpf ausgeführt. Danach wird erneut die Bedingung im Schleifenkopf auf ihren Wahrheitswert getestet, ist die Bedingung immer noch war, wird erneut der Schleifenrumpf ausgeführt. Ist die Bedingung jedoch falsch, wird der Durchlauf der Schleife beendet.\n",
+ "\n",
+ "Wie du vielleicht bemerkt hast, sind die Voraussetzungen an eine `while`-Schleife sehr abstrakt (ähnlich wie bei einer `if`-Bedingung). Dadurch kannst du viele verschiedene Anwendungsfälle mit einer `while`-Schleife darstellen.\n",
+ "\n",
+ "Im folgenden Codeblock siehst du eine Schleife, die eine `integer` Variable hochzählt. Die Bedingung vergleicht dabei diese Variable mit einem Maximalwert (in dem Fall `10`). Im Beispiel wird die Variable lediglich ausgegeben, du kannst aber natürlich alles erdenkliche mit dem `integer` anstellen."
]
},
{
"cell_type": "code",
- "execution_count": 11,
+ "execution_count": 1,
"metadata": {},
"outputs": [
{
@@ -450,7 +408,8 @@
],
"source": [
"counter = 0\n",
- "while counter < 10:\n",
+ "maximum = 10\n",
+ "while counter < maximum:\n",
" print(counter)\n",
" counter += 1"
]
@@ -459,95 +418,34 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Im obigen Codeblock sehen wir eine einfache Anwendung der while-Schleife. Kommentieren wir jedoch die letzte Zeile aus, kommt es zu einer Endlosschleife. In diesem Zusammenhang der Hinweis, dass sich im Interpreter Python Programme durch drücken von Strg + C abbrechen lassen.\n",
+ "Du solltest immer darauf achten keine Endlosschleife zu erschaffen. Wenn aus irgendeinem Grund deine Abbruchbedingung niemals `False` werden kann, wird die Schleife endlos laufen. In der Zählschleife oben kann dir dies zum Beispiel leicht passieren, wenn du die Inkrementierung (`counter += 1`) vergisst. In dem Fall würde die `counter` Variable niemals den Wert ändern und daher für immer `< maximum` bleiben. In den Konsole kannst du die Ausführung eines Python-Programms durch die Tastenkombination `Strg + C` abbrechen.\n",
"\n",
- "Innerhalb einer while-Schleife ist es möglich mit dem Schlüsselwort `break` den Durchlauf der Schleife abzubrechen oder mit dem Schlüsselwort `continue` den aktuellen Durchlauf zu überspringen. Bei der Benutzung von `continue`müssen wir wieder darauf achten keine Endlosschleifen zu erstellen."
+ "Es gibt noch zwei Schlüsselwörter, die dir mehr Kontrolle über den Schleifendurchlauf geben: `break`, `continue` und `else`. Das `break`-Schlüsselwort beendet den Durchlauf der Schleife und springt an Ende. Das `continue`-Schlüsselwort überspringt den Rest des Codeblocks und springt zum Schleifenkopf. Das `else`-Schlüsselwort kann am Ende einer Schleife benutzt werden. Der Codeblock unter dem `else`-Schlüsselwort wird ausschließlich dann ausgeführt, wenn der Durchlauf der Schleife nicht durch ein `break` abgebrochen wurde."
]
},
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Start.\n",
- "Bitte etwas eingeben: Hallo\n",
- "Hallo\n",
- "-----\n",
- "Bitte etwas eingeben: C\n",
- "Bitte etwas eingeben: Q\n",
- "Fertig.\n"
- ]
- }
- ],
- "source": [
- "print(\"Start.\")\n",
- "while True:\n",
- " eingabe = input(\"Bitte etwas eingeben: \")\n",
- " if not eingabe:\n",
- " break\n",
- " elif eingabe == \"Q\":\n",
- " break\n",
- " elif eingabe == \"C\":\n",
- " continue\n",
- " else:\n",
- " print(eingabe)\n",
- " print(len(eingabe)*\"-\")\n",
- " \n",
- "print(\"Fertig.\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Das Schlüsselwort `else` kann nicht nur in einer if-Bedingung, sonder auch in Verbindung mit einer while-Schleife benutzt werden. Dabei wird der else-Zweig ans Ende der entsprechenden while-Schleife angefügt. Der Code des else-Zweiges wird dann nur ausgeführt, wenn die Schleife __nicht__ durch ein `break` abgebrochen wurde."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Die gesuchte Zahl x ist 0 < x < 100.\n",
- ": 50\n",
- "Größer\n",
- "Noch 9 Versuche.\n",
- ": 75\n",
- "Kleiner.\n",
- "Noch 8 Versuche.\n",
- ": 62\n",
- "Kleiner.\n",
- "Noch 7 Versuche.\n",
- ": 56\n",
- "Richtig!\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"# Zahlen raten\n",
"gesucht = 56\n",
"versuche = 10\n",
- "zähler = 0\n",
+ "zaehler = 0\n",
"print(\"Die gesuchte Zahl x ist 0 < x < 100.\")\n",
"\n",
- "while zähler < versuche:\n",
+ "while zaehler < versuche:\n",
" eingabe = input(\": \")\n",
- " zähler += 1\n",
+ " zaehler += 1\n",
+ "\n",
" # eingabe überprüfen\n",
" if eingabe.isdigit():\n",
" zahl = int(eingabe)\n",
" else:\n",
" print(\"Ungültige Eingabe.\")\n",
" continue\n",
- " \n",
+ "\n",
" # Benutzer Feedback\n",
" if zahl == gesucht:\n",
" print(\"Richtig!\")\n",
@@ -557,8 +455,8 @@
" print(\"Kleiner.\")\n",
" else:\n",
" print(\"Größer\")\n",
- " print(\"Noch\", versuche-zähler, \"Versuche.\")\n",
- " \n",
+ " print(\"Noch\", versuche - zaehler, \"Versuche.\")\n",
+ "\n",
"\n",
"else:\n",
" # kein break <=> zahl wurde nicht erraten\n",
@@ -570,15 +468,19 @@
"cell_type": "markdown",
"metadata": {},
"source": [
+ "Oben siehst du ein etwas längeres Beispiel, darin sind alle Elemente dieses Levels vereint. Du siehst sowohl `if`-Bedingungen als auch eine `while`-Schleife. In der Schleife werden die drei erwähnten Schlüsselwörter `break`, `continue` und `else` benutzt. In dem Beispiel soll vom Benutzer eine Zahl geraten werden. Dazu hat der Benutzer 10 Versuche. Bei jeder gültigen Eingabe des Benutzers wird dabei eine Tendenz (\"Größer\" oder \"Kleiner\") ausgegeben. Falls der Benutzer eine ungültige Eingabe tätigt, wird der Durchlauf der Schleife übersprungen, gibt der Benutzer die gesuchte Zahl ein, wird der Schleifendurchlauf beendet.\n",
+ "\n",
"## Rückblick\n",
- "Vor diesem Level konnten wir nur sehr begrenzte Programme schreiben. Wir konnten Eingaben entgegennehmen, mit dieser Eingabe Berechnungen (im weitesten Sinne) durchführen und die Ergebnisse dieser Berechnungen wieder ausgeben. Dieses Level hat nun die if-Bedingung und die while-Schleife eingeführt. Diese beiden Kontrollstrukturen ermöglichen uns das Schreiben komplexer Programme und die Implementation anspruchsvoller Algorithmen. die if-Bedingung sorgt dafür, dass unsere Programme nun auf Eingaben zu reagieren und Fehler abzufangen. Die while-Schleife ermöglicht es uns Befehle beliebig häufig auszuführen. Damit sind schon im zweiten Level wichtige Bausteine für komplexe Programme eingeführt worden."
+ "\n",
+ "Im vorherigen Level hast du gelernt, Eingaben vom Benutzer entgegen zu nehmen, diese zu verarbeiten und das Ergebnis an den Benutzer auszugeben.\n",
+ "In diesem Level hast du zwei Kontrollstrukturen kennengelernt, die `if`-Bedingung und die `while`-Schleife. Dazu hast du den Datentyp `boolean` kennengelernt. Durch diese beiden Kontrollstrukturen kannst du komplexere Programme schreiben. Durch die `if`-Bedingung kannst du auf Eingaben des Benutzers oder Änderungen der Umgebung reagieren. Mit der `while`-Schleife kannst du zum Beispiel verschiedene mathematische Algorithmen implementieren."
]
}
],
"metadata": {
"celltoolbar": "Raw Cell Format",
"kernelspec": {
- "display_name": "Python 3",
+ "display_name": "Python 3.10.6 64-bit",
"language": "python",
"name": "python3"
},
@@ -592,7 +494,12 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.6.7"
+ "version": "3.10.6"
+ },
+ "vscode": {
+ "interpreter": {
+ "hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1"
+ }
}
},
"nbformat": 4,
diff --git "a/Level_02/L\303\266sungen/diamond.py" "b/Level_02/L\303\266sungen/diamond.py"
new file mode 100644
index 0000000..480c130
--- /dev/null
+++ "b/Level_02/L\303\266sungen/diamond.py"
@@ -0,0 +1,13 @@
+max_width = int(input("Maximale Breite: "))
+min_width = 0
+zeichen = input("Zeichen: ")
+assert len(zeichen) == 1
+
+cur_width = 1
+while cur_width * 2 <= max_width:
+ print(" " * (max_width - cur_width) + zeichen*(cur_width * 2 - 1))
+ cur_width += 1
+
+while cur_width * 2 >= min_width:
+ print(" " * (max_width - cur_width) + zeichen*(cur_width * 2 - 1))
+ cur_width -= 1
diff --git "a/Level_02/L\303\266sungen/password.py" "b/Level_02/L\303\266sungen/password.py"
new file mode 100644
index 0000000..d13110a
--- /dev/null
+++ "b/Level_02/L\303\266sungen/password.py"
@@ -0,0 +1,22 @@
+#!/usr/bin/env python3
+from getpass import getpass
+from sys import exit
+
+PWD = "123456"
+
+print("Hallo, bitte gib dein Passwort ein:")
+
+counter = 0
+while counter < 3:
+ eingabe = getpass("> ")
+ if eingabe == PWD:
+ print("Richtig.")
+ break
+ else:
+ print("Falsch.")
+ counter += 1
+else:
+ print("leider zu oft falsch :(")
+ exit()
+
+print("Herzlich Willkommen")
diff --git a/Level_02/README.md b/Level_02/README.md
new file mode 100644
index 0000000..5c46bef
--- /dev/null
+++ b/Level_02/README.md
@@ -0,0 +1,58 @@
+# Level 2
+
+In Level 1 hast du gelernt Eingaben in der Konsole vom Benutzer entgegen zu nehmen und, diese EIngaben zu verarbeiten und die Ergebnisse dieser Verarbeitung in der Konsole auszugeben.
+
+In Level 2 wirst die `if`-Bedingung kennenlernen, die es dir ermöglicht Bedingungen zu prüfen, die erfüllt sein müssen, damit ein Codeabschnitt ausgeführt werden kann.
+Des Weiteren wirst du die `while`-Schleife kennenlernen, welche einen Codeabschnitt wiederholt ausführt, solange eine Bedingung erfüllt ist.
+Im Zusammenhang mit der `if`-Bedingung und der `while`-Schleife wirst du den Datentypen `boolean` kennenlernen. Dieser Datentyp beinhaltet Wahrheitswerte.
+Am Ende des Levels wirst bereits in der Lage sein komplexere Programme umzusetzen.
+
+Um mit diesem Level zu starten navigiere zur [Level2.ipynb](https://github.com/pythonfoo/pythonfooLite/blob/master/Level_02/Level_2.ipynb) Datei im Code Repository.
+
+## Aufgaben
+
+Die folgenden Aufgaben sollen dir helfen, die in diesem Level erlangten Kenntnisse unter die Probe zu stellen. Wie immer kannst du dich bei Fragen oder Problemen gerne an uns wenden.
+
+### 2.1 password.py
+
+* Schreibe ein Programm, das ein Passwort entgegennimmt, es mit einem intern
+ gespeicherten Passwort vergleicht und eine Begrüßungsnachricht ausgibt, falls das
+ Passwort richtig war.
+* Ändere dein Programm so ab, dass der Benutzer auch eine Nachricht bekommt, wenn
+ das Passwort falsch war.
+* Ändere dein Programm so ab, dass der Benutzer 3 Versuche hat, das Passwort richtig
+ einzugeben.
+
+### 2.2 diamond.py
+
+* Schreibe ein Programm, das die unten abgebildete ASCII-Art im Terminal darstellt.
+* Ändere dein Programm so ab, dass die maximale Breite der Raute vom Benutzer angegeben werden kann.
+* Ändere dein Programm so ab, dass das Zeichen, aus dem die Raute gebildet wird, vom Benutzer eingegeben werden kann.
+
+```
+ #
+ ###
+ #####
+ ###
+ #
+```
+
+Nach erfolgreicher Bearbeitung der Aufgabe sollte das Programm wie folgt ablaufen:
+
+* Der Benutzer gibt eine maximale Breite an Zeichen ein.
+* Der Benutzer gibt ein Zeichen ein.
+* Das Programm erstellt eine Raute entsprechend der maximalen Breite mit dem angegebenen Zeichen und gibt diese Raute aus.
+
+### 2.3 hangman_v1.py
+
+In dieser Aufgabe sollst du eine einfache Version des Kinderspiels Galgenmännchen erstellen. Diese Aufgabe ähnelt sehr der Aufgabe **password.py**.
+Zuerst soll ein Wort eingegeben werden können. Dieses Wort soll nun durch Eingabe von Buchstaben erraten werden. Dabei gibt es ein Limit für die Anzahl an Fehlern.
+Implementiere eine Version des Spiels, welche folgende Anforderungen erfüllt:
+
+* Das Spiel ist gewonnen, wenn das Wort erraten wurde und das Fehlerlimit noch nicht erreicht wurde.
+* Das Spiel ist verloren, wenn das Fehlerlimit erreicht wurde und das Wort noch nicht erreicht worden ist.
+* Wird ein Buchstabe vom Benutzer eingegeben, welcher im Wort vorkommt wird das Auftauchen dieses Buchstaben im Wort ausgegeben.
+* Wird ein Buchstabe vom Benutzer eingegeben, welcher nicht im Wort enthalten ist wird dies als Fehler gewertet.
+* Enthält eine Eingabe des Benutzers mehr als ein Zeichen, wird dies ebenfalls als Fehler gewertet.
+* Bei der Eingabe von Buchstaben soll die Groß- und Kleinschreibung keine Rolle spielen.
+* Die aktuelle Fehleranzahl soll stets für den Benutzer sichtbar sein.
\ No newline at end of file
diff --git a/Level_02/boolean.py b/Level_02/boolean.py
deleted file mode 100755
index 7f3082a..0000000
--- a/Level_02/boolean.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env python3
-
-# Der Datentyp :
-boolean = True # type: bool
-boolean2 = False
-
-
-# Vergleichen von zwei boolean:
-bool_result = boolean == boolean2
-bool_result2 = boolean and boolean2
-bool_result3 = boolean or boolean2
-
-print(bool_result)
-print(bool_result2)
-print(bool_result3)
-print()
-
-
-# Der not-Operator:
-
-boolean3 = not boolean
-print(boolean3)
\ No newline at end of file
diff --git a/Level_02/Aufgaben/buggy02.py b/Level_02/buggy02.py
similarity index 100%
rename from Level_02/Aufgaben/buggy02.py
rename to Level_02/buggy02.py
diff --git a/Level_02/if.py b/Level_02/if.py
deleted file mode 100755
index 9993d57..0000000
--- a/Level_02/if.py
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/usr/bin/env python3
-
-# Die if-Bedingung:
-boolean3 = True
-
-if boolean3 == True:
- print(True)
-
-# Wenn nur geprüft werden soll, ob ein Ausdruck
-# ist, kann das '== True' weggelassen werden,
-# da der Compiler überprüft, ob der Ausdruck True
-# ist.
-
-if boolean3:
- print(True)
-
-# if-Bedingung mit else-Zweig:
-summertime = True
-
-if summertime:
- print("Yeah, it's summer!")
-else:
- print("Ohh, it's winter!")
-
-
-# if-Bedingung zum Vergleichen von int-Werten:
-a = 5
-b = 10
-if a > b:
- print(a)
-else:
- print(b)
-
-# Wichtig: Auf die Einrückung achten!
-
-# if-Bedingung mit elif- und else-Zweig:
-
-a = 6
-b = 7
-
-if a > b:
- print("A")
-
-elif a == b:
- print(" ")
-
-elif a < b:
- print("B")
-
-else:
- print("You broke the math.")
-
-
-# Verschachtelte if-Bedingungen:
-
-a = 3
-b = 4
-c = 5
-
-if a < b:
- if b < c:
- print("C ist der Größte!")
-
- else:
- if b > c:
- print("B ist der Größte!")
-
- else:
- print("B und C sind die Größten!")
-
-else:
- if a > b:
- if a > c:
- print("A ist der Größte!")
-
- else:
- if a < c:
- print("C ist der Größte!")
-
- else:
- print("A und C sind die Größten!")
-
-# Wichtig: Einrückung beibehalten!
\ No newline at end of file
diff --git a/Level_02/passwort.py b/Level_02/passwort.py
deleted file mode 100755
index f19d439..0000000
--- a/Level_02/passwort.py
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env python3
-
-from getpass import getpass
-
-PWD = "123456" # type: str
-
-eingabe = getpass() # type: str
-
-if eingabe == PWD:
- print("Richtig.")
-elif eingabe in PWD:
- print("Fast.")
-else:
- print("Falsch.")
diff --git a/Level_03/Beispielcode/caesar_decode.py b/Level_03/Beispielcode/caesar_decode.py
index 0d350c1..5d03fa3 100644
--- a/Level_03/Beispielcode/caesar_decode.py
+++ b/Level_03/Beispielcode/caesar_decode.py
@@ -1,10 +1,10 @@
#!/usr/bin/env python3
-u"""
-Dieses Programm implementiert die Cäsarchiffre, die schon Gaius Julius Cäsar
+"""
+Dieses Programm implementiert die Cäsar-Chiffre, die schon Gaius Julius Cäsar
benutzt haben soll, um mit seinen Generälen vertraulich zu kommunizieren.
-Es handelt sich dabei um eine monoalphabetische Subtitutionschiffre, das
+Es handelt sich dabei um eine mono-alphabetische Substitutionschiffre, das
bedeutet, jeder Buchstabe im Klartext wird durch einen anderen Buchstaben aus
-dem Alphabet ersetzt, bei der Cäsarchiffre wird dieser zweite Buchstaben durch
+dem Alphabet ersetzt, bei der Cäsar-Chiffre wird dieser zweite Buchstaben durch
Verschiebung um einen festen Wert ermittelt. Dieser feste Wert bildet dabei den
Schlüssel. https://de.wikipedia.org/wiki/Caesar-Verschl%C3%BCsselung
diff --git a/Level_03/Beispielcode/caesar_encode.py b/Level_03/Beispielcode/caesar_encode.py
index 56757d4..4e16608 100644
--- a/Level_03/Beispielcode/caesar_encode.py
+++ b/Level_03/Beispielcode/caesar_encode.py
@@ -1,10 +1,10 @@
#!/usr/bin/env python3
-u"""
-Dieses Programm implementiert die Cäsarchiffre, die schon Gaius Julius Cäsar
+"""
+Dieses Programm implementiert die Cäsar-Chiffre, die schon Gaius Julius Cäsar
benutzt haben soll, um mit seinen Generälen vertraulich zu kommunizieren.
-Es handelt sich dabei um eine monoalphabetische Subtitutionschiffre, das
+Es handelt sich dabei um eine mono-alphabetische Substitutionschiffre, das
bedeutet, jeder Buchstabe im Klartext wird durch einen anderen Buchstaben aus
-dem Alphabet ersetzt, bei der Cäsarchiffre wird dieser zweite Buchstaben durch
+dem Alphabet ersetzt, bei der Cäsar-Chiffre wird dieser zweite Buchstaben durch
Verschiebung um einen festen Wert ermittelt. Dieser feste Wert bildet dabei den
Schlüssel. https://de.wikipedia.org/wiki/Caesar-Verschl%C3%BCsselung
diff --git a/Level_03/fibonacci.py b/Level_03/Beispielcode/fibonacci.py
similarity index 99%
rename from Level_03/fibonacci.py
rename to Level_03/Beispielcode/fibonacci.py
index 2f47bfe..99da0fd 100755
--- a/Level_03/fibonacci.py
+++ b/Level_03/Beispielcode/fibonacci.py
@@ -15,7 +15,7 @@
for n in range(anzahl): # type: int
# Gebe das aktuelle Element aus:
print(" * ", current)
-
+
# Setze das aktuelle Element eins weiter
# und das nächste auf die Summe des letzten und des aktuellen Elements.
current, next = next, current + next
diff --git a/Level_03/Beispielcode/fizzbuzz.py b/Level_03/Beispielcode/fizzbuzz.py
new file mode 100644
index 0000000..64af435
--- /dev/null
+++ b/Level_03/Beispielcode/fizzbuzz.py
@@ -0,0 +1,7 @@
+for i in range(1, 16):
+ output = ""
+ if i % 3 == 0:
+ output += "fizz"
+ if i % 5 == 0:
+ output += "buzz"
+ print(output or i)
diff --git a/Level_03/pwd-schleifen.py b/Level_03/Beispielcode/pwd-schleifen.py
similarity index 100%
rename from Level_03/pwd-schleifen.py
rename to Level_03/Beispielcode/pwd-schleifen.py
diff --git a/Level_03/Level_3.ipynb b/Level_03/Level_3.ipynb
index b03dcbf..d8c6c3a 100644
--- a/Level_03/Level_3.ipynb
+++ b/Level_03/Level_3.ipynb
@@ -5,7 +5,9 @@
"metadata": {},
"source": [
"# Level 3\n",
+ "\n",
"In diesem Level lernen wir neue Datentypen, wie `list`, `tuple`, `dict`, `set` und `frozenset` kennen und lernen über Objekte dieser Typen mittels einer __for-Schleife__ zu iterieren. Wir werden die Schlüsselwörter `del` und `for` kennenlernen und auch den Schlüsselwörtern `in`, `break`, `continue` und `else` ein weiteres Mal begegnen.\n",
+ "\n",
"## Einstieg\n",
"Bisher können wir Werte in Variablen speichern, das funktioniert auch, solange wir wissen, wieviele Werte wir speichern müssen. Das muss aber nicht der Fall sein. Die Datentypen, die wir in diesem Level kennenlernen ermöglichen es meherere Werte in einem Objekt zu speichern. Jeder dieser Typen hat dabei seine Besonderheiten, die wir im Laufe des Levels lernen werden."
]
@@ -1334,7 +1336,7 @@
},
{
"cell_type": "code",
- "execution_count": 45,
+ "execution_count": 4,
"metadata": {},
"outputs": [
{
@@ -1355,6 +1357,34 @@
"print(\"Martha:\", Martha[\"alter\"])"
]
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Löschen erfolgt ähnlich:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'name': 'Max', 'alter': 42}"
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "del Max[\"nachname\"]\n",
+ "Max"
+ ]
+ },
{
"cell_type": "markdown",
"metadata": {},
@@ -2431,7 +2461,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.6.7"
+ "version": "3.12.3"
}
},
"nbformat": 4,
diff --git a/Level_03/Aufgaben/bubblesort.py "b/Level_03/L\303\266sungen/bubblesort.py"
similarity index 99%
rename from Level_03/Aufgaben/bubblesort.py
rename to "Level_03/L\303\266sungen/bubblesort.py"
index c88662d..ea8ee9e 100755
--- a/Level_03/Aufgaben/bubblesort.py
+++ "b/Level_03/L\303\266sungen/bubblesort.py"
@@ -5,7 +5,7 @@ def get_random_list(n: int) -> list:
result = list(range(n))
random.shuffle(result)
return result
-
+
n = int(input("Länge der Liste: "))
unsorted_list = get_random_list(n)
diff --git a/Level_03/Aufgaben/fakultaet.py "b/Level_03/L\303\266sungen/fakultaet.py"
similarity index 99%
rename from Level_03/Aufgaben/fakultaet.py
rename to "Level_03/L\303\266sungen/fakultaet.py"
index caa89cf..30d47c6 100755
--- a/Level_03/Aufgaben/fakultaet.py
+++ "b/Level_03/L\303\266sungen/fakultaet.py"
@@ -22,4 +22,3 @@
print(str(n) + "! = " + str(result))
"""
-
diff --git "a/Level_03/Aufgaben/gau\303\237.py" "b/Level_03/L\303\266sungen/gau\303\237.py"
similarity index 100%
rename from "Level_03/Aufgaben/gau\303\237.py"
rename to "Level_03/L\303\266sungen/gau\303\237.py"
diff --git a/Level_03/README.md b/Level_03/README.md
new file mode 100644
index 0000000..b06889b
--- /dev/null
+++ b/Level_03/README.md
@@ -0,0 +1,51 @@
+# Level 3 Aufgaben
+
+Viele Algorithmen in der Mathematik lassen sich als Summen oder Produkte beschreiben. Diese wiederrum können mit Schleifen implementiert werden. Später werden wir allerdings noch einen anderen Weg kennenlernen solche Algorithmen zu implementieren (Rekursion). Im Folgenden soll die Benutzung von Schleifen an klassischen Beispielen geübt werden.
+
+## Aufgabe 1: Die Fakultät
+Die Fakultät einer natürlichen Zahl `n` schreibt man als `n!` und ist das Produkt aller natürlichen Zahlen von 1 bis einschließlich n.
+Wir schreiben: `n! = 1 * 2 * 3 * n-2 * n-1 * n`.
+**Schreibe ein Programm, das die Fakultät einer eingegebenen Zahl berechnet. Und überprüfe mit Hilfe der vorgegebenen Werte.**
+
+```
+3! = 1 * 2 * 3 = 6
+4! = 1 * 2 * 3 * 4 = 24
+6! = 1 * 2 * 3 * 4 * 5 * 6 = 720
+```
+
+**Hinweis:** Die Fakultät von n entspricht ungefähr 1,6^n, was bedeutet, das sie exponentiell wächst, weshalb aus Zeitgründen, das Programm nur mit niedrigen Zahlen getestet werden sollte.
+
+## Aufgabe 2: Die gaußsche Summe
+Die gaußsche Summe von einer natürlichen Zahl n ist die Summe aller natürlicher Zahlen von 1 bis einschließlich n.
+Wie zu sehen ist hat die gaußsche Summe große Ähnlichkeit mit der Fakultät, weshalb der Code nicht so stark verändert werden muss. Allerdings hat die gaußsche Summe den Vorteil, dass man sie nicht iterativ berechnen muss. Gauß soll für folgende Berechnungsmethode verantwortlich sein:
+`n + n-1 + n-2 ... + 3 + 2 + 1 = n*(n+1)/2 `
+
+**Schreibe ein Programm, dass die gaußsche Summe eine Zahl n iterativ und mit Hilfe der gaußschen Formel berechnet und vergleiche die Ergebnisse (sollten Diskrepanzen auftreten ist Dir ein Fehler unterlaufen).**
+
+## Aufgabe 3: Bubblesort
+Bubblesort ist ein Sortieralgorithmus, das heißt eine Prozedur um Folgen zu sortieren.
+Angenommen wir wollen eine Liste mit n Elementen, die jeweils ganze Zahlen sind, sortieren.
+``` python
+liste = [7, 4, 6, 2, 8, 1, 3, 5]
+```
+Nun vergleichen wir jeweils zwei benachbarte Elemente:
+```
+7 > 4
+4 < 6
+6 > 2
+2 < 8
+8 > 1
+1 < 3
+3 > 5
+```
+Wenn das vordere Element größer als das hintere Element ist, werden diese vertauscht. Bei jeder Vertauschung merken wir uns, das wir eine Vertauschung gemacht haben. Dies wird solange durchgeführt, bis es in einem Durchgang keine Vertauschung mehr gab. Dann ist die Liste sortiert.
+```
+0 [7, 4, 6, 2, 8, 1, 3, 5] # Vertauscht = True
+1 [4, 6, 2, 7, 1, 3, 5, 8] # Vertauscht = True
+2 [4, 2, 6, 1, 3, 5, 7, 8] # Vertauscht = True
+3 [2, 4, 1, 3, 5, 6, 7, 8] # Vertauscht = True
+4 [2, 1, 3, 4, 5, 6, 7, 8] # Vertauscht = True
+5 [1, 2, 3, 4, 5, 6, 7, 8] # Vertauscht = False
+```
+Im Ordner Level_03/Vorgaben findet sich eine Datei "bubblesort.py". Diese erstellt eine Liste mit `n`Elementen und durchmischt diese, das bedeutet, dass kein Element doppelt auftauchen wird.
+ **Schreibe ein Programm in diese Datei, dass die Liste `unsortet_list` mit Hilfe von Bubblesort sortiert.**
diff --git a/Level_03/bubblesort.py b/Level_03/Vorgaben/bubblesort.py
similarity index 98%
rename from Level_03/bubblesort.py
rename to Level_03/Vorgaben/bubblesort.py
index 7a62480..43c4a41 100755
--- a/Level_03/bubblesort.py
+++ b/Level_03/Vorgaben/bubblesort.py
@@ -5,7 +5,7 @@ def get_random_list(n: int) -> list:
result = list(range(n))
random.shuffle(result)
return result
-
+
n = int(input("Länge der Liste: "))
unsortet_list = get_random_list(n)
diff --git a/Level_03/dictionaries.py b/Level_03/dictionaries.py
deleted file mode 100755
index fb1e5dc..0000000
--- a/Level_03/dictionaries.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/env python3
-
-# Listentypen:
-
-# 3. Das Dictionary:
-
-# Ein Dictionary ist eine unsortierte Liste, in der
-# immer ein /Wert einem /Schlüssel zugeordnet ist.
-
-# Ein Dictionary wird über geschweifte Klammern
-# definiert:
-dictionary = {"Eins": "one", "Zwei": "two"} # type: dict
-dictionary = dict([("Eins", "one"), ("Zwei", "two")])
-print(dictionary)
-
-# Auf einen value wird mit Hilfe des keys zu-
-# gegriffen:
-print(dictionary["Eins"])
-# dictionary["nicht da"]: schlägt fehl
-dictionary.get("nicht da")
-
-# Ein neues Key-Value-Paar wird erstellt,
-# indem auf ein nicht-existierenden value zu-
-# gegriffen wird und dieser definiert wird:
-dictionary["Wasser"] = "water"
-print(dictionary)
-# Als keys geeignet sind zum Beispiel: Integer, Strings, Tupel, Boolean
-
-# Einträge löschen
-del dictionary["Wasser"]
-
-# Mit len() lässt sich die Länge ausgeben:
-print(len(dictionary))
-
-
-# Die Schlüssel eines Dictionarys können als Liste zurückgegeben werden:
-print(dictionary.keys())
-
-
-# ebenso wie die Values:
-print(dictionary.items())
diff --git a/Level_03/for.py b/Level_03/for.py
deleted file mode 100755
index 54c0a3a..0000000
--- a/Level_03/for.py
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/env python3
-
-# Schleifen:
-
-# 2. Die for-Schleife:
-
-# Die for-Schleife durchläuft ein iterierbares
-# Objekt. Alle oben genannten Listen sind solche
-# iterierbaren Objekte.
-String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-
-for char in String: # type: str
- print(char)
-
-# Beim Durchlaufen eines Dictionary wird jedoch nur
-# der key zurückgegeben:
-Dictionary = {"one": "Eins", "two": "Zwei", "three": "drei"}
-for key in Dictionary:
- print(key)
- print(Dictionary[key])
-
-# besser:
-for key, value in Dictionary.items():
- print(key, value)
-
-# Ebenso kann ein Tupel oder eine Liste durchlaufen werden
-
-# Mit dem Befehl range() erschafft man ein iterierbares
-# Objekt, das mit Zahlen gefüllt ist:
-R = range(10)
-print(list(R))
-
-# Dabei kann man auch den Startwert und die Schrittweite
-# angeben:
-R = range(0, 101, 2)
-print(list(R))
-
-# Somit kann man eine Zählschleife implementieren:
-R = range(10)
-for i in R:
- print(i)
-
-# oder:
-
-for i in range(10):
- print(i)
diff --git a/Level_03/listen.py b/Level_03/listen.py
deleted file mode 100755
index 70bd296..0000000
--- a/Level_03/listen.py
+++ /dev/null
@@ -1,92 +0,0 @@
-#!/usr/bin/env python3
-
-# Listentypen:
-
-# 1. Die Liste:
-
-# Eine Liste ist eine beliebig lange Folge von beliebigen Objekten
-
-# Eine Liste wird mit Hilfe von eckigen Klammern definiert.
-liste = [0, "foo"] # type: list
-print(liste)
-
-
-# Mit list() lässt sich bspw. ein String in einen Liste verwandeln:
-String = "ABCDEFGHIJ"
-print(list(String))
-
-
-# Auf ein Element in einer Liste wird über dessen Index
-# zugegriffen. Der Index ist die Stelle, an der das Element
-# steht.
-# Wichtig: Die Zählung des Index beginnt mit 0,
-# daher ist der Index des ersten Elements 0.
-# Liste: [0, "foo"]
-# Index: 0 1
-
-element = liste[0]
-print(element)
-
-# Die Funktion liefert für viele Objekte die Länge zurück.
-# Bei einer Liste enspricht die Länge der Anzahl an Elementen.
-l = len(liste) # type: int
-print(l)
-
-
-# Die append()-Methode fügt einer Liste ein beliebiges
-# Element hinzu:
-liste.append("bar")
-liste += ["bar"] # tut das gleiche
-print(liste)
-
-
-# Statt ein Objekt am Ende einer Liste anzufügen, ist es auch möglich,
-# es an einem Index einzusetzen. Dabei wird das Objekt vor dem Index
-# eingesetzt.
-liste.insert(0, "test")
-print(liste)
-
-
-# Die pop()-Methode löscht das Objekt an dem Index in der Liste.
-# Ist kein Index angegeben lösht pop() das letzte Element
-liste.pop()
-print(liste)
-
-# alternativ per Index löschen
-del liste[1]
-
-# Ein Element kann aber nicht nur über den Index gelöscht werden, sondern
-# auch über das Objekt, es wird allerdings nur das erste Auftreten des
-# Objektes gelöscht. Dabei wird ein Fehler geworfen, falls das Objekt
-# nicht in der Liste vorhanden ist.
-liste.remove('bar') # type: None
-print(liste)
-
-
-# Element über den Wert finden
-liste.index('foo')
-
-
-# Um festzustellen, wie oft ein Wert in einer Liste vorhanden ist kann
-# die count()-Methode verwendet werden.
-liste3 = list("aabbbcccc")
-print(liste3.count("a"))
-print(liste3.count("d"))
-
-# mit in kann man herausfinden, ob ein Element in einer Liste enthalten ist
-print("a" in liste3)
-
-# Eine Liste kann mit sort() sortiert werden:
-liste2 = [9,6,3,2,7]
-liste2.sort() # type: None
-print(liste2)
-
-
-# Auf die einzelnen Zeichen eines Strings kann ebenfalls über den Index
-# zugegriffen werden, wie bei einer Liste.
-String = "ABCDEFGHIJKLMNOPQRSTUVW"
-print(String)
-print(String[4])
-
-# Reversing
-print(String[::-1])
diff --git a/Level_03/sets.py b/Level_03/sets.py
deleted file mode 100644
index 4810587..0000000
--- a/Level_03/sets.py
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/usr/bin/env python3
-
-# Sets sind Mengen (im mathematischen Sinne), also:
-# * Elemente können maximal einfach vorkommen
-# * Es gibt keine Reihenfolge.
-
-s = {1, 2, 2, 2, 2, 2, 3, 'foo'}
-s.update({5})
-s
-set('foo')
-type({})
diff --git a/Level_03/tupel.py b/Level_03/tupel.py
deleted file mode 100755
index bee9e8d..0000000
--- a/Level_03/tupel.py
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env python3
-
-# Listentypen:
-
-# 2. Das Tuple:
-
-# Ein Tuple ist eine unveränderliche und unsortierte
-# Folge von Elementen.
-
-# Ein Tuple wird über runde Klammern definiert:
-Tuple = ("foo", "bar") # type: tuple
-print(Tuple)
-
-# man kann auch vorhandene Werte in Tupel umwandeln
-print(tuple('foo'))
-
-# Mit einem Index kann auf ein Element zugegriffen
-# werden:
-print(Tuple[0])
-
-# Mit dem len()-Befehl lässt sich die Länge aus-
-# geben:
-print(len(Tuple))
diff --git a/Level_03/while.py b/Level_03/while.py
deleted file mode 100755
index 64247ab..0000000
--- a/Level_03/while.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env python3
-
-# Schleifen:
-
-# 1. Die while-Schleife:
-
-# Im Kopf der while-Schleife steht eine Bedingung.
-# Wenn die Begindung erfüllt ist, durchläuft die while-Schleife ihren Bauch.
-# Danach prüft sie erneut die Bedingung. Und das immer so weiter.
-counter = 0
-
-while counter < 10:
- counter += 1
-
-# Endlosschleife:
-"""
-while True:
- print("foo")
-"""
-
-# Schleifen vorzeitig beenden
-
-counter = 0
-while counter < 4:
- counter += 1
- print(counter)
- if counter == 5:
- break
-else:
- print("Die Schleife ist bis zum Ende durchgelaufen.")
-
-# Schleifendurchläufe überspringen
-counter = 0
-while counter < 10:
- counter += 1
- if counter == 5:
- continue
- print(counter)
diff --git a/Level_04/loremipsum.py b/Level_04/Beispielcode/loremipsum.py
similarity index 100%
rename from Level_04/loremipsum.py
rename to Level_04/Beispielcode/loremipsum.py
diff --git a/Level_04/loremipsum.txt b/Level_04/Beispielcode/loremipsum.txt
similarity index 100%
rename from Level_04/loremipsum.txt
rename to Level_04/Beispielcode/loremipsum.txt
diff --git a/Level_04/loremipsvm.txt b/Level_04/Beispielcode/loremipsvm.txt
similarity index 100%
rename from Level_04/loremipsvm.txt
rename to Level_04/Beispielcode/loremipsvm.txt
diff --git a/Level_04/Level_4.ipynb b/Level_04/Level_4.ipynb
new file mode 100644
index 0000000..cbecb83
--- /dev/null
+++ b/Level_04/Level_4.ipynb
@@ -0,0 +1,212 @@
+{
+ "cells": [
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Level 4\n",
+ "\n",
+ "In diesem Level geht es um Dateien.\n",
+ "\n",
+ "[`pathlib`](https://docs.python.org/3/library/pathlib.html) ist wahrscheinlich die beste Möglichkeit, mit Pfaden und Dateien zu hantieren."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "from pathlib import Path\n",
+ "\n",
+ "# Referenz auf die Datei \"loremipsum.txt\"\n",
+ "ipsum = Path(\"Beispielcode\") / Path(\"loremipsum.txt\")\n",
+ "\n",
+ "# Existiert diese Datei? Ist es überhaupt eine Datei?\n",
+ "ipsum.exists() and ipsum.is_file()"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Wenn wir ein Referenz auf eine Datei haben, wollen wir mit der Datei auch etwas machen.\n",
+ "Das einfachste ist wahrscheinlich, die Datei komplett einzulesen:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.\\nVivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.\\nSuspendisse lectus leo, consectetur in tempor sit amet, placerat quis neque. Etiam luctus porttitor lorem, sed suscipit est rutrum non. Curabitur lobortis nisl a enim congue semper. Aenean commodo ultrices imperdiet. Vestibulum ut justo vel sapien venenatis tincidunt. Phasellus eget dolor sit amet ipsum dapibus condimentum vitae quis lectus. Aliquam ut massa in turpis dapibus convallis. Praesent elit lacus, vestibulum at malesuada et, ornare et est. Ut augue nunc, sodales ut euismod non, adipiscing vitae orci. Mauris ut placerat justo. Mauris in ultricies enim. Quisque nec est eleifend nulla ultrices egestas quis ut quam. Donec sollicitudin lectus a mauris pulvinar id aliquam urna cursus. Cras quis ligula sem, vel elementum mi. Phasellus non ullamcorper urna.\\nClass aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In euismod ultrices facilisis. Vestibulum porta sapien adipiscing augue congue id pretium lectus molestie. Proin quis dictum nisl. Morbi id quam sapien, sed vestibulum sem. Duis elementum rutrum mauris sed convallis. Proin vestibulum magna mi. Aenean tristique hendrerit magna, ac facilisis nulla hendrerit ut. Sed non tortor sodales quam auctor elementum. Donec hendrerit nunc eget elit pharetra pulvinar. Suspendisse id tempus tortor. Aenean luctus, elit commodo laoreet commodo, justo nisi consequat massa, sed vulputate quam urna quis eros. Donec vel. \\n'"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "ipsum.read_text()"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "(bzw. `read_bytes` für Binärdateien)\n",
+ "\n",
+ "Das funktioniert für sehr kleine Dateien; bei großen Dateien geht das aber leider nicht mehr sinnvoll.\n",
+ "Mit `open` bekommen wir eine Referenz auf eine offene Datei, was uns viel mehr Spielraum gibt:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "0\n",
+ "Lorem\n",
+ "5\n",
+ "2\n",
+ "2\n",
+ "rem i\n"
+ ]
+ }
+ ],
+ "source": [
+ "lorem_ipsum = (Path(\"Beispielcode\") / Path(\"loremipsum.txt\")).open(\"r\")\n",
+ "print(lorem_ipsum.tell())\n",
+ "print(lorem_ipsum.read(5))\n",
+ "print(lorem_ipsum.tell())\n",
+ "print(lorem_ipsum.seek(2))\n",
+ "print(lorem_ipsum.tell())\n",
+ "print(lorem_ipsum.read(5))\n",
+ "lorem_ipsum.close()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Mit `write` lässt sich entsprechend Text an die aktuelle Position des Zeigers schreiben."
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Mit `write_text` bzw. `open(\"w\")` lässt sich eine Datei entsprechend zum (Über-)Schreiben öffnen:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "test = Path(\"test.txt\")\n",
+ "test.write_text(\"blub\")\n",
+ "test.unlink() # löscht die Datei wieder"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Wenn die Datei nicht existiert (hat), wurde sie durch das `write_text` angelegt."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Mit `open(\"a\")` lässt sich auch Text an eine Datei anhängen: Der Zeiger wird direkt beim Öffnen auf das Dateiende gelegt. Wenn die Datei nicht existiert, wird sie auch hierbei angelegt."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Auch praktisch: mit `writeline` bzw. `writelines` lassen sich ganze Zeilen in die Datei schreiben:\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "content = 10 * [\"spam\"]\n",
+ "filename = \"spam.txt\"\n",
+ "file_object = open(filename, \"w\")\n",
+ "file_object.writelines(content)\n",
+ "file_object.close()"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Ordner gibt es natürlich auch. Wir können sie z.B. anlegen oder löschen:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "test_dir = Path(\"testdir\")\n",
+ "test_dir.mkdir()\n",
+ "test_dir.rmdir()"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.3"
+ },
+ "orig_nbformat": 4
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/Level_04/Aufgaben/monty.txt "b/Level_04/L\303\266sungen/monty.txt"
similarity index 100%
rename from Level_04/Aufgaben/monty.txt
rename to "Level_04/L\303\266sungen/monty.txt"
diff --git a/Level_04/Aufgaben/monty_a.py "b/Level_04/L\303\266sungen/monty_a.py"
similarity index 91%
rename from Level_04/Aufgaben/monty_a.py
rename to "Level_04/L\303\266sungen/monty_a.py"
index a03046e..d527110 100755
--- a/Level_04/Aufgaben/monty_a.py
+++ "b/Level_04/L\303\266sungen/monty_a.py"
@@ -1,8 +1,8 @@
#!/usr/bin/env python3
-# Dies ist eine Beispielslösung für Aufgabe 2a aus Level 4
+# Dies ist eine Beispiellösung für Aufgabe 2a aus Level 4
# Schreibe ein Programm, dass:
-# die Datei `monty.txt` aus dem Coderepository einliest,
+# die Datei `monty.txt` aus dem Code-Repository einliest,
# * eine Worthäufigkeitstabelle erstellt,
# * eine Buchstabenhäufigkeitstabelle erstellt,
# * die Worthäufigkeiten lesbar formatiert in "words.txt" abspeichert,
@@ -22,7 +22,7 @@
text = file_obj.read() # Einlesen des Textes
file_obj.close() # Schließen des Dateiobjekts
else:
- print("Die Datei {} existiert nicht.".format(path_text))
+ print(f"Die Datei {path_text} existiert nicht.")
exit()
# Alternativ:
diff --git a/Level_04/Aufgaben/monty_b.py "b/Level_04/L\303\266sungen/monty_b.py"
similarity index 75%
rename from Level_04/Aufgaben/monty_b.py
rename to "Level_04/L\303\266sungen/monty_b.py"
index 908d755..3478c27 100755
--- a/Level_04/Aufgaben/monty_b.py
+++ "b/Level_04/L\303\266sungen/monty_b.py"
@@ -1,10 +1,10 @@
#!/usr/bin/env python3
-# Dies ist eine Beispielslösung für Aufgabe 2b aus Level 4
+# Dies ist eine Beispiellösung für Aufgabe 2b aus Level 4
# * einen Integer n einliest,
# * die Häufigkeitstabelle der Buchstaben aus der, zuvor erstellten, Datei
# "chars.txt" einliest und
-# * die n häufigsten und die n seltesten Buchstaben ausgibt.
+# * die n häufigsten und die n seltenen Buchstaben ausgibt.
from pathlib import Path
@@ -20,7 +20,7 @@
# Einlesen der Datei:
if not path.exists():
- print("Die Datei {} wurde nicht gefunden.".format(path))
+ print(f"Die Datei {path} wurde nicht gefunden.")
exit()
table = {}
@@ -47,7 +47,7 @@
tmp.remove(max_entry)
-# Ausgeben der n häufigsten und n seltesten Buchstaben:
+# Ausgeben der n häufigsten und n seltenen Buchstaben:
common = []
rare = []
@@ -57,8 +57,8 @@
for entry in table[-(n+1):-1]:
rare.append(entry[0])
-print("Die {} häufigsten Buchstaben sind: ".format(n))
+print(f"Die {n} häufigsten Buchstaben sind: ")
print(common)
-print("Die {} seltesten Buchstaben sind: ".format(n))
+print(f"Die {n} seltenen Buchstaben sind: ")
print(rare)
diff --git a/Level_04/Aufgaben/monty_c.py "b/Level_04/L\303\266sungen/monty_c.py"
similarity index 86%
rename from Level_04/Aufgaben/monty_c.py
rename to "Level_04/L\303\266sungen/monty_c.py"
index 153d978..8287795 100755
--- a/Level_04/Aufgaben/monty_c.py
+++ "b/Level_04/L\303\266sungen/monty_c.py"
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
-# Dies ist eine Beispielslösung für Aufgabe 2c aus Level 4
+# Dies ist eine Beispiellösung für Aufgabe 2c aus Level 4
# Schreiben Sie ein Programm, dass:
# * die Datei `monty.txt` öffnet und den Inhalt einliest,
# * im eingelesenen Inhalt jedes Auftauchen des Wortes `Python` durch `PYTHON`
@@ -20,7 +20,7 @@
text = file_obj.read()
file_obj.close()
else:
- print("Die Datei {} existiert nicht.".format(path_text))
+ print(f"Die Datei {path_text} existiert nicht.")
exit()
# 2. "Python" ersetzen:
diff --git a/Level_04/quine.py "b/Level_04/L\303\266sungen/quine.py"
similarity index 100%
rename from Level_04/quine.py
rename to "Level_04/L\303\266sungen/quine.py"
diff --git a/Level_04/README.md b/Level_04/README.md
new file mode 100644
index 0000000..f3dd538
--- /dev/null
+++ b/Level_04/README.md
@@ -0,0 +1,35 @@
+# Level 4 Aufgaben
+## Aufgabe 1 (Quine)
+Schreibe ein Programm, dass seinen Quellcode ausgibt.
+
+## Aufgabe 2 (Monty Python)
+### a)
+**Schreibe ein Programm, dass:**
+
+* die Datei `monty.txt` aus dem Code-Repository einliest,
+* eine Worthäufigkeitstabelle erstellt,
+* eine Buchstabenhäufigkeitstabelle erstellt,
+* die Worthäufigkeiten lesbar formatiert in "words.txt" abspeichert,
+* und die Buchstabenhäufigkeiten lesbar formatiert in "chars.txt" speichert.
+
+### b)
+**Schreibe ein Programm, dass:**
+
+* einen Integer `n` einliest,
+* die Häufigkeitstabelle der Buchstaben aus der, zuvor erstellten, Datei `chars.txt`einliest,
+* die `n` häufigsten und die `n` seltenen Buchstaben ausgibt.
+
+### c)
+**Schreibe ein Programm, dass:**
+
+* die Datei `monty.txt` öffnet und den Inhalt einliest,
+* im eingelesenen Inhalt jedes Auftauchen des Wortes `Python` durch `PYTHON` ersetzt,
+* und den entstandenen Text in einer Datei `MONTY.txt` (auf Windows unter `monty_upper.txt`) speichert
+
+## Tipps:
+
+1. Überlege dir für Aufgabe 2 eine sinnvolle Formatierung, um die
+Tabellen in den Dateien zu speichern.
+2. Überlege dir eine Methode, um die Wörter zählen zu können
+3. Bedenke, dass für die Häufigkeit von Buchstaben irrelevant ist,
+ob diese groß oder klein geschrieben wurden.
diff --git a/Level_04/dateien.py b/Level_04/dateien.py
deleted file mode 100755
index 887a0f3..0000000
--- a/Level_04/dateien.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env python3
-
-# Level 4: Dateien
-
-# Pathlib (https://docs.python.org/3/library/pathlib.html) ist die beste Möglichkeit,
-# mit Pfaden und Dateien zu hantieren.
-
-from pathlib import Path
-
-# Existiert eine Datei?
-
-Path("lorem_ipsum.txt").exists() # type: bool
-# OUT: False
-Path("loremipsum.txt").exists()
-# OUT: True
-
-# einen Ordner erstellen
-
-test_dir = Path("test")
-test_dir.mkdir()
-
-# eine Datei auslesen
-
-# schneller: print(Path("loremipsum.txt").read_text())
-lorem_ipsum = Path("loremipsum.txt").open("r")
-print(lorem_ipsum.read())
-lorem_ipsum.close()
-
-# eine Datei schreiben
-
-# schneller: (test_dir / Path("test.txt")).write_text("total toller Text")
-test = (test_dir / Path("test.txt")).open("w")
-test.write("total toller Text") # type: int
-# OUT: 17
-test.close()
-
-# eine Datei löschen
-
-(test_dir / Path("test.txt")).unlink()
-
-# einen Ordner löschen
-
-test_dir.rmdir()
diff --git a/Level_05/Beispielcode/calculator05.py b/Level_05/Beispielcode/calculator05.py
index ddcd497..c9fab20 100644
--- a/Level_05/Beispielcode/calculator05.py
+++ b/Level_05/Beispielcode/calculator05.py
@@ -1,4 +1,4 @@
-u"""
+"""
Das folgende Programm ist ein einfacher Taschenrechner.
Nach dem Eingeben zweier Zahlen kann eine Operation ausgewählt werden.
@@ -6,13 +6,13 @@
"""
# Für die Berechnung der Quadratwurzel wird die math Bibliothek benötigt,
-# desweiteren wird zum vorzeitigen Beenden die sys Bibliothek benötigt.
+# des Weiteren wird zum vorzeitigen Beenden die sys Bibliothek benötigt.
import math
import sys
def menu():
- u"""Zeigt ein Menü an."""
+ """Zeigt ein Menü an."""
# Zuerst eine Willkommensnachricht
print()
print("Dies ist ein einfacher Taschenrechner.")
@@ -22,7 +22,7 @@ def menu():
print()
counter = 0
for fun in operations:
- print("{} {}".format(counter, fun.__name__))
+ print(f"{counter} {fun.__name__}")
counter += 1
print("Bitte eine Zahl für eine der Operationen angeben")
choice = input(":")
@@ -36,7 +36,7 @@ def menu():
def add():
- u"""
+ """
Addiert zwei eingegebene Zahlen.
Die Zahlen können sowohl ganze Zahlen (integer) oder Fließkommazahlen
@@ -45,11 +45,11 @@ def add():
sum1 = input("Bitte den ersten Summanden eingaben: ")
sum2 = input("Bitte den zweiten Summanden eingeben: ")
result = float(sum1) + float(sum2)
- print("{} + {} = {}".format(sum1, sum2, result))
+ print(f"{sum1} + {sum2} = {result}")
def sum():
- u"""
+ """
Summiert eine Menge an Zahlen auf.
Die Summanden können sowohl ganze Zahlen (integer) oder Fließkommazahlen
@@ -60,11 +60,11 @@ def sum():
result = 0.0
for i in values:
result += float(i)
- print("sum({}) = {}".format(values, result))
+ print(f"sum({values}) = {result}")
def product():
- u"""
+ """
Multipliziert eine Menge an Zahlen auf.
Die Faktoren können sowohl ganze Zahlen (integer) oder Fließkommazahlen
@@ -75,11 +75,11 @@ def product():
result = 1.0
for i in values:
result *= float(i)
- print("product({}) = {}".format(values, result))
+ print(f"product({values}) = {result}")
def difference():
- u"""
+ """
Subtrahiert eine Zahl von einer anderen.
Minuend und Subtrahend können sowohl ganze Zahlen (integer) oder
@@ -88,11 +88,11 @@ def difference():
minu = input("Bitte den Minuenden eingeben: ")
subt = input("Bitte den Subtrahenden eingeben: ")
result = float(minu) - float(subt)
- print("{} - {} = {}".format(minu, subt, result))
+ print(f"{minu} - {subt} = {result}")
def quotient():
- u"""
+ """
Teilt einen Divisor durch einen Dividenden.
Dividend und Divisor können sowohl ganze Zahlen (integer), als auch
@@ -104,11 +104,11 @@ def quotient():
print("Ungültige Divisor.")
return
result = float(divid) / float(divis)
- print("{} / {} = {}".format(divid, divis, result))
+ print(f"{divid} / {divis} = {result}")
def modulo():
- u"""
+ """
Gibt das Ergebnis einer Modulo Division zurück.
Dividend und Divisor müssen ganze Zahlen sein. 0 ist als Divisor nicht
@@ -120,11 +120,11 @@ def modulo():
print("Ungültige Divisor.")
return
result = int(divid) % int(divis)
- print("{} % {} = {}".format(divid, divis, result))
+ print(f"{divid} % {divis} = {result}")
def sqrt():
- u"""
+ """
Berechnet die Quadratwurzel einer eingegebenen Zahl.
Die Zahl kann sowohl eine ganze Zahl (integer) als auch eine Fließkommazahl
@@ -132,11 +132,11 @@ def sqrt():
"""
radiant = input("Bitte eine Zahl eingeben: ")
result = math.sqrt(float(radiant))
- print("sqrt({}) = {}".format(radiant, result))
+ print(f"sqrt({radiant}) = {result}")
def power():
- u"""
+ """
Berechnet eine Potenz.
Basis und Exponent können sowohl ganze Zahlen (integer), als auch
@@ -145,11 +145,11 @@ def power():
base = input("Bitte die Basis eingeben: ")
exp = input("Bitte den Exponenten eingeben: ")
result = pow(float(base), float(exp))
- print("{} ^ {} = {}".format(base, exp, result))
+ print(f"{base} ^ {exp} = {result}")
def fak():
- u"""
+ """
Berechnet die Fakultät einer Zahl.
Die Zahl sollte eine positive ganze Zahl (natürliche Zahl) sein.
@@ -158,11 +158,11 @@ def fak():
result = 1
for i in range(2, int(x) + 1):
result *= i
- print("{}! = {}".format(x, result))
+ print(f"{x}! = {result}")
def help():
- u"""
+ """
Ruft das Hilfe Menü auf.
Das Hilfe Menü zeigt die Docstrings der einzelnen Funktionen an.
@@ -173,11 +173,11 @@ def help():
def quit():
- u"""Beendet das Programm."""
+ """Beendet das Programm."""
sys.exit(0)
-# Die Funktionen für die Opertationen werden in einem Tuple gespeichert
+# Die Funktionen für die Operationen werden in einem Tuple gespeichert
operations = (
add,
sum,
diff --git a/Level_05/fibonacci.py b/Level_05/Beispielcode/fibonacci.py
similarity index 91%
rename from Level_05/fibonacci.py
rename to Level_05/Beispielcode/fibonacci.py
index 1327d18..8891d39 100755
--- a/Level_05/fibonacci.py
+++ b/Level_05/Beispielcode/fibonacci.py
@@ -9,7 +9,7 @@
# Die Fibonacci-Folge ist rekursiv definiert
# - trotzdem ist die rekursive Berechnung ziemlich ineffizient im Vergleich zur Iterativen;
# siehe dazu https://github.com/pythonfoo/pythonfooLite/wiki/Rekursion_Vs._Iteration.
-# Eine wesentlich perfomantere Version findet sich in Level 7.
+# Eine wesentlich performantere Version findet sich in Level 7.
def fib(n: int) -> int:
diff --git a/Level_05/ggT.py b/Level_05/Beispielcode/ggT.py
similarity index 98%
rename from Level_05/ggT.py
rename to Level_05/Beispielcode/ggT.py
index 90eebf4..f14f084 100755
--- a/Level_05/ggT.py
+++ b/Level_05/Beispielcode/ggT.py
@@ -11,18 +11,18 @@ def ggT(a: int, b: int) -> int:
# Wir nehmen einfach den Betrag.
a = abs(a)
b = abs(b)
-
+
# a soll größer sein als b.
# Falls das nicht bereits der Fall ist,
# tauschen wir die beiden einfach.
if b > a:
return ggT(b, a)
-
+
# Wenn b Null ist, sind wir fertig und a ist der ggT.
# Ansonsten müssen wir (nochmal) rechnen.
if b == 0:
return a
-
+
# Teile a mit Rest durch b;
# setze a auf b
# und b auf den Rest.
diff --git a/Level_05/Interessantes.md b/Level_05/Interessantes.md
new file mode 100644
index 0000000..5d5ac29
--- /dev/null
+++ b/Level_05/Interessantes.md
@@ -0,0 +1,18 @@
+# Level 5.5
+Oder auch, Dinge, die auch interessant und/oder wichtig sind, in bisherigen Leveln aber keinen Platz gefunden haben.
+## IDE, Texteditor oder doch Interpreter?
+Es ist uns egal, wie ihr euren Code schreibt. Es ist möglich einen Texteditor zu benutzen in der Konsole zu benutzen, wie zum Beispiel `vim` oder `nano`, einen Texteditor mit graphischer Oberfläche, wie zum Beispiel `gedit`, einen Texteditor mit Syntax Hervorhebung (engl. syntax highlighting), wie zum Beispiel `notepad++` oder `Sublime Text`, eine IDE, wie zum Beispiel `PyCharm` oder `geany` oder den Code in den Interpreter zu schreiben. Uns ist nur wichtig, dass ihr mit dem entsprechenden Programm Code schreiben könnt. Natürlich können wir euch sagen, welches Programm wir benutzen, was uns daran gefällt und was nicht. Wir können euch sagen, was wir bei verschiedenen Programmen besonders praktisch finden, sei es Autovervollständigung, PEP 8 Check, Syntax Hervorhebung, GitHub Integration oder ähnliches. Wir können euch wahrscheinlich bei Problemen mit euren Texteditor/IDE der Wahl natürlich am ehesten helfen, wenn wir das entsprechende Programm kennen.
+
+### Beispielprogramme:
+#### Texteditor in der Konsole
+* vi
+* vim
+* nano
+#### Texteditor mit graphischer Oberfläche
+* gedit
+* sublime text (2/3)
+* notepad++
+* Atom
+#### IDE
+* PyCharm
+* geany
\ No newline at end of file
diff --git a/Level_05/Level_5.ipynb b/Level_05/Level_5.ipynb
new file mode 100644
index 0000000..5689789
--- /dev/null
+++ b/Level_05/Level_5.ipynb
@@ -0,0 +1,488 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "8a8cb1fc",
+ "metadata": {},
+ "source": [
+ "Mit Hilfe von Funktionen ist es möglich Codeabschnitte bzw. kleinere Programmteile zu speichern und wiederzuverwenden. So wird die Komplexität stark reduziert.\n",
+ "Durch Funktionen muss du dich beim Schreiben eines Hello-World-Programms nicht erst mit der Kommunikation mit dem System Output kümmern oder um die Dekodierung deiner Eingabe. Du kannst einfach die print() Funktion benutzen, die alles wichtige für dich erledigt, sodass du nur noch Text eingeben musst.\n",
+ "Python liefert nun eine ganze Menge grundlegender Funktionen mit, was dir die Arbeit unglaublich erleichtert. Viele dieser Funktionen haben wir bereits in den vorherigen Levels behandelt und sie auch als Funktionen bezeichnet, ohne näher darauf einzugehen.\n",
+ "Beispiele für diese grundlegenden Funktionen sind:\n",
+ "\n",
+ "* `print()`\n",
+ "* `len()`\n",
+ "* `input()`\n",
+ "\n",
+ "Aber auch viele Funktionen, die zu einem Objekt gehören (solche Funktionen nennen wir \"Methoden\", dazu mehr im nächsten Level):\n",
+ "\n",
+ "* `list.append()`\n",
+ "* `list.count()`\n",
+ "* `list.pop()`\n",
+ "\n",
+ "Um aber nicht auf die Menge der mitgelieferten oder aus Drittquellen bezogenen (auch dazu mehr im nächsten Level) Funktionen beschränkt zu sein, bietet Python wie viele andere Programmiersprachen, die Möglichkeit eigene Funktionen zu definieren. Dadurch kann ich kleine Teile des Programms vorhalten und sie genau dann benutzen, wenn ich sie brauche.\n",
+ "Der Name Funktion mag andeuten, dass es sich dabei um etwas ähnliches wie eine mathematische Funktion handelt, das ist jedoch nur zum Teil richtig. Während eine mathematische Funktion einen festen Definitionsbereich besitzt, der aus mathematischen Objekten beruht, nimmt eine Funktion in Python beliebige Objekte entgegen und verarbeitet diese. Mit einer Python-Funktion kann ich beliebige mathematisch Funktionen definieren, andersherum ist das deutlich schwieriger. Die Analogie des Ablaufs oder der Prozedur ist daher eventuell angebrachter. Wir werden im folgenden trotzdem den Begriff Funktion verwenden."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7aeaaa2c",
+ "metadata": {},
+ "source": [
+ "## Die Funktionsdefinition\n",
+ "Im Folgenden wollen wir eine Funktion definieren, die genau das macht was ein Hello-World-Programm auch macht: \"Hello World\" ausgeben"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "1bd2230e",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "hello world\n"
+ ]
+ }
+ ],
+ "source": [
+ "def hello_world():\n",
+ " print(\"hello world\")\n",
+ "hello_world()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5e5615bd",
+ "metadata": {},
+ "source": [
+ "`def`ist ein Schlüsselwort, das zu Beginn einer Funktionsdefinition steht. Danach folgt der Funktionsname `hello_world`, für den die gleichen syntaktischen Anforderungen gelten, wie für Variablennamen, da `hello_world`in diesem Fall eine Variable ist. Demnach kann eine Funktion auch überschrieben werden, wie jede andere Variable auch. Darauf folgt eine leere runde Klammer in die Funktionsparameter eingetragen werden könnten. Darauf folgt ein Doppelpunkt und die Funktionssignatur ist abgeschlossen. Der darauf folgende Block ist eingerückt und muss zwangsweise Code enthalten. Nach der Funktionsdefinition wird die Funktion über ihren Namen, bzw. den Namen ihrer Variable, in dem Fall `hello_world`aufgerufen. Die runden Klammern am Ende der des Funktionsnamens stehen dabei für einen Aufruf und können eventuelle Parameter enthalten.\n",
+ "Diese Funktion macht aktuell noch keinen Sinn, da sie nur einen festgelegten String (\"hello world\") ausgeben kann.\n",
+ "\n",
+ "Nun wollen wir unsere Funktion ein wenig aufpeppen, indem wir ihr einen Parameter übergeben, sodass sie beliebige Strings ausgeben kann."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "eb2fce52",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Testeingabe\n"
+ ]
+ }
+ ],
+ "source": [
+ "def new_print(text):\n",
+ " print(text)\n",
+ "inp_text = input(\"Eingabe: \")\n",
+ "new_print(inp_text)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "25b92a60",
+ "metadata": {},
+ "source": [
+ "Der Parameter wurde, wie bereits erwähnt in die runden Klammern eingetragen. `text`ist nun eine Variable und steht in der Funktion zur Verfügung. Im Funktionsaufruf haben wir unserer Funktion `new_print`die Variable `inp_text` übergeben, die zu dem Zeitpunkt den String `\"Testeingabe\"` enthielt. Dieser String wurde nun ausgegeben.\n",
+ "\n",
+ "## Rückgabewerte\n",
+ "\n",
+ "In den meisten Anwendungsfällen wollen wir das Ergebnis einer Funktion allerdings nicht ausgeben, sondern zum Beispiel in einer Variablen speichern können, um es später verwenden zu können. Dafür benötigt unsere Funktion einen Rückgabewert. Mit Hilfe eines Rückgabewertes kann eine Funktion ein Objekt beliebigen Typs zurückgeben, damit es weiter benutzt werden kann. Die folgende Funktion hat nun einen anderen Anwendungsfall verfügt jedoch über einen Übergabeparameter und einen Rückgabewert."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "72e337d0",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "25"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "def square(x):\n",
+ " return x**2\n",
+ "square(5)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "302d6450",
+ "metadata": {},
+ "source": [
+ "Die Funktion `square` nimmt einen Parameter entgegen (sollte dieser weder `int` noch `float` sein, wird ein Fehler geworfen). Dieser wird nun erst quadriert und danach über das Schlüsselwort `return` zurückgegeben. Wichtig zu beachten ist, dass alles, was nach einem `return` in der selben Einrückungsebene steht, nicht mehr ausgeführt wird. Folglich kann es in einem Einrückungsblock nur ein `return` geben (natürlich kann man mehr hinschreiben, diese werden jedoch nicht ausgeführt werden und sind daher sinnlos). Ein `return`beendet also die Definition einer Funktion. Der Rückgabewert einer Funktion kann nun entweder direkt verwendet werden (wie oben im Beispiel) oder in einer Variable abgespeichert werden um später benutzt zu werden. Ebenfalls wichtig zu beachten ist, dass mit `return`immer nur ein Objekt zurückgegeben werden kann. Falls man mehrere Objekte zurückgeben möchte, sollte man sie in eine Liste, Tupel oder Dictionary packen.\n",
+ "\n",
+ "## args und kwargs\n",
+ "Bisher können wir einer Funktion einen Parameter geben und einen Rückgabewert zurückgeben lassen. Allerdings benötigen viele Anwendungsfälle Funktionen, die mehrere Objekte entgegen nehmen können, d.h. die mehrere Parameter haben können. Nun wäre der naive Ansatz, der schon bei Rückgabewerten benutzt wurde, statt mehreren Parametern eine Liste von Parametern zu übergeben. Praktischerweise ist in Python dieser Ansatz implementiert. Zuerst wollen wir aber zwei verschiedene Fälle unterscheiden:\n",
+ "\n",
+ "1. Die Menge an Parametern ist fest.\n",
+ "2. Die Menge an Parametern ist variabel\n",
+ "\n",
+ "Diese Unterscheidung ist sehr wichtig, da die Verwendung von mehreren Parametern sich danach unterscheidet."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "01d28a10",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2\n",
+ "-2\n"
+ ]
+ }
+ ],
+ "source": [
+ "def diff(a, b):\n",
+ " return a - b\n",
+ "print(diff(5, 3))\n",
+ "print(diff(3, 5))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9517e691",
+ "metadata": {},
+ "source": [
+ "Wenn ich eine feste Anzahl an Parametern benutzen möchte, kann ich diese in der Signatur auflisten. Wichtig ist dabei, dass beim Aufruf die Reihenfolge entscheidend ist. Die obige Funktion subtrahiert das Objekt der Variable `b` von dem Objekt der Variable `a`, daher sind `a` und `b` idealerweise ganze Zahlen oder Fließkommazahlen. Beim Aufruf wird das n-te Element im Aufruf dem n-ten Element der Signatur zugeordnet (hier kann man die Benutzung einer Liste oder eines Tupels erkennen).\n",
+ "\n",
+ "Nun möchte ich aber einer Funktion eine beliebige Anzahl an Parametern übergeben, weil ich zum Beispiel nicht weiß, wie viele Parameter zur Laufzeit benötigt werden."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "7e8cee93",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'01test'"
+ ]
+ },
+ "execution_count": 6,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "def string_add(*elemente):\n",
+ " result = \"\"\n",
+ " for e in elemente:\n",
+ " result += str(e)\n",
+ " return result\n",
+ "string_add(0, 1, \"test\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a518055c",
+ "metadata": {},
+ "source": [
+ "Das `*elemente` steht dabei für ein Tupel und kann innerhalb der Funktion als Tupel mit dem Variablennamen `elemente` behandelt werden. Wichtig zu wissen ist, dass `*args` auch leer sein kann, wenn keine Argumente übergeben wurden. Manchmal ist es jedoch vorteilhaft eine Funktion zu definieren, die mindestens n Parameter entgegennimmt und danach beliebig viele weitere, dabei ist es wichtig, das die `*args` Argumente in der Signatur nach den positionalen Parametern kommen."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "5b5c4ef5",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "12"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "def add_int(summand_a, summand_b, *more_summands):\n",
+ " result = summand_a + summand_b\n",
+ " for summand in more_summands:\n",
+ " result += summand\n",
+ " return result\n",
+ "add_int(1, 5, 6)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "fdaf7e63",
+ "metadata": {},
+ "source": [
+ "Noch viel praktischer ist es, wenn man Standartwerte angeben kann, die benutzt werden, wenn keine Parameter angegeben werden. Für diesen Anwendungsfall gibt keyword arguments, kurz kwargs."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "7cfc0f32",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "123456\n",
+ "123456\n"
+ ]
+ }
+ ],
+ "source": [
+ "def pwd_input(prompt=\"Passwort: \"):\n",
+ " return input(prompt)\n",
+ "print( pwd_input(\"pwd: \"))\n",
+ "print( pwd_input() )"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2afe8680",
+ "metadata": {},
+ "source": [
+ "Es ist auch möglich, eine beliebige Anzahl von keyword arguments zu benutzen. Dabei werden die Parameter als Dictionary interpretiert."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "db791f61",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "dict_keys(['test1', 'test2'])\n",
+ "dict_values(['foo', 'test'])\n"
+ ]
+ }
+ ],
+ "source": [
+ "def fun(**kwargs):\n",
+ " print(kwargs.keys())\n",
+ " print(kwargs.values())\n",
+ "fun(test1 = \"foo\", test2 = \"test\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "515dec33",
+ "metadata": {},
+ "source": [
+ "## Rekursion\n",
+ "Es ist nicht nur möglich innerhalb einer Funktion Kontrollstrukturen wie eine if-Bedingung oder eine for-Schleife benutzen, sondern auch Funktionen aufrufen und insbesondere die eigene Funktion aufrufen. Wir nennen es Rekursion, wenn eine Funktion sich selber aufruft. Rekursion kann, wie Schleifen, benutzt werden, um verschiedene mathematische Algorithmen zu implementieren. Allerdings unterscheidet sich die Nutzung von Rekursion gegenüber der Nutzung von Schleifen, bei der Implementierung von Algorithmen, insofern, dass es ein Rekursionslimit gibt, wohingegen eine while-Schleife endlos laufen kann."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "e0400629",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "3000\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "1200"
+ ]
+ },
+ "execution_count": 10,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import sys\n",
+ "print( sys.getrecursionlimit() )\n",
+ "sys.setrecursionlimit(1200)\n",
+ "sys.getrecursionlimit()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ed5247cf",
+ "metadata": {},
+ "source": [
+ "Wie oben zu sehen ist, kann das Rekursionslimit zwar geändert werden, die Tatsache, dass es ein Limit gibt, beschränkt trotzdem die Art der Algorithmen, die mit Rekursion implementiert werden können.\n",
+ "\n",
+ "### WARNUNG: LIMIT\n",
+ "Um nicht in das Rekursionslimit zu laufen, sollte Rekursion in der Praxis nur angewendet werden, wenn die Anzahl der rekursiven Aufrufe bekannt oder bekannt gering ist.\n",
+ "In realen Einsatzbereichen kommt es immer wieder zu schwer lösbaren Fehlern, wenn diesem Problem nicht rechtzeitig Aufmerksamkeit geschenkt wird.\n",
+ "\n",
+ "### WARNUNG: Kompliziert\n",
+ "Das Debuggen von Rekursiven aufrufen kann extrem Kompliziert werden. Das sollte unbedingt beachtet werden, wenn ein Programm einem realen Einsatzzweck zugeführt werden soll und ob eine Lösung mit einer Schleife nicht besser geeignet wäre."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1e2cdfb1",
+ "metadata": {},
+ "source": [
+ "# Zeit\n",
+ "\n",
+ "Dieser Abschnitt zeigt ein paar Funktionen von `time`.\n",
+ "\n",
+ "Damit kann man z.B. die aktuelle Uhrzeit abfragen:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "bf3ede3e",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Timestamp: 1763056857.404581\n",
+ "strukturierte Daten: time.struct_time(tm_year=2025, tm_mon=11, tm_mday=13, tm_hour=19, tm_min=0, tm_sec=57, tm_wday=3, tm_yday=317, tm_isdst=0)\n"
+ ]
+ }
+ ],
+ "source": [
+ "import time\n",
+ "print(\"Timestamp:\", time.time())\n",
+ "print(\"strukturierte Daten:\", time.localtime())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3ba3f394",
+ "metadata": {},
+ "source": [
+ "# mehr String-Funktionen\n",
+ "\n",
+ "## Escaping\n",
+ "\n",
+ "Es gibt Zeichen, die man nicht eingeben kann. Stattdessen lassen sich diese über\n",
+ "Backslash-Escapes benutzen:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "cc0d83bc",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"Tab:\\t#\")\n",
+ "print(\"Wal: \\N{WHALE}\")\n",
+ "print(\"\\aabc\")\n",
+ "print(\"\\\\0/\") # der Backslash selbst\n",
+ "# Rawstrings können kein escaping:\n",
+ "print(r\"\\n\")\n",
+ "print(r\"\\0/\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "bb476ec4",
+ "metadata": {},
+ "source": [
+ "## Formatting\n",
+ "\n",
+ "Mit geschweiften Klammern können Platzhalter in Strings eingesetzt werden:\n",
+ "\n",
+ "(mehr Details: )"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ccb62994",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"Das folgende Wort wird ersetzt: '{}' Der Rest nicht.\".format(\"blargh\"))\n",
+ "print(\n",
+ " \"Das folgende Wort wird ersetzt: '{} und {}' Der Rest nicht.\".format(\"foo\", \"bar\")\n",
+ ")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f8304b68",
+ "metadata": {},
+ "source": [
+ "## Aufspalten\n",
+ "\n",
+ "Mit `.split` lassen sich Strings an einem Trennzeichen aufspalten:\n",
+ "Damit lässt sich ein einfacher (aber fehleranfälliger) CSV-Parser bauen."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "3e6c1bb7",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "['a', 'b', 'cd']\n",
+ "a;b;cd\n"
+ ]
+ }
+ ],
+ "source": [
+ "s = \"a;b;cd\"\n",
+ "l = s.split(\";\")\n",
+ "print(repr(l))\n",
+ "print(\";\".join(l))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/Level_05/Aufgaben/fakultaet.py "b/Level_05/L\303\266sungen/fakultaet.py"
similarity index 79%
rename from Level_05/Aufgaben/fakultaet.py
rename to "Level_05/L\303\266sungen/fakultaet.py"
index c68f7f0..6c11a23 100755
--- a/Level_05/Aufgaben/fakultaet.py
+++ "b/Level_05/L\303\266sungen/fakultaet.py"
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
-# Dies ist eine Beispielslösung für die erste Aufgabe des fünften Levels:
+# Dies ist eine Beispiellösung für die erste Aufgabe des fünften Levels:
def fakultaet(n):
# Alternativ: n == 0
diff --git a/Level_05/README.md b/Level_05/README.md
new file mode 100644
index 0000000..422cd1a
--- /dev/null
+++ b/Level_05/README.md
@@ -0,0 +1,12 @@
+# Level 5 Aufgaben
+Wie bereits in den Aufgaben zu Level 3 angekündigt bieten Funktionen eine weitere Möglichkeit Abläufe zu wiederholen. Im Gegensatz zu den Schleifen sind die Einsatzmöglichkeiten von Funktionen weitaus vielfältiger.
+
+## Aufgabe 1: Fakultät rekursiv
+Die Fakultät ist als rekursive Funktion definiert, weshalb es intuitiv sein sollte, sie als rekursive Funktion zu implementieren. In dieser Aufgabe geht es genau um diese Implementation. Schreibe eine Funktion `factorial(n: int) -> int` die eine Zahl `n` entgegen nimmt und rekursiv deren Fakultät berechnet.
+Zur Erinnerung: Die Fakultät einer Zahl `n` ist gegeben durch:
+```
+n! = n * (n-1) mit 0! = 1
+```
+
+**Hinweis:**
+Während es bei der while-Schleife keine Begrenzung gibt, was die maximale Anzahl an Durchläufen angeht, existiert für die Tiefe einer Rekursion ein Limit.
diff --git a/Level_05/funktionen.py b/Level_05/funktionen.py
deleted file mode 100755
index 1eae627..0000000
--- a/Level_05/funktionen.py
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/usr/bin/env python3
-
-# Funktionen:
-
-def funktion() -> None:
- print("Hallo!")
-funktion()
-# OUT: Hallo!
-
-
-def funktion(text: str) -> None:
- print(text)
-funktion("a")
-# OUT: a
-
-
-def funktion(text, wirklich):
- if wirklich:
- print(text)
-
-funktion("Hallo", True)
-# OUT: Hallo
-
-funktion(True, "Hallo")
-# OUT: True
-
-
-def funktion(text: str = "Beispiel", wirklich: bool = False):
- if wirklich:
- print(text)
-
-funktion()
-# OUT: None
-
-funktion(wirklich=True)
-# OUT: Beispiel
-
-funktion(wirklich=True, text="Abc")
-# OUT: Abc
-
-
-def ja() -> str:
- return "Ja"
-ja()
-# OUT: 'Ja'
-
-# beliebig viele Parameter
-def sum(*params):
- s = 0
- for x in params:
- s += x
- return s
-
-sum() # 0
-sum(1,5) # 6
-
-# beliebig viele Keyword-Argumente
-def print_kwargs(**kwargs):
- print(kwargs)
-
-print_kwargs(a=5, b="foo")
-
-# die allgemeinste Funktion
-def allg(*args, **kwargs):
- print(args, kwargs)
-
-# Rekursion:
-
-def fun() -> None:
- print("Fun!")
- fun()
-
-# Quersumme:
-def quersumme(zahl: int) -> int:
- qs = 0
- for ziffer in str(zahl):
- qs += int(ziffer)
- return qs
-
-# Docstrings
-
-def fun():
- """Diese Funktion macht Spaß."""
- print("Spaß")
diff --git a/Level_05/strings_erweitert.py b/Level_05/strings_erweitert.py
deleted file mode 100755
index 76922ce..0000000
--- a/Level_05/strings_erweitert.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env python3
-
-# Character escaping:
-# escaping ist eine Möglichkeit Zeichen und Steuerzeichen (z.B. \n und \t) in einen
-# String einzubauen
-print("Tab:\t#")
-
-# Zeichen über ihren Namen einbinden:
-print("Wal: \N{WHALE}")
-
-# Das Zeichen hinter einem \ wird entweder Steuerzeichen interpretiert oder ignoriert
-print("\aabc")
-
-# Folglich kann ein \ nicht trivial in einen String gepackt werden:
-# Nicht so:
-print("\0/")
-# Sondern so:
-print("\\0/")
-
-# Rawstrings können kein escaping:
-print(r"\n")
-print(r"\0/")
-
-
-# string.format()
-print("Das folgende Wort wird ersetzt: '{}' Der Rest nicht.".format("blargh"))
-# Auch:
-print("Das folgende Wort wird ersetzt: '{0} und {1}' Der Rest nicht.".format("foo", "bar"))
-
-# Zum Weiterlesen und erweitern: https://www.digitalocean.com/community/tutorials/how-to-use-string-formatters-in-python-3
-
-# String.split()
-s = "a;b;cd"
-l = s.split(";") # type: list
-print(repr(l))
-# l entspricht nun: ["a", "b", "cd"]
-# Geeignet zum Parsen von .csv Dateien zum Beispiel
-
-s = ";".join(l) # type: str
-# l enspricht nun: 'a;b;cd'
-
-# Wiederholung:
-# string.split(char) Trennt den String bei jedem Auftreten von char
-# string.join(list) Trennt die Liste mit String und gibt einen String zurück
diff --git a/Level_05/zeit.py b/Level_05/zeit.py
deleted file mode 100755
index 6957b2c..0000000
--- a/Level_05/zeit.py
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env python3
-import time
-
-# Timestamp:
-time.time() # type: float
-# OUT: 1444327310.2887266
-
-
-# Datum und Uhrzeit:
-time.localtime()
-# OUT: time.struct_time(tm_year=2015, tm_mon=10, tm_mday=8, tm_hour=20,
-# tm_min=2, tm_sec=11, tm_wday=3, tm_yday=281, tm_isdst=1)
-
-# Zugriff über Index
-time.localtime()[0] # type: int
-# OUT: 2015
-
-list(time.localtime())
-# OUT: [2015, 10, 8, 20, 3, 1, 3, 281, 1]
-
-# Zugriff über Schlüssel
-time.localtime().tm_year
-# OUT: 2015
-
-
-# Pause:
-time.sleep(1)
-# Wartet eine Sekunde
-
-
-# Ladebalken:
-
-while True:
- print(".", end="", flush=True)
- time.sleep(1)
-# OUT: ...........................................
diff --git a/Level_06/README.md b/Level_06/README.md
new file mode 100644
index 0000000..b55385a
--- /dev/null
+++ b/Level_06/README.md
@@ -0,0 +1,18 @@
+# Level 6 Aufgaben
+
+## Aufgabe 1 (Monty Python)
+
+Passe deine Lösung aus Level 4 so an, dass:
+ * alle Dateinamen als Parameter auf der Kommandozeile übergeben werden können
+ * alle Befehle in einem Programm sind
+ * `argparse` dabei verwendet wird
+
+Wenn du keine eigene Lösung hast, kannst du auch unsere Lösung von Level 4 benutzen.
+Aufrufbar sein soll das Programm am Ende wie folgt:
+
+```bash
+python3 monty.py words --input monty.txt --output words.txt
+python3 monty.py chars --input monty.txt --output chars.txt
+python3 monty.py analyze --chars chars.txt
+python3 monty.py replace --input monty.txt --output MONTY.txt
+```
diff --git a/Level_06/progress.py b/Level_06/progress.py
index 6243742..111d0e7 100755
--- a/Level_06/progress.py
+++ b/Level_06/progress.py
@@ -9,7 +9,7 @@
pass
print("unbekannte Länge:")
-for x in tqdm((x for x in range(25000000))):
+for x in tqdm(x for x in range(25000000)):
pass
print("grafisch:")
diff --git a/Level_07/OOP1.py b/Level_07/OOP1.py
index ca0b844..f87e727 100755
--- a/Level_07/OOP1.py
+++ b/Level_07/OOP1.py
@@ -7,10 +7,10 @@ class Simple:
Dies ist die einfachst mögliche Klasse.
Sie hat keine Methoden, keine Attribute
und erbt (implizit) von `object`.
-
+
Sie ist allerdings relativ langweilig,
weil man recht wenig mit ihr machen kann.
-
+
Klassennamen sollten laut PEP8 in CamelCase sein
und mit einem Großbuchstaben beginnen
(https://www.python.org/dev/peps/pep-0008/#class-names).
@@ -22,7 +22,7 @@ class HelloWorld:
def hello_world():
"""
Diese Methode gibt "Hello World!" auf der Konsole aus.
-
+
Funktions- oder Methodennamen sollten laut PEP8 kleingeschrieben
werden und evtl. mit Unterstrichen getrennt sein
(https://www.python.org/dev/peps/pep-0008/#function-names).
@@ -38,7 +38,7 @@ def hello(name: str = "World") -> None:
Natürlich können Methoden auch Parameter haben.
Dies funktioniert genau so wie bei Funktionen.
"""
- print("Hello, {}!".format(name))
+ print(f"Hello, {name}!")
# Die Methode aufrufen:
Hello.hello(getuser())
@@ -92,9 +92,9 @@ class Thing:
def __init__(self) -> None:
"""
Dies ist ein Konstruktor.
- Bis auf den Namen ähnelt er anderen Instanzmethoden.
+ Bis auf den Namen ähnelt er anderen Instanz-Methoden.
Er wird aufgerufen, wenn die Klasse instanziert wird.
-
+
Standardmäßig existiert ein leerer Konstruktor ohne Parameter.
"""
print ("Hallo!")
@@ -109,20 +109,20 @@ def __init__(self, name: str, phone: int, email: str) -> None:
"""
Dies ist ein Konstruktor.
Aber dieser hat Parameter.
-
+
Diese Parameter werden Instanzvariablen zugewiesen.
"""
self.name = name
self.phone = phone
self.email = email
-
+
def print(self):
"""
Druckt den Kontakt aus.
"""
- print("Name: {}".format(self.name))
- print("Telefonnummer: {}".format(self.phone))
- print("E-Mail: {}".format(self.email))
+ print(f"Name: {self.name}")
+ print(f"Telefonnummer: {self.phone}")
+ print(f"E-Mail: {self.email}")
c = Contact("Ich", "01234-56789", "mail@example.org")
@@ -132,6 +132,6 @@ class HTTPURL:
""" Diese Klasse repräsentiert eine HTTPURL. """
def __init__(self, url: str) -> None:
self.url = url
-
+
def open(self) -> None:
webbrowser.open(self.url)
diff --git a/Level_07/OOP2.py b/Level_07/OOP2.py
index ed905bb..1045b6b 100755
--- a/Level_07/OOP2.py
+++ b/Level_07/OOP2.py
@@ -28,53 +28,53 @@
class C(Complex):
"""
Komplexe Zahlen haben einen Real- und einen Imaginärteil.
-
+
Sie werden häufig als a + bi geschrieben,
wobei a der Realteil und b der Imaginärteil ist.
-
+
Man kann sie sich auch als zweidimensionalen Vektorraum vorstellen, der 1 + 0i (bzw. (1, 0)) und 0 + 1i (bzw. (0, 1)) als Basisvektoren hat, d.h. eine Dimension ist der Realteil und die andere Dimension ist der Imaginärteil
"""
real = 0 # type: float
imag = 0 # type: float
-
+
def __init__(self, real: float = 0, imag: float = 0) -> None:
"""
Erstellt eine neue komplexe Zahl.
-
+
Sowohl Real- als auch Imaginärteil können weggelassen werden,
dann wird einfach 0 angenommen.
"""
self.real = real
self.imag = imag
-
+
def __abs__(self) -> float:
"""
Berechnet den Betrag einer komplexen Zahl.abs
-
+
Mit der Vektordarstellung (real, imag) sollte das klar sein
- das ist nur der Satz von Pythagoras.
"""
return sqrt(self.real**2 + self.imag**2)
-
+
def __add__(self, o: Complex) -> "C":
"""
Addiert zwei komplexe Zahlen.
-
+
Mit der Vektordarstellung sollte das klar sein:
g = (a, b), h = (c, d), g + h = (a + c, b + d)
"""
assert isinstance(o, Complex)
return C(self.real + o.real, self.imag + o.imag)
-
+
def __radd__(self, o: float) -> "C":
"""
Addiert eine rationale Zahl zu einer komplexen Zahl.
-
+
Hierbei ändert sich einfach nur der Realteil.
"""
assert isinstance(o, float)
return C(self.real + o, self.imag)
-
+
def __mul__(self, o: Complex) -> "C":
"""
Multipliziert zwei komplexe Zahlen.
@@ -84,16 +84,16 @@ def __mul__(self, o: Complex) -> "C":
real=self.real * o.real - self.imag * o.imag,
imag=self.real * o.imag + self.imag * o.real
)
-
+
def __rmul__(self, o: float) -> "C":
"""
Multipliziert eine rationale Zahl an eine komplexe Zahl.
-
+
Hierbei ändert sich nur der Realteil.
"""
assert isinstance(o, float)
return C(self.real * o, self.imag)
-
+
def __pow__(self, o: int) -> "C":
"""
Potenziert eine komplexe Zahl.
@@ -103,13 +103,13 @@ def __pow__(self, o: int) -> "C":
for i in range(o):
value *= self
return value
-
+
def __rpow__(self, o: float) -> "C":
"""
Potenziert nur den Realteil.
"""
return C(self.real ** o, self.imag)
-
+
def __truediv__(self, o: Complex) -> "C":
"""
Dividiert zwei komplexe Zahlen.
@@ -119,64 +119,64 @@ def __truediv__(self, o: Complex) -> "C":
real=(self.real * o.real + self.imag * o.imag) / (o.real ** 2 + o.imag ** 2),
imag=(self.imag * o.real - self.real * o.imag) / (o.real ** 2 + o.imag ** 2)
)
-
+
def __rtruediv__(self, o: float) -> "C":
"""
Dividiert eine komplexe Zahl durch eine rationale Zahl.
-
+
Hierbei ändert sich nur der Realteil.
"""
return C(self.real / o, self.imag)
-
+
def __eq__(self, o: object) -> bool:
"""
Vergleicht zwei komplexe Zahlen auf Äquivalenz.
-
+
Mit der Vektordarstellung sollte das klar sein:
g = (a, b), h = (c, d), (g = h) <=> (a = c ^ b = c)
"""
if not isinstance(o, Complex):
return False
return (self.real == o.real) and (self.imag == o.imag)
-
+
def conjugate(self) -> "C":
"""
Berechnet das komplexe Konjugat einer komplexen Zahl.
"""
return C(self.real, -self.imag)
-
+
def __pos__(self) -> "C":
"""
Berechnet +x (für x eine komplexe Zahl).
"""
return self
-
+
def __neg__(self) -> "C":
"""
Berechnet -x (für x eine komplexe Zahl).
"""
return C(-self.real, -self.imag)
-
+
def __complex__(self) -> complex:
"""
Wandelt eine komplexe Zahl in eine complex-Instanz um.
"""
return complex(self.real, self.imag)
-
+
def __hash__(self) -> int:
"""
Berechnet den Hashwert einer komplexen Zahl.
-
+
Wichtig ist: Wenn zwei Zahlen äquivalent sind, sollen sie den gleichen Hash haben.
-
- Wir machen es uns einfach und nehmen einfach die menschenlesbare Darstellung.
+
+ Wir machen es uns einfach und nehmen einfach die menschen-lesbare Darstellung.
"""
return hash(repr(self))
-
+
def __repr__(self) -> str:
"""
- Stellt eine komplexe Zahl menschenlesbar dar.
-
+ Stellt eine komplexe Zahl menschen-lesbar dar.
+
Dies gibt die Darstellung a + b i,
nicht die Vektordarstellung (a, b) zurück.
"""
diff --git a/Level_07/Ueberladung.py b/Level_07/Ueberladung.py
index ea8342c..0a150fe 100644
--- a/Level_07/Ueberladung.py
+++ b/Level_07/Ueberladung.py
@@ -1,41 +1,41 @@
-""" Diese Datei zeigt Operatorüberladung. """
+""" Diese Datei zeigt Operator-Überladung. """
import math
class Punkt:
"""
Ein Punkt in einem dreidimensionalen Koordinatensystem.
-
+
Man kann ihn z.B. ausgeben lassen, vergleichen oder addieren.
"""
-
+
def __init__(self, x, y, z) -> None:
""" Ein Punkt wird erzeugt unter Angabe von drei Koordinaten: x, y und z. """
self.x = float(x)
self.y = float(y)
self.z = float(z)
-
+
def __repr__(self) -> str:
- """ die menschenlesbare Darstellung -- str und repr """
- return "({}|{}|{})".format(self.x, self.y, self.z)
-
+ """ die menschen-lesbare Darstellung -- str und repr """
+ return f"({self.x}|{self.y}|{self.z})"
+
def __eq__(self, p: "Punkt") -> bool:
""" prüft auf Äquivalenz -- == """
if hasattr(p, "x") and hasattr(p, "y") and hasattr(p, "z"):
return self.x == p.x and self.y == p.y and self.z == p.z
else:
return False
-
+
def __add__(self, p: "Punkt") -> "Punkt":
""" addiert p und erzeugt einen neuen Punkt -- + """
assert isinstance(p, Punkt)
return Punkt(self.x + p.x, self.y + p.y, self.z + p.z)
-
+
def __sub__(self, p: "Punkt") -> "Punkt":
""" subtrahiert p und erzeugt einen neuen Punkt -- - """
assert isinstance(p, Punkt)
return self + -p
-
+
def __neg__(self) -> "Punkt":
""" negiert dieses Objekt -- - """
return Punkt(-self.x, -self.y, -self.z)
@@ -45,22 +45,22 @@ class Strecke:
Eine Strecke ist eine Linie zwischen zwei Punkten.
Sie hat keine Richtung.
"""
-
+
def __init__(self, p1: Punkt, p2: Punkt) -> None:
""" Eine Strecke wird erzeugt unter Angabe zweier Punkte. """
assert isinstance(p1, Punkt)
assert isinstance(p2, Punkt)
self.p1 = p1
self.p2 = p2
-
+
def __repr__(self) -> str:
- """ die menschenlesbare Darstellung -- str und repr """
- return "{} - {}".format(self.p1, self.p2)
-
+ """ die menschen-lesbare Darstellung -- str und repr """
+ return f"{self.p1} - {self.p2}"
+
def __eq__(self, l: "Strecke") -> bool:
"""
prüft auf Äquivalenz -- ==
-
+
Strecken haben keine Reihenfolge.
"""
if not isinstance(l, Strecke):
@@ -70,41 +70,41 @@ def __eq__(self, l: "Strecke") -> bool:
if self.p1 == l.p2 and self.p2 == l.p1:
return True
return False
-
+
def __abs__(self) -> float:
""" berechnet den Betrag -- abs """
x = self.p1.x - self.p2.x
y = self.p1.y - self.p2.y
z = self.p1.z - self.p2.z
return math.sqrt(x**2 + y**2 + z**2)
-
+
def __len__(self) -> int:
""" Berechnet die Länge. Dies muss ein int sein. -- len """
return int(abs(self))
-
+
def __gt__(self, l: "Strecke") -> bool:
"""
prüft auf echtes größer -- >
-
+
Dies muss ein bool zurückgeben.
-
+
kleiner muss nicht manuell implementiert werden.
"""
return abs(self) > abs(l)
-
+
def __ge__(self, l: "Strecke") -> bool:
"""
prüft auf größer oder gleich -- >=
-
+
Dies muss ein bool zurückgeben.
-
+
kleiner gleich muss nicht manuell implementiert werden.
"""
return self == l or self > l
class Vektor:
""" Ein Vektor hat eine Richtung. """
-
+
def __init__(self, *args) -> None:
if len(args) == 3: # x, y, z
self.x = float(args[0])
@@ -116,44 +116,44 @@ def __init__(self, *args) -> None:
self.z = args[1].z - args[0].z
else:
raise NotImplementedError
-
+
def __repr__(self) -> str:
- """ die menschenlesbare Darstellung -- str und repr """
- return "({}|{}|{})".format(self.x, self.y, self.z)
-
+ """ die menschen-lesbare Darstellung -- str und repr """
+ return f"({self.x}|{self.y}|{self.z})"
+
def __eq__(self, l: "Vektor") -> bool:
""" Äquivalenz: Vektoren haben eine Richtung. """
if not isinstance(l, Vektor):
return False
return self.x == l.x and self.y == l.y and self.z == l.z
-
+
def __abs__(self) -> float:
""" berechnet den Betrag -- abs """
return math.sqrt(self.x**2 + self.y**2 + self.z**2)
-
+
def __len__(self) -> int:
return int(abs(self))
-
+
def __gt__(self, l: "Vektor") -> bool:
return abs(self) > abs(l)
-
+
def __ge__(self, l: "Vektor") -> bool:
return self == l or self > l
-
+
def __add__(self, l: "Vektor") -> "Vektor":
""" Addition """
assert isinstance(l, Vektor)
return Vektor(self.x + l.x, self.y + l.y, self.z + l.z)
-
+
def __sub__(self, l: "Vektor") -> "Vektor":
""" Subtraktion """
assert isinstance(l, Vektor)
return self + -l
-
+
def __neg__(self) -> "Vektor":
""" Negation """
return Vektor(-self.x, -self.y, -self.z)
-
+
def __mul__(self, faktor):
""" Multiplikation """
if isinstance(faktor, float) or isinstance(faktor, int):
@@ -169,7 +169,7 @@ def __mul__(self, faktor):
z = self.z * faktor.z
return x + y + z
return None
-
+
def __pow__(self, exp: int):
""" Potenzieren - ** """
assert isinstance(exp, int)
@@ -178,14 +178,13 @@ def __pow__(self, exp: int):
for i in range(0, exp):
r *= r
return r
-
+
def __iter__(self):
""" Iterator - siehe nächstes Kapitel """
yield self.x
yield self.y
yield self.z
-
+
def __getitem__(self, item: int) -> float:
""" Zugriff via Index """
return tuple(self)[item]
-
diff --git a/Level_07/fight.py b/Level_07/fight.py
new file mode 100644
index 0000000..2ef6b20
--- /dev/null
+++ b/Level_07/fight.py
@@ -0,0 +1,70 @@
+from typing import Optional
+
+class Weapon:
+ name: str
+ damage: int
+
+ def __init__(self: "Weapon", init_name: str, init_damage: int):
+ self.name = init_name
+ self.damage = init_damage
+
+ def __repr__(self: "Weapon") -> str:
+ return "Weapon(name=" + self.name + ", damage=" + str(self.damage) + ")"
+
+class Supplement:
+ name: str
+ healing: int
+
+ def __init__(self: "Supplement", name: str, healing: int):
+ self.name = name
+ self.healing = healing
+
+ def __repr__(self: "Supplement") -> str:
+ return "Supplement(name=" + self.name + ", healing=" + str(self.healing) + ")"
+
+class Character:
+ name: str
+ health: int
+
+ def __init__(self: "Character", name: str, health: int):
+ self.name = name
+ self.health = health
+
+ def take(self: "Character", supplement: Supplement):
+ self.health += supplement.healing
+
+class Monster(Character):
+ def __init__(self: "Monster", name: str, health: int = 5):
+ super().__init__(name, health)
+
+ def __repr__(self: "Monster") -> str:
+ return "Monster(name=" + self.name + ", health=" + str(self.health) + ")"
+
+class Player(Character):
+ """A fearless wanderer, ready to attack."""
+ weapon: Optional[Weapon] = None
+
+ def __init__(self: "Player", name: str, health: int = 10):
+ super().__init__(name, health)
+
+ def __repr__(self: "Player") -> str:
+ return "Player(name=" + self.name + ", health=" + str(self.health) + ", weapon=" + repr(self.weapon) + ")"
+
+ def attack(self: "Player", other: "Player | Monster"):
+ if self.weapon is None:
+ other.health -= 1
+ else:
+ other.health -= self.weapon.damage
+
+class Villager(Character):
+ def __init__(self: "Villager", name: str):
+ super().__init__(name, 9)
+
+hero = Player("Hero")
+orky = Monster("Orky")
+sword = Weapon("Sword", 3)
+hero.weapon = sword
+hugo = Villager("Hugo Müller")
+hero.attack(hugo)
+heiltrank = Supplement("Donnergurgler", 10)
+
diff --git a/Level_08/fibonacci.py b/Level_08/Beispielcode/fibonacci.py
similarity index 94%
rename from Level_08/fibonacci.py
rename to Level_08/Beispielcode/fibonacci.py
index 7c9cc42..a3b0f4a 100755
--- a/Level_08/fibonacci.py
+++ b/Level_08/Beispielcode/fibonacci.py
@@ -9,13 +9,13 @@ def cache(func):
Dies ist ein Dekorator der Funktionsaufrufe cachet.
Er funktioniert natürlich nur sinnvoll für mathematische Funktionen,
also Funktionen, die beim Aufruf mit den gleichen Parametern immer das gleiche Ergebnis zurückliefern und sonst keine Seiteneffekte haben.
-
+
Dieser Cache hat keinerlei Ersetzungs- oder Löschstrategien, wird also mit der Zeit immer größer.
Das ist nicht ideal, reicht aber für dieses Beispiel.
"""
# ein Dict erzeugen für die zwischengespeicherten Werte
values = dict()
-
+
# die neue Funktion
# hier der Einfachheit halber nur positionale Parameter
def new_func(*args):
@@ -27,10 +27,10 @@ def new_func(*args):
result = func(*args)
values[args] = result
return result
-
+
return new_func
-# die gleiche unpeformante Version von Fibonacci wie in Level 5
+# die gleiche nicht-performante Version von Fibonacci wie in Level 5
@cache
def fib(n: int) -> int:
if n <= 1:
diff --git a/Level_08/fizzbuzz.py b/Level_08/Beispielcode/fizzbuzz_func.py
similarity index 100%
rename from Level_08/fizzbuzz.py
rename to Level_08/Beispielcode/fizzbuzz_func.py
diff --git a/Level_08/Beispielcode/fizzbuzz_iter.py b/Level_08/Beispielcode/fizzbuzz_iter.py
new file mode 100644
index 0000000..36dc265
--- /dev/null
+++ b/Level_08/Beispielcode/fizzbuzz_iter.py
@@ -0,0 +1,10 @@
+def fizz_buzz(number: int) -> str:
+ output = ""
+ if number % 3 == 0:
+ output += "fizz"
+ if number % 5 == 0:
+ output += "buzz"
+ return output or str(number)
+
+for val in map(fizz_buzz, range(1, 16)):
+ print(val)
diff --git a/Level_08/Level_8.ipynb b/Level_08/Level_8.ipynb
new file mode 100644
index 0000000..67cae1d
--- /dev/null
+++ b/Level_08/Level_8.ipynb
@@ -0,0 +1,695 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "cd0bab55",
+ "metadata": {},
+ "source": [
+ "# Exceptions\n",
+ "\n",
+ "Bisher ist unser Programm abgestürzt, wenn Fehler auftreten. Das muss nicht passieren:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "1243337c",
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "ZeroDivisionError",
+ "evalue": "division by zero",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mZeroDivisionError\u001b[0m Traceback (most recent call last)",
+ "Cell \u001b[0;32mIn[5], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;241;43m1\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m/\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\n",
+ "\u001b[0;31mZeroDivisionError\u001b[0m: division by zero"
+ ]
+ }
+ ],
+ "source": [
+ "1 / 0"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "c8d4962e",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "division by zero\n",
+ "Fertig.\n"
+ ]
+ }
+ ],
+ "source": [
+ "try:\n",
+ " 1 / 0\n",
+ "\n",
+ "except ZeroDivisionError as exc:\n",
+ " print(exc)\n",
+ "\n",
+ "finally:\n",
+ " print(\"Fertig.\")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6d40ff35",
+ "metadata": {},
+ "source": [
+ "Schön ist auch `raise` innerhalb eines `except`-Blocks.\n",
+ "\n",
+ "So wird der Fehler bearbeitet, aber bleibt nicht unentdeckt:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "f9e8689d",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "a kann nicht als Integer benutzt werden.\n"
+ ]
+ },
+ {
+ "ename": "ValueError",
+ "evalue": "invalid literal for int() with base 10: 'a'",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
+ "Cell \u001b[0;32mIn[7], line 3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 2\u001b[0m x \u001b[38;5;241m=\u001b[39m \u001b[38;5;28minput\u001b[39m()\n\u001b[0;32m----> 3\u001b[0m x \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mint\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mx\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m:\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28mprint\u001b[39m(x, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mkann nicht als Integer benutzt werden.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n",
+ "\u001b[0;31mValueError\u001b[0m: invalid literal for int() with base 10: 'a'"
+ ]
+ }
+ ],
+ "source": [
+ "try:\n",
+ " x = input()\n",
+ " x = int(x)\n",
+ "except ValueError:\n",
+ " print(x, \"kann nicht als Integer benutzt werden.\")\n",
+ " raise\n",
+ "else:\n",
+ " print(\"Kein Value-Fehler\")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0631e2b4",
+ "metadata": {},
+ "source": [
+ "Man kann auch eigene Fehler definieren, die von Exception erben:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "747ab3fa",
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "MeinFehler",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mMeinFehler\u001b[0m Traceback (most recent call last)",
+ "Cell \u001b[0;32mIn[8], line 4\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mMeinFehler\u001b[39;00m(\u001b[38;5;167;01mException\u001b[39;00m):\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mpass\u001b[39;00m\n\u001b[0;32m----> 4\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m MeinFehler\n",
+ "\u001b[0;31mMeinFehler\u001b[0m: "
+ ]
+ }
+ ],
+ "source": [
+ "class MeinFehler(Exception):\n",
+ " pass\n",
+ "\n",
+ "raise MeinFehler"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e3ac0adb",
+ "metadata": {},
+ "source": [
+ "# with\n",
+ "\n",
+ "`with` ist ein sogenannter Kontextmanager.\n",
+ "\n",
+ "Eine genauere Beschreibung als hier findet sich unter und .\n",
+ "\n",
+ "Hier folgen nun einige Beispiele.\n",
+ "\n",
+ "## Dateien öffnen"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "a718b5e9",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.\n",
+ "Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.\n",
+ "Suspendisse lectus leo, consectetur in tempor sit amet, placerat quis neque. Etiam luctus porttitor lorem, sed suscipit est rutrum non. Curabitur lobortis nisl a enim congue semper. Aenean commodo ultrices imperdiet. Vestibulum ut justo vel sapien venenatis tincidunt. Phasellus eget dolor sit amet ipsum dapibus condimentum vitae quis lectus. Aliquam ut massa in turpis dapibus convallis. Praesent elit lacus, vestibulum at malesuada et, ornare et est. Ut augue nunc, sodales ut euismod non, adipiscing vitae orci. Mauris ut placerat justo. Mauris in ultricies enim. Quisque nec est eleifend nulla ultrices egestas quis ut quam. Donec sollicitudin lectus a mauris pulvinar id aliquam urna cursus. Cras quis ligula sem, vel elementum mi. Phasellus non ullamcorper urna.\n",
+ "Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In euismod ultrices facilisis. Vestibulum porta sapien adipiscing augue congue id pretium lectus molestie. Proin quis dictum nisl. Morbi id quam sapien, sed vestibulum sem. Duis elementum rutrum mauris sed convallis. Proin vestibulum magna mi. Aenean tristique hendrerit magna, ac facilisis nulla hendrerit ut. Sed non tortor sodales quam auctor elementum. Donec hendrerit nunc eget elit pharetra pulvinar. Suspendisse id tempus tortor. Aenean luctus, elit commodo laoreet commodo, justo nisi consequat massa, sed vulputate quam urna quis eros. Donec vel. \n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "with open(\"../Level_04/Beispielcode/loremipsum.txt\") as lorem:\n",
+ " print(lorem.read())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4573de3f",
+ "metadata": {},
+ "source": [
+ "## Exceptions ignorieren"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "75ef5391",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from contextlib import suppress\n",
+ "\n",
+ "with suppress(ZeroDivisionError):\n",
+ " print(1 / 0)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e96478a9",
+ "metadata": {},
+ "source": [
+ "## temporäre Dateien und Ordner"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "0cdf805c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import tempfile\n",
+ "from os.path import join\n",
+ "\n",
+ "with tempfile.TemporaryFile(mode=\"w\") as tmpfile:\n",
+ " tmpfile.write(\"Dies ist ein Test.\\n\")\n",
+ "\n",
+ "with tempfile.TemporaryDirectory() as tmpdir:\n",
+ " with open(join(tmpdir, \"test.txt\"), \"w\") as test:\n",
+ " test.write(\"Dies ist auch ein Test.\\n\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f69a7254",
+ "metadata": {},
+ "source": [
+ "contextlib bietet auch Dekoratoren an, um eigene Contextmanager zu erstellen:\n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9b383d6b",
+ "metadata": {},
+ "source": [
+ "# Generatoren\n",
+ "\n",
+ "Generatoren können \"lazy\" Elemente erzeugen:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "581b8844",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Generatoren und yield\n",
+ "def gen(s):\n",
+ " for char in s:\n",
+ " yield char"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "a75ac011",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "a\n",
+ "b\n",
+ "c\n",
+ "d\n",
+ "e\n",
+ "f\n"
+ ]
+ }
+ ],
+ "source": [
+ "# iterieren mit einer for-Schleife:\n",
+ "for x in gen(\"abcdef\"):\n",
+ " print(x)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "8d4afc47",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "f\n",
+ "o\n"
+ ]
+ }
+ ],
+ "source": [
+ "# oder manuell mit next:\n",
+ "g = gen(\"foobar\")\n",
+ "print(next(g))\n",
+ "print(next(g))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4c7e69b4",
+ "metadata": {},
+ "source": [
+ "# Dekoratoren\n",
+ "\n",
+ "Dekoratoren sind Funktionen, die auf Funktionen angewandt werden bei deren Definition:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "id": "d3ed8738",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "4\n",
+ "9\n"
+ ]
+ }
+ ],
+ "source": [
+ "def f(x):\n",
+ " return x**2\n",
+ "\n",
+ "print(f(2))\n",
+ "print(f(3))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 26,
+ "id": "a2bba8e0",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Args: (2,)\n",
+ "Return: 4\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "4"
+ ]
+ },
+ "execution_count": 26,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "def dec(func):\n",
+ " def inner_func(*args):\n",
+ " print(f\"Args: {args}\")\n",
+ " r = func(*args)\n",
+ " print(f\"Return: {r}\")\n",
+ " return r\n",
+ "\n",
+ " return inner_func\n",
+ "\n",
+ "\n",
+ "@dec\n",
+ "def f(x):\n",
+ " return x**2\n",
+ "\n",
+ "f(2)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7abbcad7",
+ "metadata": {},
+ "source": [
+ "# map\n",
+ "\n",
+ "Mit `map` lassen sich Funktionen auf jedes Element eines Generators anwenden:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "id": "9caff1aa",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]"
+ ]
+ },
+ "execution_count": 25,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "def add_2(x):\n",
+ " return x + 2\n",
+ "\n",
+ "\n",
+ "l = range(10)\n",
+ "result = list(map(add_2, l))\n",
+ "result\n",
+ "\n",
+ "# äquivalent zum folgenden Code:\n",
+ "# result = []\n",
+ "# for i in l:\n",
+ "# result.append(add_2(i))\n",
+ "\n",
+ "# oder auch: result = [add_2(x) for x in l]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f1b2b72d",
+ "metadata": {},
+ "source": [
+ "# filter\n",
+ "\n",
+ "`filter` funktioniert ähnlich, aber \"siebt\" die Elemente:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "id": "ed19bc69",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[0,\n",
+ " 2,\n",
+ " 4,\n",
+ " 6,\n",
+ " 8,\n",
+ " 10,\n",
+ " 12,\n",
+ " 14,\n",
+ " 16,\n",
+ " 18,\n",
+ " 20,\n",
+ " 22,\n",
+ " 24,\n",
+ " 26,\n",
+ " 28,\n",
+ " 30,\n",
+ " 32,\n",
+ " 34,\n",
+ " 36,\n",
+ " 38,\n",
+ " 40,\n",
+ " 42,\n",
+ " 44,\n",
+ " 46,\n",
+ " 48,\n",
+ " 50,\n",
+ " 52,\n",
+ " 54,\n",
+ " 56,\n",
+ " 58,\n",
+ " 60,\n",
+ " 62,\n",
+ " 64,\n",
+ " 66,\n",
+ " 68,\n",
+ " 70,\n",
+ " 72,\n",
+ " 74,\n",
+ " 76,\n",
+ " 78,\n",
+ " 80,\n",
+ " 82,\n",
+ " 84,\n",
+ " 86,\n",
+ " 88,\n",
+ " 90,\n",
+ " 92,\n",
+ " 94,\n",
+ " 96,\n",
+ " 98]"
+ ]
+ },
+ "execution_count": 24,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "def even(n):\n",
+ " return n % 2 == 0\n",
+ "\n",
+ "\n",
+ "r = range(100)\n",
+ "even_numbers = list(filter(even, r))\n",
+ "# oder: even_numbers = [x for x in r if even(x)]\n",
+ "even_numbers"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f53c24bb",
+ "metadata": {},
+ "source": [
+ "# zip\n",
+ "\n",
+ "`zip` fügt mehrere Iteratoren zusammen:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "id": "1c3cf39f",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[(0, -10),\n",
+ " (1, -9),\n",
+ " (2, -8),\n",
+ " (3, -7),\n",
+ " (4, -6),\n",
+ " (5, -5),\n",
+ " (6, -4),\n",
+ " (7, -3),\n",
+ " (8, -2),\n",
+ " (9, -1)]"
+ ]
+ },
+ "execution_count": 23,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "iter1 = range(10)\n",
+ "iter2 = range(-10, 0)\n",
+ "list(zip(iter1, iter2))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "491e268c",
+ "metadata": {},
+ "source": [
+ "# lambda\n",
+ "\n",
+ "Mit `lambda` lassen sich anonyme Funktionen definieren:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "id": "92c56dea",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[0,\n",
+ " 2,\n",
+ " 4,\n",
+ " 6,\n",
+ " 8,\n",
+ " 10,\n",
+ " 12,\n",
+ " 14,\n",
+ " 16,\n",
+ " 18,\n",
+ " 20,\n",
+ " 22,\n",
+ " 24,\n",
+ " 26,\n",
+ " 28,\n",
+ " 30,\n",
+ " 32,\n",
+ " 34,\n",
+ " 36,\n",
+ " 38,\n",
+ " 40,\n",
+ " 42,\n",
+ " 44,\n",
+ " 46,\n",
+ " 48,\n",
+ " 50,\n",
+ " 52,\n",
+ " 54,\n",
+ " 56,\n",
+ " 58,\n",
+ " 60,\n",
+ " 62,\n",
+ " 64,\n",
+ " 66,\n",
+ " 68,\n",
+ " 70,\n",
+ " 72,\n",
+ " 74,\n",
+ " 76,\n",
+ " 78,\n",
+ " 80,\n",
+ " 82,\n",
+ " 84,\n",
+ " 86,\n",
+ " 88,\n",
+ " 90,\n",
+ " 92,\n",
+ " 94,\n",
+ " 96,\n",
+ " 98]"
+ ]
+ },
+ "execution_count": 22,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "list(filter(lambda x: x % 2 == 0, r))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "cf140ff2",
+ "metadata": {},
+ "source": [
+ "# all / any\n",
+ "\n",
+ "`all` und `any` laufen einen Iterator ab und prüfen Bedigungen, brechen aber ggf. früher ab:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "id": "49dbeb10",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 27,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "all(even(x) for x in even_numbers)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "90fea9ed",
+ "metadata": {},
+ "source": [
+ "Für mehr Spaß mit Generatoren lohnt sich ein Blick auf [itertools](https://docs.python.org/3/library/itertools.html) und [more-itertools](https://more-itertools.readthedocs.io)."
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/Level_08/exceptions.py b/Level_08/exceptions.py
deleted file mode 100755
index dd6d4d0..0000000
--- a/Level_08/exceptions.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python3
-
-# Exceptions
-try:
- 1 / 0
-
-except ZeroDivisionError as exc:
- print(exc)
-
-finally:
- print("Fertig.")
-
-# OUT:
-# division by zero
-# Fertig
-
-# Nett ist auch "raise" innerhalb eines except-Blocks.
-
-try:
- x = input()
- x = int(x)
-except ValueError:
- print(x, " kann nicht als Integer benutzt werden.")
- raise
-else:
- print("Kein Valuefehler")
-
-# So wird der Fehler bearbeitet, aber der Fehler bleibt nicht unentdeckt
-
-# Man kann auch eigene Fehler definieren, die von Exception erben:
-class MeinFehler(Exception):
- pass
\ No newline at end of file
diff --git a/Level_08/generatoren.py b/Level_08/generatoren.py
deleted file mode 100755
index c562d8e..0000000
--- a/Level_08/generatoren.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env python3
-
-# Generatoren und yield
-def gen(s):
- for char in s:
- yield char
-
-# iterieren mit einer for-Schleife:
-for x in gen("abcdef"):
- print(x)
-
-# oder manuell mit next:
-g = gen("foobar")
-print(next(g))
-print(next(g))
-
-# Dekoratoren
-def f(x):
- return x**2
-
-
-# IN: f(2)
-# OUT: 4
-# IN: f(3)
-# OUT: 9
-
-def dec(func):
- def inner_func(*args):
- print(args)
- r = func(*args)
- print("Return: {}".format(r))
- return r
- return inner_func
-
-@dec
-def f(x):
- return x**2
-
-
-# IN: f(2)
-# OUT: (2,)
-# OUT: Return:
-# OUT: 4
-# OUT:4
diff --git a/Level_08/map.py b/Level_08/map.py
deleted file mode 100755
index 5757b6b..0000000
--- a/Level_08/map.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env python3
-
-# map
-
-def add_2(x):
- return x + 2
-
-l = range(10)
-
-# Statt:
-result = []
-for i in l:
- result.append(add_2(i))
-
-# Kann man map() benutzen:
-result = list(map(add_2, l))
-
-
-# oder:
-result = [add_2(x) for x in l]
-
-# filter
-
-def even(n):
- return n % 2 == 0
-
-r = range(100)
-even_numbers = list(filter(even, r))
-
-even_numbers = [x for x in r if even(x)]
-print(even_numbers)
-
-# zip
-iter1 = range(10)
-iter2 = range(-10,0)
-print(list(zip(iter1, iter2)))
-
-# lambda
-print(list(filter(lambda x: x % 2 == 0, r)))
-
-print(all((even(x) for x in even_numbers)))
-
-# für mehr Spaß mit Generatoren: https://docs.python.org/3/library/itertools.html
\ No newline at end of file
diff --git a/Level_08/with.py b/Level_08/with.py
deleted file mode 100755
index 2764fe8..0000000
--- a/Level_08/with.py
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env python3
-
-"""
-with ist ein Kontextmanager.
-
-Eine genauere Beschreibung als hier findet sich unter https://docs.python.org/3.6/reference/compound_stmts.html#with und https://docs.python.org/3.6/reference/datamodel.html#context-managers .
-
-Hier folgen nun einige Beispiele.
-"""
-
-# Dateien öffnen
-
-with open("../Level_04/loremipsum.txt", "r") as lorem:
- print(lorem.read())
-
-# Exceptions ignorieren
-
-from contextlib import suppress
-
-with suppress(ZeroDivisionError):
- print(1/0)
-
-# temporäre Dateien und Ordner
-
-import tempfile
-from os.path import join
-
-with tempfile.TemporaryFile(mode="w") as tmpfile:
- tmpfile.write("Dies ist ein Test.\n")
-
-with tempfile.TemporaryDirectory() as tmpdir:
- with open(join(tmpdir, "test.txt"), "w") as test:
- test.write("Dies ist auch ein Test.\n")
-
-# contextlib bietet Decoratoren an um eigene Contextmanager zu erstellen:
-# https://docs.python.org/3/library/contextlib.html
\ No newline at end of file
diff --git a/Level_09/prozesse.py b/Level_09/prozesse.py
index 2858e6f..6640684 100755
--- a/Level_09/prozesse.py
+++ b/Level_09/prozesse.py
@@ -5,7 +5,7 @@
from sys import argv
"""
-multiprocessing ist progammatisch ähnlich zu verwenden wie threading.
+multiprocessing ist programmatisch ähnlich zu verwenden wie threading.
Das Modul heißt anders und die Klasse auch (nämlich Process).
"""
@@ -14,7 +14,7 @@ def __init__(self, wait: float = 0.1) -> None:
Process.__init__(self)
self.wait = wait
self.daemon = True # siehe Threads
-
+
def run(self) -> None:
while True:
print(getpid())
diff --git a/Level_09/threads.py b/Level_09/threads.py
index a9cdb81..103bbd4 100755
--- a/Level_09/threads.py
+++ b/Level_09/threads.py
@@ -18,8 +18,8 @@ def __init__(self, string: str, wait: float = 0.1) -> None:
Thread.__init__(self)
self.string = string
self.wait = wait
- self.daemon = True # Soll dieser Thread beendet werden beim Programmende des Hauptthreads?
-
+ self.daemon = True # Soll dieser Thread beendet werden beim Programmende des Haupt-Threads?
+
def run(self) -> None:
while True:
print(self.string, end="", flush=True)
diff --git a/Level_10/Level_10.ipynb b/Level_10/Level_10.ipynb
new file mode 100644
index 0000000..37938d1
--- /dev/null
+++ b/Level_10/Level_10.ipynb
@@ -0,0 +1,158 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "079741c2",
+ "metadata": {},
+ "source": [
+ "# Grafische Benutzeroberflächen\n",
+ "\n",
+ "Es gibt wahnsinnig viele Toolkits, um grafische Anwendungen zu programmieren (z.B. GTK+ und Tk). Wir haben uns für [Qt](https://www.qt.io/) (in der Version 5) entschieden, weil die API nachvollziehbar ist und es auf sehr vielen Plattformen verfügbar ist.\n",
+ "\n",
+ "Für eine Anbindung an Python nehmen wir [PySide 2](https://wiki.qt.io/PySide2).\n",
+ "Dies ist leider in vielen Distributionen noch nicht in den Paketquellen enthalten.\n",
+ "Für die aktuelle Ubuntu LTS (16.04) muss z.B. das [PPA](https://launchpad.net/~thopiekar/+archive/ubuntu/pyside-git) `ppa:thopiekar/pyside-git` hinzugefügt und\n",
+ "das Paket `python3-pyside2` installiert werden.\n",
+ "\n",
+ "## Benötigte Module laden:\n",
+ "\n",
+ "Qt besteht aus vielen einzelnen Modulen - je nach Verwendung müssen die benötigten Module zuerst geladen werden.\n",
+ "Dies können (je nach Einsatz) mehr oder weniger sein - diese hier sind allerdings üblich:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "b47eaae5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from PySide2.QtCore import *\n",
+ "from PySide2.QtGui import *\n",
+ "from PySide2.QtWidgets import *"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4288f6b5",
+ "metadata": {},
+ "source": [
+ "Für den nächsten Schritt benötigen wir zusätzlich noch das Python-Modul `sys`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "266038f5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import sys"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "dd90e098",
+ "metadata": {},
+ "source": [
+ "## `QApplication`-Objekt erstellen\n",
+ "\n",
+ "Um überhaupt irgendetwas mit Qt machen zu können, brauchen wir eine Instanz von `QApplication`. (Bei reinen Konsolen-Anwendungen kann man auch `QCoreApplication` verwenden.)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "909d55ca",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "app = QApplication(sys.argv)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "927b6ad8",
+ "metadata": {},
+ "source": [
+ "Die Befehlszeilenparameter unseres Programms geben wir an Qt weiter, damit es auf bestimmte Parameter darin reagieren kann (u.a. [diese](https://doc.qt.io/qt-5/qapplication.html#QApplication)).\n",
+ "\n",
+ "## Ein Widget erstellen:\n",
+ "\n",
+ "Alle grafischen Komponenten in Qt sind `QWidgets`.\n",
+ "\n",
+ "Der einfachste Fall ist ein `QLabel` - das zeigt einfach einen beliebigen Text an."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "c810142a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "label = QLabel(\"Dies ist ein Text.\")\n",
+ "label.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e30727f8",
+ "metadata": {},
+ "source": [
+ "Normalerweise würde man dieses Label in einem Fenster mit anderen Elementen unterbringen - in diesem einfachen Fall lassen wir das aber.\n",
+ "\n",
+ "## Die main loop:\n",
+ "\n",
+ "Jetzt ist alles so eingerichtet, wie wir das wollen.\n",
+ "Wir sehen aber noch nichts.\n",
+ "Wieso?\n",
+ "\n",
+ "Der wichtigste Teil fehlt noch:\n",
+ "Wir übergeben die Kontrolle des Programmablaufs an Qt:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "ba9639bb",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0"
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "app.exec_()"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/Level_10/gravatar/gravatar.qml b/Level_10/gravatar/gravatar.qml
index b741a41..2a2d8a1 100644
--- a/Level_10/gravatar/gravatar.qml
+++ b/Level_10/gravatar/gravatar.qml
@@ -9,11 +9,11 @@ Window {
width: 360
height: 360
title: "Gravatar"
-
+
ColumnLayout {
spacing: 2
anchors.fill: parent
-
+
Image {
id: avatar
source: ""
diff --git a/Level_10/label.py b/Level_10/label.py
index fc6733a..d61ab02 100755
--- a/Level_10/label.py
+++ b/Level_10/label.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python3
-# coding: utf-8
# Level 9: Ein Label in einem Fenster.
diff --git a/Level_10/textbox.py b/Level_10/textbox.py
index 5191ba1..a6ee1b6 100755
--- a/Level_10/textbox.py
+++ b/Level_10/textbox.py
@@ -44,10 +44,10 @@
def onClick() -> None:
# die Eingabe holen
input = text.text()
- print("Eingabe: {}".format(input))
+ print(f"Eingabe: {input}")
# MessageBox erstellen
mb = QMessageBox(QMessageBox.Information, "Titel",
- "Der eingegebene Text war: \n{}".format(input), QMessageBox.Ok, window)
+ f"Der eingegebene Text war: \n{input}", QMessageBox.Ok, window)
# MessageBox anzeigen
mb.show()
@@ -57,7 +57,7 @@ def onClick() -> None:
# Alternative:
#button.clicked.connect(lambda: QMessageBox(QMessageBox.Information, "Titel", "Der eingegebene Text war: \n{}".format(text.text()), QMessageBox.Ok, window).show())
-# Fenster anzeigenw
+# Fenster anzeigen
window.show()
# main loop
diff --git a/Notizen.md b/Notizen.md
new file mode 100644
index 0000000..c409f27
--- /dev/null
+++ b/Notizen.md
@@ -0,0 +1,25 @@
+#Notizen:
+## Ideen:
+* Einstieg in Funktionen mit `turtle`
+* Gliederung in Ordner pro Level
+* Aufteilung in Präsentationsdateien und Code Beispiele
+* genauere Formulierung der Aufgaben pro Level im Wiki
+* Verlinkung der Seiten im Wiki mit den Codebeispielen
+* Decoratoren: Als Beispiel das Cachen von Werten bei rekursiven mathematischen Funktionen
+* Dokumentation: Sphinx
+
+## ToDo:
+* anspruchsvollere Aufgaben
+* Weitere .md Dateien zu jedem Level im Wiki
+* Codebeispiele zu jedem Level im Repository
+* Lösungen für die Aufgaben
+* Glossar vervollständigen
+* ~~Kapitel 4~~
+* Link zu Operatoren.md, wenn es um .append geht, in Kapitel 3
+* Kapitel 2: Soll hier eine Verknüpfung zur PW Datei / Erklärung entstehen?
+* Erklärung Vorteile / Anwendungsmöglichkeiten der Schleifen
+* `with` in Level 7
+* Kapitel zu CLI-Anwendungen (argparse usw.)
+* Sets und listcomprehensions
+* with in Level 7
+* pip erwähnen
\ No newline at end of file
diff --git a/Operatoren.md b/Operatoren.md
new file mode 100644
index 0000000..705f53d
--- /dev/null
+++ b/Operatoren.md
@@ -0,0 +1,58 @@
+# Operatoren
+
+Python kennt diverse Operatoren (z.B. `+`, `-`, `*` und `/`).
+Diese sind allerdings nicht in der Sprache festgelegt,
+sondern sie hängen von den verwendeten Datentypen ab und werden dort definiert.
+Es ist sogar möglich (und erwünscht!), sie mit eigenen Datentypen zu verwenden.
+
+## int
+
+Auf `int`-Werte angewandt, verhalten sich die Operatoren wie normale Rechenoperatoren.
+
+ * ` + -> `: Die Summe der beiden Zahlen.
+ * ` - -> `: Die Differenz der beiden Zahlen.
+ * ` * -> `: Das Produkt der beiden Zahlen.
+ * ` / -> `: Der (exakte) Quotient der beiden Zahlen.
+ * ` // -> `: Der abgerundete Quotient der beiden Zahlen.
+ * ` % -> `: Modulo Division (Rest einer Division)
+ * ` ** -> `: Die Potenz der beiden Zahlen.
+ * ` << -> `: Bitshift nach links (äquivalent zu ` * (2 ** )`)
+ * ` >> -> `: Bitshift nach rechts (äquivalent zu ` // (2 ** )`)
+ * ` ^ -> `: bitweises XOR
+
+## float
+
+Bei `float`-Werten funktioniert das fast alles genau so wie bei `int` mit der Besonderheit,
+dass alle Rückgabewerte auch `float` sind. (Dies gilt auch, wenn `int` und `float` gemischt werden.)
+Außerdem funktionieren die Bitoperatoren `<<`, `>>` und `^` nicht auf floats.
+
+## bool
+
+Die oben beschriebenen `int`-Operationen lassen sich auch auf `bool`-Werte anwenden. Dabei gilt:
+
+ * `True == 1`
+ * `False == 0`
+
+Außerdem gibt es auch noch weitere boolesche Operatoren:
+
+ * ` and -> `: logisches Und
+ * ` or -> `: logisches Oder
+ * `not -> `: logisches Nicht
+
+## str
+
+Bei Strings ist das Verhalten auch sinnvoll, aber auf den ersten Blick eventuell anders als erwartet:
+
+ * ` + -> `: Verkettet die beiden Strings.
+ * ` * -> `: Hängt den String n-mal hintereinander. (äquivalent zu n-mal `+`)
+
+## list
+
+Bei Listen funktioniert das auch:
+
+ * ` + -> `: Verkettet die beiden Listen.
+ * ` * -> `: Hängt die Liste n-mal hintereinander. (äquivalent zu n-mal `+`)
+
+## tuple
+
+Bei Tupeln funktioniert alles genau wie bei Listen mit der Besonderheit, dass alle Rückgabewerte auch `tuple` sind.
diff --git a/Python27.md b/Python27.md
new file mode 100644
index 0000000..543a36b
--- /dev/null
+++ b/Python27.md
@@ -0,0 +1,41 @@
+# Python 2.7
+
+Wir stellen nur aktuelle Versionen von Python vor.
+Es kann allerdings sein, dass man für manche (sehr speziellen) Einsatzzwecke Python 2.7 verwenden muss.
+
+Mit dem Erscheinen von Python 3.0 wurden einige größere Änderungen eingebracht - und die fehlen dann natürlich in 2.7. Außerdem hat die Standardbibliothek im Laufe der Zeit einige neue Module erhalten.
+
+## Aktivieren des bereits unterstützten neuen Verhaltens
+
+Python 2.7 unterstützt viele Änderungen in Python 3.0 schon - sie müssen nur noch aktiviert werden. Dazu müssen die folgenden zwei Zeilen an den Anfang (!) jeder Datei gepackt werden:
+
+
+```python
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function, unicode_literals
+from io import open
+```
+
+(Warum unbedingt an den Anfang der Datei?
+Syntaktisch ist das ein Kommentar und ein `import`-Statement, semantisch sind dies allerdings Anweisungen an den Compiler.)
+
+Die erste Zeile sorgt dafür, dass der Quellcode als [UTF-8](http://utf8everywhere.org/) gelesen wird.
+Die zweite Zeile aktiviert die neue Import-Reihenfolge, die neue Division (`/` gibt `float` zurück), die `print`-Funktion (statt einem Statement) und Unicode-Strings als Standard.
+Die dritte Zeile ersetzt `open` durch das aus Python 3 bekannte.
+
+## Dinge, die anders sind
+
+ * `input` heißt `raw_input`
+ * viele Funktionen geben Listen oder Tupel zurück statt Iteratoren (z.B. `xrange` statt `range` verwenden)
+ * viele Funktionen verwenden Bytestrings statt Unicodestrings
+ * Klassen müssen explizit von `object` erben
+ * `int`s, `list`s und `dict`s haben eine maximale Länge (eventuell statt `int` `long` verwenden)
+ * einige Dinge in der Standardbibliothek wurden verschoben (siehe z.B. [diese Tabelle](https://six.readthedocs.io/#module-six.moves))
+ * ...
+
+
+## neue Module aus der Standardbibliothek, die sich nachinstallieren lassen
+
+ * [ipaddress](https://pypi.org/project/ipaddress/)
+ * [enum34](https://pypi.org/project/enum34/)
+ * ...
diff --git a/README.md b/README.md
index 832221d..7e62b1c 100644
--- a/README.md
+++ b/README.md
@@ -2,8 +2,188 @@
**tl, dr**
The repository for PythonfooLite. The meeting for beginners in Python.
-Siehe auch unser [Wiki](https://github.com/pythonfoo/pythonfooLite/wiki).
+Und in ausführlich:
+Dies ist das Repository für das PythonfooLite, dem Meeting für Anfänger in der Programmiersprache Python. Es enthält sowohl Codebeispiele als auch Hilfstexte. Diese sollen dabei helfen, einen Einstieg in Python zu bekommen. Dabei sind die Codebeispiele in Level unterteilt, zum einem aus Gründen der Übersichtlichkeit und andererseits damit jemand, der schon einmal programmiert hat die Anfänge überspringen kann. Wenn du Python lernen möchtest, komm doch mal am ersten oder zweiten Donnerstag im Monat im Chaosdorf vorbei. Du kannst natürlich auch gerne zu Hause die Codebeispiele durchgehen.
-### Und in ausführlich:
-Dies ist das Repository für das PythonfooLite, dem Meeting für Anfänger in der Programmiersprache Python. Es enthält sowohl Codebeispiele als auch Hilfstexte. Diese sollen dabei helfen, einen Einstieg in Python zu bekommen. Dabei sind die Codebeispiele in Level unterteilt, zum einem aus Gründen der Übersichtlichkeit und andererseits damit jemand, der schon einmal programmiert hat die Anfänge überspringen kann. Wenn du Python lernen möchtest, komm doch mal am ersten oder zweiten Donnerstag im Monat im Chaosdorf vorbei. Du kannst natürlich auch gerne zu Hause die Codebeispiele durchgehen.
\ No newline at end of file
+## Einleitung
+
+> "The only way to learn a new programming language is by writing programs in it." - Dennis Ritchie
+
+Das PythonfooLite beschäftigt sich dezidiert mit Programmieranfängern oder Python-Neulingen. Aus der Erfahrung heraus, das diese im sich "normalen" Pythonfoo abgehängt fühlen, widmen wir die ersten beiden Donnerstage jedes Monats den Neulingen. Wer Lust hat kommt einfach vorbei, jeweils am ersten oder zweiten Donnerstag im Monat ab 18:00 im Chaosdorf. Es hilft einen tragbaren Rechner mitzubringen, auf dem man auch Programme installieren kann. Vorwissen über Programmierung wird nicht benötigt.
+
+## Python
+Wir beschäftigen uns beim Pythonfoo mit Python in der Version 3.x. Python ist eine Programmiersprache, die leicht zu lernen aber schwer zu meistern ist ("easy to learn, hard to master"). Das soll uns aber nicht abschrecken. Python verzichtet auf einige Eigenheiten populärer Sprachen (wie z.B. Java oder C), büßt somit Performanz ein, ist allerdings leichter zu lernen. Wenn man sich lange genug mit Python beschäftigt, ist es problemlos möglich andere Programmiersprachen zu lernen, da Grundlegende Konzepte schon aus der Theorie und Praxis bekannt sind und auf diesen aufgebaut werden kann.
+
+## Sprache
+Grundsätzlich sind alle Texte in Deutsch verfasst, die Codebeispiele jedoch enthalten teilweise englische Namen, da auch die Programmiersprache mit englischen Begriffen arbeitet. An einigen Stellen, werden in den Texten englische Begriffe verwendet, was meistens daran liegt, dass die deutsche Übersetzung sehr sperrig ist ("integer" <-> "ganze Zahl", "float" <-> "Fließkommazahl") oder weil der englische Begriff der weitaus gebräuchlichere ist.
+
+## Glossar
+Im Wiki des Github Repositories findest du ein Glossar, in dem die meisten Begriffe kurz erklärt werden.
+
+## Kontakt und Feedback
+Falls du Anregungen, Fragen, Einwände oder Ideen hast, kannst du uns natürlich an den ersten beiden Donnerstagen im Monat im Chaosdorf erreichen, oder eine Nachricht im Github Repository hinterlassen oder eine E-Mail an [pythonfoo@chaosdorf.de](mailto:pythonfoo@chaosdorf.de) schicken, zudem bietet GitHub noch ein Issue System, um Fehler im Repository zu melden. Wir sind über jegliche Art von Feedback dankbar.
+Da wir nur zwei Studenten sind, die Spaß daran haben, anderen die Grundlagen der Programmierung in Python näher zu bringen, sind wir natürlich weder allwissend oder unfehlbar. Die Codebeispiele und das Wiki im Repository sind insofern als "work in progress" zu sehen, dennoch sind wir für jegliches Feedback dankbar. Wir sind stetig damit beschäftigt die Codebeispiele und beiliegenden Texte zu erweitern und verbessern, auch in diesem Zusammenhang freuen wir uns über jegliches Feedback.
+
+## Gliederung
+Wir haben den Ablauf in Level unterteilt, die aufeinander aufbauen. Das sorgt dafür, dass wir den Ablauf individuell an den Kenntnisstand der Anwesenden anpassen können, was es nicht langweilig werden lässt. Die Level sind unten grob skizziert und geben einen Überblick. Zu jedem Level sind Stichwörter aufgeführt, die sich entweder im Glossar oder im Internet suchen lassen, und einen Einblick geben sollen um was es geht, damit du falls du bereits Erfahrung im Programmieren mit Python oder einer anderen Programmiersprache hast, weißt wo du am besten einsteigen kannst.
+
+### Zeiteinteilung
+Da die Level nicht gleich umfangreich sind und die Geschwindigkeit des Durchgehens stark vom Kenntnisstand bzw. eventuellen Vorkenntnissen abhängig ist, ist es schwierig allgemein zu sagen, wie viel Zeit für die Level eingeplant werden muss; die Erfahrung zeigt aber, dass die ersten 5 Level gut in einen bis zwei Abenden à 3 Stunden beendet werden können. Da zwischen Level 5.5 und Level 6 ein großer inhaltlicher Sprung besteht, bietet es sich an zwischen den Levels eine Pause zur Auffrischung und Wiederholung einzulegen. Zudem ist der Einstieg in Level 6 zuerst theoretisch, weshalb es besser ist, ausgeruht in das Level zu starten.
+
+### Aufgaben
+Zur Auffrischung und Anwendung des Gelernten, bieten wir zu den meisten Level Aufgaben an, die sich auf das Level beziehen und der Übung dienen sollen. Die Aufgaben sind natürlich vollkommen freiwillig wir schauen gerne über Lösungen drüber. In einigen Levels gibt es auch Beispiellösungen zu den Aufgaben. Da es für uns schwierig ist den Schwierigkeitsgrad der Aufgaben richtig zu wählen, sind wir hier auf Feedback angewiesen.
+
+### Level 0
+Level 0 ist Programmieranfänger gedacht und klärt die Grundlagen von Programmierung im Allgemeinen und mit Python.
+#### Stichwörter:
+* Programmiersprache
+* Anweisung
+* Compiler
+* Interpreter
+* hello_world.py
+* Code
+
+### Level 1
+Level 1 beginnt mit dem Programmieren einfacher Programme in Python und klärt Grundlegende Konzepte der Programmierung in Python, die sich aber auch auf andere Programmiersprachen übertragen lassen.
+#### Stichwörter:
+* Variable
+* Typ
+* Wert
+* Ausdruck
+* Integer
+* Float
+* String
+* Eingabe
+* Ausgabe
+* Schlüsselwort
+* Kommentar
+
+### Level 2
+Level 2 führt eine erste Kontrollstruktur ein, welche ein wichtiges Element jeder Programmiersprache darstellt. Des Weiteren wird ein neuer Typ eingeführt.
+#### Stichwörter:
+* Programmablauf
+* if-Bedingung
+* while-Schleife
+* Boolean
+
+### Level 3
+Level 3 beschäftigt sich nun mit einer weiteren Kommandostruktur, den Schleifen und führt dazu drei neue Typen ein. Nach Abschluss von Level 3, kann in der Theorie jedes Programm schon geschrieben werden.
+#### Stichwörter:
+* for-Schleife
+* Liste
+* Tupel
+* Dictionary
+* Sets
+
+### Level 4
+Level 4 beschäftigt sich mit dem Lesen und Bearbeiten von Textdateien.
+#### Stichwörter:
+* `pathlib`
+* `shutil`
+* Dateien lesen
+* Dateien speichern
+* Dateien verschieben
+* Dateien löschen
+
+### Level 5
+Level 5 beschäftigt sich mit dem Erstellen von Funktionen (ob mit oder ohne Parameter / Übergabewert) und Rekursion.
+#### Stichwörter:
+* Funktion
+* Gültigkeitsbereich
+* Rekursion
+* Rückgabewert
+* Docstrings
+
+### Level 5.5
+Dieses Level beschäftigt sich mit Themen, die in bisherigen Level nicht behandelt wurden, weil sie nichts mit Python zu tun haben oder nicht dem Fortschritt entsprachen. Dennoch sind diese Themen, nicht nur für die Programmierung in Python, sondern auch in anderen Programmiersprachen, sehr wichtig.
+
+#### Stichwörter:
+* Texteditor
+* IDE
+* Git und GitHub
+* [PEP8](https://www.python.org/dev/peps/pep-0008/)
+* `s.format()`
+* Bash / Terminal / Shell
+* JSON / CSV / TOML
+* Fehlersuche
+* Refactoring
+
+### Level 6
+
+In Level 6 geht es um Konsolen-Anwendungen. Diese kann man grob in zwei Arten unterteilen:
+ * Programme, die nur Parameter entgegennehmen und etwas ausgeben
+ * Programme, die interaktiv arbeiten
+
+Einfache Formen des letzteren Typs kamen bereits in den vorigen Level vor.
+
+#### Stichwörter:
+ * `argparse`
+ * `curses`
+
+### Level 7 (OOP 1)
+Level 7 widmet sich dem Bereich der Objektorientierten Programmierung. Dieses Konzept hat auch in vielen anderen Programmiersprachen eine große Bedeutung. In diesen Level werden die Kompetenzen vermittelt um eigene Typen zu definieren, Klassen oder Module zu schreiben, sowie ein grundsätzliches Verständnis von Objektorientierter Programmierung.
+
+#### Stichwörter:
+* Klassen
+* Bibliotheken
+* Objekt
+* Module
+* Imports
+* Attribute und Methoden
+* Vererbung
+* Überladung
+* `super()`
+* `isInstance()` und `is`
+
+### Level 8
+Level 8 beschäftigt sich mit Dingen, die thematisch in andere Level gehören, aber nicht zu deren Kenntnisstand passen.
+
+#### Exkurse:
+* `turtle` - Ein Modul zum Steuern einer Schildkröte
+* `random` - Ein Modul dass verschiedene Methoden für Pseudozufallszahlen bereitstellt
+#### Stichwörter:
+* Generatoren
+* Decoratoren
+* Exceptions
+* `map()` und `zip()`
+* assert
+
+**Folgendes ist eher fortgeschritten.**
+
+### Level 9 Nebenläufigkeit und Alternativen
+* Threads
+* `multiprocessing`
+* `asyncio`
+
+### Level 10 GUI
+Es gibt wahnsinnig viele Möglichkeiten,
+grafische Benutzeroberflächen mit Python zu realisieren.
+Wir beschränken uns hier auf Qt 5 als GUI-Toolkit.
+**nur kurz anreißen!**
+
+#### Aufgaben
+Ein Hauptfenster soll einen Button und ein Textfeld
+enthalten. Beim Klick auf den Button soll der Inhalt des
+Textfelds in einem Dialog angezeigt werden.
+
+### Level 11 Web
+Webanwendungen sind ein häufiger Einsatzzweck von Python.
+* Was ist HTTP und wie funktioniert es?
+* [requests](http://docs.python-requests.org/en/latest/)
+* [BeautifulSoup](https://www.crummy.com/software/BeautifulSoup/bs4/doc/)
+* CGI
+* WSGI
+* [Werkzeug](http://werkzeug.pocoo.org/)
+* [Django](https://www.djangoproject.com/) (/[Flask](http://flask.pocoo.org/)?) **nur kurz anreißen!**
+
+#### Aufgaben
+* *Hallo Welt!* als Webapp
+
+### Level 12 Packaging und Repos
+Mit `setuptools` und `pip` kann man Pakete erstellen, packen und installieren.
+* [pypi](https://pypi.org/) als Repository
+* Pakete aus dem Internet herunterladen und installieren
+* Pakete erstellen
+* Pakete bauen
+* Pakete hochladen
diff --git a/Rekursion_Vs._Iteration.md b/Rekursion_Vs._Iteration.md
new file mode 100644
index 0000000..8b7023d
--- /dev/null
+++ b/Rekursion_Vs._Iteration.md
@@ -0,0 +1,65 @@
+# Rekursion Vs. Iteration
+## Einleitung
+Zum Anfang betrachten wir, was genau Rekursion ist. Im Grunde ist Rekursion nämlich nur ein Sprachfeature, dass eine Funktion sich selber aufrufen kann. Jedoch ist eine Programmiersprache auch ohne Rekursion Turing komplett, d.h. ich kann jedes Programm auch ohne Rekursion implementieren. Das wird unter anderem dadurch deutlich, dass eine rekursive Funktion beim Übersetzen in Maschinencode als Schleife ausgeführt wird. Zusammenfassend kann man also sagen:
+
+> Alles was sich iterativ implementieren lässt, lässt sich auch rekursiv
+> implementieren und anders herum.
+
+Rekursion bietet sich an, da viele Algorithmen rekursiv definiert sind und daher rekursiv leichter zu implementieren sind als iterativ. Damit ist jedoch nicht gesagt, dass die rekursive Implementierung die effizientere ist. Ein einfaches Beispiel dafür sind die Fibonacci-Zahlen.
+
+## Die Fibonacci-Zahlen
+Die Fibonacci-Zahlen tauchen in der Natur auf und sind eine relativ schnell wachsende Zahlenfolge, die folgendermaßen definiert ist:
+```
+fib(0) = 1
+fib(1) = 1
+fib(n) = fib(n-2) + fib(n-1)
+```
+### Einfache rekursive Implementierung
+
+Die Definition ist eindeutig rekursiv, folglich wäre der simpelste Ansatz diese Zahlenfolge zu implementieren die folgende:
+``` python
+def fibR(n): # Fibonacci Rekursiv
+ if n == 0 or n == 1:
+ return 1
+ return fibR(n-2) + fibR(n-1)
+```
+
+### Probleme
+
+Dieser Code funktioniert, ist leicht zu lesen hat aber einige Nachteile:
+
+#### Rekursionslimit
+
+Der Rekursion ist ein Limit gesetzt, weshalb der Code bei größeren Zahlen in einen `RecursionError`laufen wird. In diesem Fall passiert dies schon sehr früh, weil es zwei rekursive Aufrufe in der Funktion gibt.
+
+#### Laufzeit
+
+Das weitaus größere Problem ist die Laufzeit, denn dadurch, dass fibR(n-2) und fibR(n-1) aufgerufen werden, wird fibR() immer häufiger aufgerufen:
+```
+n = 5
+fibR(5) wird 1 mal aufgerufen
+fibR(4) wird 1 aufgerufen
+fibR(3) wird 2 mal aufgerufen
+fibR(2) wird 3 mal aufgerufen
+fibR(1) wird 5 mal aufgerufen
+fibR(0) wird 8 mal aufgerufen
+```
+Wenn man sich die Anzahl der Aufrufe genau anschaut, stellt man fest dass es sich um die Fibonaccifolge handelt. Die rekursive Implementation berechnet also ihre eigene Laufzeit. Da die Fibonaccifolge aber relativ schnell wächst, wächst auch die Laufzeit relativ schnell.
+
+### Lösung
+
+Da jeder Algorithmus sowohl rekursiv, als auch iterativ implementiert werden kann und die rekursive Implementation Probleme aufwies, versuchen wir jetzt die Fibonacci Folge iterativ zu implementieren:
+
+```
+def fibI(n): # Fibonacci Iterativ
+ last = 1
+ current = 1
+ for i in range(0,n):
+ current, last = current + last, current
+ return current
+```
+
+Diese Funktion implementiert die Folge iterativ, läuft daher nicht in einen `RecursionError` benötigt `n` Durchläufe der Schleife, ist also deutlich schneller als die rekursive Implementierung.
+
+### Fazit
+Die beiden gezeigten Implementierungen eines einfachen Problems, waren ungefähr gleich komplex, haben sich aber in der Laufzeit stark unterschieden. Beide Möglichkeiten der Implementation haben jedoch ihre Vorzüge, weshalb im Einzelfall entschieden werden muss, mit welcher Methode ein Algorithmus implementiert wird.
diff --git a/Shell.md b/Shell.md
new file mode 100644
index 0000000..2e30c45
--- /dev/null
+++ b/Shell.md
@@ -0,0 +1,27 @@
+# Der Umgang mit der Shell
+***ToDo:** Hier den Link zum Kurs von Github für Git*
+## Was ist die Shell?
+## Wie rufe ich die Shell auf?
+In UNIX Systemen wird meistens als Terminal oder Konsole ein Shell Emulator geöffnet.
+Diese können eine Graphische Oberfläche haben, können aber auch nur Textbasiert sein (beispielsweise die Standard Terminals tty1 - tty6).
+## Welche Unterschiede gibt es zwischen den Betriebssystemen?
+## Welche Befehle sind für den Anfang wichtig?
+#### UNIX:
+* **cd** - Wechselt das Verzeichnis in den angegebenen Pfad
+* **mv** - Verschiebt eine Datei oder einen Ordner
+* **touch** - Legt eine leere Datei an
+* **mkdir** - Legt ein neues Verzeichnis an
+* **ls** - Listet den Inhalt eines Verzeichnisses auf
+* **rm** - Löscht eine Datei oder ein Verzeichnis
+* **man** - Öffnet den Handbucheintrag zu einem Befehl oder Programm
+* **clear** - Löscht die aktuelle Ausgabe
+#### Windows:
+
+
+## Welche Konsolen-Programme empfehlt ihr mir?
+
+* **htop** - Prozessmonitor in der Konsole in Farbe (UNIX Systeme)
+* **git** - Ein Konsolen-Programm zur Versionskontrolle (siehe "Versionskontrolle.md")
+* **pip3** - Paketmanager für Python3 Bibliotheken (UNIX Systeme)
+* **bpython3** - Bunter Python-Interpreter mit Autovervollständigung (UNIX Systeme)
+* **fish** - Weitere Shell mit Features, Unterschiede zur **Bash** vorhanden (UNIX Systeme)
\ No newline at end of file
diff --git a/Versionskontrolle.md b/Versionskontrolle.md
new file mode 100644
index 0000000..0aaa58e
--- /dev/null
+++ b/Versionskontrolle.md
@@ -0,0 +1,27 @@
+# Einstieg in Git und Github
+## Was ist Versionskontrolle?
+Mit einer Versionskontrolle ist es möglich die verschiedenen Versionen eines Programms, welche beim Programmieren natürlich entstehen, zu dokumentieren. So ist es möglich Änderungen rückgängig zu machen verschiedene Entwicklungszweige zusammen zu führen oder die Arbeit mehrerer Leute mit einander zu verknüpfen.
+
+## Warum möchte ich Versionskontrolle haben?
+Mit einer funktionierenden Versionskontrolle kann ich:
+
+ * Mit vielen Leuten an einem Projekt arbeiten, ohne sich im Weg zu stehen
+ * Schnell die Version finden, bei der alles kaputt ging
+ * Auf einfache Weise nachvollziehen wie sich mein Projekt entwickelt hat
+ * Den Fortschritt meines Projektes im Auge behalten
+
+Versionsverwaltung hat zwar nur indirekt mit Programmierung zu tun, ist aber ein sehr praktisches Hilfsmittel, gerade wenn es um größere Projekte geht, an denen eventuell auch mehrere Leute arbeiten. Durch die Möglichkeit zu einer bestimmten Version zurückspringen zu können, wird es einfacher Fehler zu finden. Sobald die Verwaltung der Versionskontrolle in den Workflow eines Projektes übergegangen ist, wird die Entwicklung
+
+## Was ist git?
+Nachdem jetzt (hoffentlich) klar wurde, warum Versionskontrolle beim Programmieren eine gute Idee ist, ist es natürlich wichtig zu wissen, wie man das denn umsetzt, dazu gibt es glücklicherweise eine einfache Möglichkeit: Git. Git ist, sehr vereinfacht, eine Möglichkeit Versionskontrolle durchzuführen, die sich bewährt hat.
+
+## Wie funktioniert Git?
+
+## Wie benutze ich git?
+Git lässt sich unter UNIX als Konsolen-Programm ausführen, unter Windows ist das EInbinden und das Arbeiten mit Git etwas komplexer.
+
+### Ich will aber nicht in der Konsole arbeiten
+Es gibt sowohl unter Windows als auch unter Linux, Programme mit einer graphischen Oberfläche, welche git dann im Hintergrund aufrufen, falls einem die Arbeit mit der Konsole zu kompliziert erscheint. Allerdings lassen sich gerade die komplexeren Operationen in der Konsole komfortabler lösen lassen und die Hilfestellungen im Internet™ häufig zu den Konsolen-Befehlen ausführlicher sind.
+
+## Was ist Github?
+## Wie benutze ich Github?
diff --git a/passwort.md b/passwort.md
new file mode 100644
index 0000000..79a77b9
--- /dev/null
+++ b/passwort.md
@@ -0,0 +1,138 @@
+# Einfache Passwortabfragen
+Passwortabfragen werden häufig benutzt um die Authentizität eines Nutzers zu überprüfen, dabei bildet ein Passwort eine Art Geheimnis, dass ich dem Dienst mitgeteilt habe und das, im Idealfall, nur mir bekannt sein sollte. Somit kann ich dem Dienst zumindest zeigen, dass ich die Person hinter diesem Account bin. In Zeiten von Zwei-Faktor Authentifizierung geraten einfache Passwortabfragen immer mehr in den Hintergrund, sie dienen hier aber auch nur als anschauliches Beispiel zum Umgang mit if-Bedingungen und generell zur Art, wie man ein Programm schreibt.
+Generell sollten wir beim Programmieren immer darauf achten, möglichst einfach anzufangen, dabei erkennt man dann wie der Code noch verbessert werden kann. Wir schreiben also ersteinmal Code, der auf die simpelste Art und Weise den Anforderungen entspricht und verbessern ihn fortlaufend. Dabei kann uns auch Versionskontrolle helfen Änderungen zu widerrufen.
+Wenn wir also als Anforderung hätten
+**Schreiben SIe ein Programm, das ein Passwort abfragt und etwas ausgibt, falls das Passwort dem vorgegebenen entspricht.**
+würde folgendes Programm der Anforderungen komplett entsprechen:
+
+```python
+password = "12345678"
+password_input = input("Bitte geben Sie das Passwort ein: ")
+if password == password_input:
+ print("Zugang gewährt")
+```
+
+Theoretisch könnte man selbst dieses Programm weiter vereinfachen, worauf wir an der Stelle aber verzichten.
+Es dürften aber schon einige Schwachstellen aufgefallen sein:
+
+* Es gibt keine Ausgabe bei Eingabe eines falschen Passworts
+* Das Programm beendet direkt nach einer falschen Eingabe
+* Der Benutzer hat nur eine Möglichkeit das Passwort einzugeben
+* Das Passwort kann beim Eingeben gelesen werden
+* Das Passwort kann aus dem Quellcode gelesen werden
+
+Um diese Nachteile wollen wir uns jetzt kleinschrittig kümmern, um am Ende ein Programm geschrieben zu haben, dass die selben Anforderungen vom Anfang erfüllt aber noch zusätzlich die Nachteile ausbügelt.
+### Es gibt keine Ausgabe bei Eingabe eines falschen Passwort
+Dies lässt sich mit wenig Aufwand am vorhandenen Code ändern:
+
+```python
+password = "12345678"
+password_input = input("Bitte geben Sie das Passwort ein: ")
+if password == password_input:
+ print("Zugang gewährt")
+else:
+ print("Das Passwort war falsch")
+```
+Durch den `else`-Zweig wird auch etwas ausgegeben, falls das Passwort nicht richtig war.
+
+### Das Programm beendet direkt nach einer falschen Eingabe
+Hier bemerken wir, dass wir ihn schon behoben haben, da jetzt etwas ausgegeben wird.
+###Der Benutzer hat nur eine Möglichkeit das Passwort einzugeben
+Dies ist tatsächlich ein Problem, da gerade bei langen komplizierten Passwörtern die Möglichkeit größer wird, sich bei einem einzigen Zeichen zu vertun. Wir wollen also nun dem Benutzer 3 Versuche geben das Passwort richtig einzugeben:
+```python
+password = "12345678"
+counter = 1
+while counter <= 3
+ password_input = input("Bitte geben Sie das Passwort ein: ")
+ if password == password_input:
+ print("Zugang gewährt")
+ break
+ else:
+ print("Das Passwort war falsch")
+ counter += 1
+```
+Durch das benutzen der while-Schleife hat der Benutzer jetzt 3 Versuche das Passwort einzugeben, ohne, dass es neu abgefragt wird, wenn es bereits richtig eingegeben wurde. Hier wurde ein Teil der Optimierung schon implizit übernommen, da eine Schleife nicht notwendig gewesen wäre um ein Password 3 mal abzufragen. So hätte man das Programm auch folgendermaßen schreiben können:
+```python
+password = "12345678"
+access = False
+if not access:
+ password_input = input("Bitte geben Sie das Passwort ein: ")
+ if password == password_input:
+ print("Zugang gewährt")
+ access = True
+ else:
+ print("Das Passwort war falsch")
+
+if not access:
+ password_input = input("Bitte geben Sie das Passwort ein: ")
+ if password == password_input:
+ print("Zugang gewährt")
+ access = True
+ else:
+ print("Das Passwort war falsch")
+
+if not access:
+ password_input = input("Bitte geben Sie das Passwort ein: ")
+ if password == password_input:
+ print("Zugang gewährt")
+ access = True
+ else:
+ print("Das Passwort war falsch")
+
+```
+Spätestens jetzt sollte aber aufgefallen sein, das eine Schleife hier angebracht ist, zumal manchmal das Passwort ja auch 10-mal eingegeben werden kann.
+
+### Das Passwort kann beim Eingeben gelesen werden
+Um diesen Issue zu beheben müssen wir uns von der `input()` Funktion trennen, da bei ihrer Benutzung immer die Eingabe angezeigt wird. Daher benutzen wir nun die `getpass` Methode aus dem Modul `getpass`:
+```
+from getpass import getpass as passinput
+password = "12345678"
+counter = 1
+while counter <= 3
+ password_input = passinput("Bitte geben Sie das Passwort ein: ")
+ if password == password_input:
+ print("Zugang gewährt")
+ break
+ else:
+ print("Das Passwort war falsch")
+ counter += 1
+```
+Zum Glück funktioniert `getpass.getpass()`fast genauso wie `input()` weshalb wir nur minimale Änderungen vornehmen mussten. Was aber auffällt ist, das wir gerade etwas geändert haben, was seit der ersten Version des Programms schon da war und somit sehr relevant war. Das sollte uns daran erinnern, das wir kein Code in Stein meißeln sondern so agil sein müssen, auch altbewährtes neu zu schreiben.
+
+### Das Passwort kann aus dem Quellcode gelesen werden
+Dieser Issue ist gewissermaßen ein wenig widersinnig, denn bisher kann das unser Programm vom Benutzer geändert werden. Trotzdem wollen wir uns anschauen wie dieser Issue geschlossen werden kann. Dafür müssen wir uns kurz mit Hashwerten befassen. Das Prinzip hinter einem Hashwert ist, dass ich aus einer Eingabe einen Wert erzeuge, wobei die Eingabe immer zu diesem Hashwert führen wird aber auch andere Eingaben zu diesem Hashwert führen können, weshalb man aus dem Hashwert nicht auf die Eingabe schließen kann. Beim Hashen der Eingabe gehen Informationen verloren, die nicht wiederhergestellt werden können. Genau diesen Effekt nutzen wir im Folgenden aus.
+
+```python
+import bcrypt
+pwd = b"Test1234"
+salt = bcrypt.gensalt()
+hashed_pwd = bcrypt.hashpw(pwd,salt)
+print(hashed_pwd)
+```
+
+Doch wie nutzen wir den jetzt konkret Hashwerte für unsere Passwortabfrage? Nun im folgenden werden wir nicht mehr Passworteingabe und Passwort vergleichen, sondern die Passworteingabe hashen und mit dem Hash vom Passwort vergleichen, sodass das Passwort selber nicht im Quellcode steht. Wir nutzen dafür das `bcrypt` Modul, das für das Hashen von Passwörtern gedacht ist.
+Nun können wir unser Programm umändern:
+
+``` python
+from getpass import getpass as passinput
+import bcrypt
+passwordHash = ""
+counter = 1
+while counter <= 3
+ password_input = passinput("Bitte geben Sie das Passwort ein: ")
+ password_input = password_input.encode(password_input)
+ salt = bcrypt.gensalt()
+ inputHash = bcrypt.hashpw(password_input, salt)
+ if passwordHash == inputHash:
+ print("Zugang gewährt")
+ break
+ else:
+ print("Das Passwort war falsch")
+ counter += 1
+```
+Es liegt aber noch ein Problem vor:
+Hash-Funktionen verlieren Informationen, das heißt, dass mehrere Eingaben den selben Hashwert liefern können, weshalb der Benutzer nicht **das** Passwort eingeben muss, dass den Hashwert ergibt, sondern nur **eins** von denen, die diesen Hashwert ergeben. An dieser Stelle vertrauen wir darauf, dass die Wahrscheinlichkeit für so eine Kollision niedrig genug ist um sie zu tolerieren, zumal wir ja die Eingabe auf 3 Versuche beschränkt haben.s
+
+## Fazit:
+Wir haben mit einem Programm angefangen, das genau den gestellten Anforderungen entsprach. Anschließend haben wir Probleme mit unseren Programm ausgemacht und diese Issues in 5 Schritten behoben. Dabei haben wir zuerst nur Funktionalität hinzugefügt und in den letzten beiden Schritten auch bestehenden Code verändert. Wir haben aber die Funktionalität der ersten Version erhalten gelassen. Diesen Vorgang nennt man Refactoring. Bei dem Optimieren des Codes kann Versionskontrolle eine sehr wichtige Rolle spielen, denn es kann sein, dass man den Code über-optimiert und er auf ein mal nicht mehr tut was er soll. Vorausgesetzt man hat eine ordentliche Versionskontrolle durchgeführt, kann man nun von dem letzten funktionierenden Stand aus vorwärts gehen und so die Änderung ausfindig machen, die das Programm zerschossen hat.
+Sowohl zu Refactoring als auch zu Versionskontrolle haben wir eigene Folien (geplant).
diff --git a/random.md b/random.md
new file mode 100644
index 0000000..8f10bdf
--- /dev/null
+++ b/random.md
@@ -0,0 +1,53 @@
+# random
+Das Modul random ermöglicht einfache aber vielfältige Operationen mit Zufallszahlen. Hierbei sei gesagt, dass der eingebaute Zufallsgenerator bei weitem nicht der Beste ist und schon gar nicht für kryptographische Operationen genutzt werden sollte.
+Wir fangen damit an das Modul random zu importieren und uns die Attribute und Methoden anzuschauen:
+```python
+import random
+print(dir(random))
+```
+Als Ausgabe bekommen wir:
+```python
+['BPF', 'LOG4', 'NV_MAGICCONST', 'RECIP_BPF', 'Random', 'SG_MAGICCONST', 'SystemRandom', 'TWOPI', '_BuiltinMethodType', '_MethodType', '_Sequence', '_Set', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_acos', '_ceil', '_cos', '_e', '_exp', '_inst', '_log', '_pi', '_random', '_sha512', '_sin', '_sqrt', '_test', '_test_generator', '_urandom', '_warn', 'betavariate', 'choice', 'expovariate', 'gammavariate', 'gauss', 'getrandbits', 'getstate', 'lognormvariate', 'normalvariate', 'paretovariate', 'randint', 'random', 'randrange', 'sample', 'seed', 'setstate', 'shuffle', 'triangular', 'uniform', 'vonmisesvariate',
+'weibullvariate']
+```
+Viele dieser Sachen sind allerdings ersteinmal uninteressant, deshalb wollen wir uns daher ersteinmal auf folgende Dinge beschränken:
+
+* choice
+* gauss
+* randint
+* random
+* randrange
+* sample
+* seed
+* shuffle
+
+### random.seed()
+Wir wollen dabei mit random.seed() anfangen. Mit dieser Methode können wir den Seed für die Zufallsberechnung setzen. Der Seed wird bei der Zufallsberechnung als Ausgang genommen, was bedeutet, das bei dem selben Seed immer derselbe Strom an Zufallszahlen entstehen wird. Daher ist diese Methode auch essentiell wichtig, da sie die anderen der obigen Methoden beeinflusst.
+```python
+import random
+random.seed("foo")
+random.random() # 0.45443115919715416
+random.random() # 0.27540896360984124
+```
+Um Zufall zufällig zu behalten sollte **niemals** ein statischer Seed oder ein sehr primitiver Seed (wie zum Beispiel Datum oder Uhrzeit) benutzt werden.
+
+
+### random.random()
+Wir haben eben eine weitere Methode benutzt ohne sie einzuführen. Diese Methode liefert eine Fließkommazahl zwischen 0 und ausschließend 1 zurück.
+```python
+import random
+random.random()
+```
+
+### random.randint()
+Diese Methode erwartet zwei Parameter (einen Startwert und einen Endwert) und gibt eine Zufallszahl zwischen diesen beiden Werten zurück, wobei der Endwert ausgenommen ist.
+```python
+import random
+R = random.randint(0,10)
+print(R)
+```
+ist äquivalent zu:
+```python
+import random
+R = int(random.random()*10)
+```
diff --git a/turtle.md b/turtle.md
new file mode 100755
index 0000000..a927ad1
--- /dev/null
+++ b/turtle.md
@@ -0,0 +1,232 @@
+# Einstieg in turtle
+## Vorwort
+Im folgenden wird das `turtle`-Modul aus der Standardbibliothek vorgestellt, die Beispiele sind absichtlich einfach gehalten und sollen einen sanften Einstieg gewährleisten. Um den Codebeispielen folgen zu können, solltest du wissen:
+
+* wie du auf deinem System Pythoncode ausführst
+* was eine Variable ist
+* was ein Funktionsaufruf ist
+* was ein `int`, ein `string` und ein `float`sind
+* was eine `if`-Bedingung ist
+* was eine Schleife ist
+
+Solltest du bei einem der oben genannten Punkte noch Fragen oder Probleme haben, schau dir doch mal die Level 0 - 2 an.
+
+## Das turtle-Modul
+Mit dem `turtle` Modul ist es möglich, mit Hilfe von einfachen Befehlen/Funktionen die namensgebende turtle über ein Fläche zu bewegen.
+Die turtle zeichnet dabei standardmäßig eine Spur hinter sich, dies kann benutzt werden um einfache bis komplexe Formen auf der 2D-Ebene zu zeichnen.
+Das `turtle`-Modul stellt dafür einfache Funktionen bereit, die miteinander verknüpft werden können um die turtle zu bewegen.
+
+Viele `turtle`-Methoden bieten Aliase an (z.B. `turtle.fd()` statt `turtle.forward()`). Diese Aliase vermindern die Schreibarbeit, leider aber auch die Lesbarkeit. Ob du diese Aliase benutzen willst, um ein paar Zeichen zu sparen, bleibt selbstverständlich dir überlassen. Wir weisen bei den Funktionen auf ihre jeweiligen Aliase hin.
+
+Im folgenden sollen in kurzen Codeabschnitten, die einzelnen Funktionen vorgestellt werden. Die Codeabschnitte sind so konzipiert, dass sie einfach in den Interpreter oder eine .py-Datei kopiert werden können, ohne auf vorherige Abschnitte angewiesen zu sein. Daher fängt jeder Codeabschnitt auch mit dem `import`-Statement an.
+
+Für den Anfang kannst du die turtle am einfachsten aus dem Interpreter heraus steuern. Öffne dazu den Python-Interpreter deiner Wahl, importiere die `turtle`-Bibliothek und fang an der turtle Befehle zu geben. Dann sollte sich ein Fenster öffnen, in dem du die turtle beobachten kannst. Die Arbeit im Interpreter hat den Vorteil, dass du die Auswirkungen deines Codes direkt sehen kannst. Es bietet sich also an deinen Python-Interpreter und das turtle-Fenster nebeneinander zu öffnen.
+
+## Die turtle bewegen
+Die `forward()` und `backward()` Methoden können für die Bewegung benutzt werden. Die turtle läuft dabei die angegebene Strecke ab und zieht eine Spur hinter sich her. Dabei ändert sich nicht ihre Richtung. Beim Start des Programms ist die Richtung `0` was nach rechts entspricht.
+
+Alternativ zu `turtle.forward(n)` kann auch `turtle.fd(n)` und statt
+`turtle.backward(n)` `turtle.bk(n)` benutzt werden.
+``` python
+import turtle
+turtle.forward(50) # bewegt die turtle um 50 Pixel nach vorne
+turtle.backward(25) # bewegt die turtle um 25 Pixel nach hinten
+```
+
+Um die turtle zu drehen und somit ihre Richtung zu ändern, gibt es die `left()` und `right()` Methode, welche die turtle um eine bestimmte Grad-Zahl in die entsprechende Richtung drehen. Alternativ zu `left()` und `right()` können auch die Alias-Methoden `lt()` bzw. `rt()` benutzt werden.
+``` python
+import turtle
+turtle.forward(50) # bewegt die turtle um 50px
+turtle.left(90) # dreht die turtle um 90° nach links
+turtle.forward(20) # bewegt die turtle um 20px
+turtle.right(180) # dreht die turtle um 180° nach rechts
+turtle.forward(20) # bewegt die turtle um 20px
+```
+
+## Auslesen von Position und Richtung
+Die Methoden `turtle.position()` und `turtle.heading()` liefern uns die aktuelle Position bzw. Richtung der turtle. Diese Methoden können zum Beispiel dabei helfen, nicht über den Rand zu laufen oder eine Kreislinie entlang zu laufen.
+``` python
+import turtle
+turtle.forward(100) # bewegt die turtle um 100px
+turtle.left(90) # dreht die turtle um 90° nach links
+turtle.forward(50) # bewegt die turtle um 50px
+
+position = turtle.position() # aktuelle Position
+print(position) # Out: (100.00,50.00)
+
+heading = turtle.heading() # aktuelle Richtung
+print(heading) # Out: 90.0
+```
+Alternativ zu `turtle.position()` kann `turtle.pos()` verwendet werden.
+
+Zusätzlich zu den Methoden `forward()` und `backward()` welche die turtle relativ zu ihrer aktuellen Position bewegen, kann auch die `setposition()` Methode benutzt werden um die turtle unabhängig von ihrer aktuellen Position und Richtung zu einer bestimmten Position zu bewegen. Dabei wird die Richtung beibehalten.
+``` python
+import turtle
+turtle.setposition((100, 0)) # bewegt die turtle zu angegebenen Position
+turtle.setposition((100, 100))
+```
+Alternativ zur `setposition()`-Methode können auch die Alias-Methoden `setpos()` oder `goto()` benutzt werden.
+
+Analog zur `turtle.setposition()`-Methode kann die `turtle.setheading()`-Methode benutzt werden um die Richtung der turtle unabhängig von ihrer aktuellen Richtung zu verändern. Standardmäßig erwartet die Methode eine Grad-Zahl als `int` oder `float`. Hierbei entsprechen 0° nach rechts, 90° nach oben, 180° nach links, 270° nach oben. Es ist allerdings auch möglich negative Werte anzugeben (-90° entspricht nach unten).
+``` python
+import turtle
+print(turtle.heading()) # Out: 0.0
+
+turtle.setheading(90) # setzt die Richtung der turtle auf die angegebene Grad-Zahl
+turtle.forward(50)
+
+print(turtle.heading()) # Out: 90.0
+print(turtle.position()) # Out: (0.00, 50.00)
+```
+Alternativ zur `setheading()`-Methode kann auch die Alias-Methode `seth()` benutzt werden.
+
+Eine praktische Methode im Zusammenhang mit Position und Richtung ist die `turtle.home()`-Methode, welche Position und Richtung auf `(0.00, 0.00)` bzw. `0.0` zurücksetzt.
+
+Mit Hilfe der `distance()`-Methode kann die Entfernung der turtle zum Beispiel zu einer Position berechnet werden.
+```python
+import turtle
+turtle.setposition((100, 100))
+distance = turtle.distance((0, 0)) # berechnet die Distanz zur Position
+print(distance) # Out: 141.4213562373095
+```
+
+Analog zur `distance()`-Methode kann mit der `towards()`-Methode der Winkel der Linie zwischen der aktuellen Position und der angegebenen Position.
+```python
+import turtle
+turtle.setposition((100, 100))
+gradient = turtle.towards((0, 0))
+print(gradient)
+# Out: 225.0
+```
+
+## Manipulation der gezogenen Linie
+Standardmäßig zeichnet die turtle eine schwarze Linie, wenn sie sich bewegt. Mit `turtle.penup()` und `turtle.pendown()` ist es möglich den *Stift* zu heben un zu senken und somit das Zeichnen der Linie zu unterbrechen. Dies kann sinnvoll sein um die turtle zu einer Ausgangsposition zu bewegen, ohne dabei eine Linie zu ziehen. Gerade in Verbindung mit der `turtle.setposition()`- und der `turtle.home()`-Methode ergibt es Sinn den *Stift* anzuheben.
+
+Der folgende Codeabschnitt bewegt die turtle zu einer Ausgangsposition `(-100, -100)` und zeichnet anschließend ein Quadrat mit einer Seitenlänge von 200 Pixeln, dessen Mitte bei `(0.00, 0.00)` liegt.
+```python
+import turtle
+turtle.penup() # Stift heben -> keine Linie
+turtle.setposition((-100, -100)) # Ausgangsposition
+turtle.pendown() # Stift senken -> Linie
+for i in range(4):
+ turtle.forward(200)
+ turtle.left(90)
+```
+Alternativ zu `turtle.penup()` können auch die Alias-Methoden `turtle.pu()` oder `turtle.up()` benutzt werden. Alternativ zu `turtle.pendown()` können auch die Alias-Methoden `turtle.pd()` oder `turtle.down()` benutzt werden.
+
+Mit Hilfe der `turtle.isdown()`-Methode kann überprüft werden, ob der *Stift* gesenkt ist, also ob gerade eine Linie gezogen wird.
+```python
+import turtle
+turtle.penup() # Stift heben -> keine Linie
+pen_status = turtle.isdown()
+print(pen_status)
+# Out: False
+
+turtle.pendown() # Stift senken -> Linie
+pen_status = turtle.isdown()
+print(pen_status)
+# Out: True
+```
+
+Die Farbe der Linie, welche von der turtle gezogen wird, lässt sich mit der `turtle.pencolor()` lesen und verändern. Übergeben wir der Methode keine Parameter, wird die aktuelle Farbe zurückgegeben. Übergeben wir der `turtle.pencolor()`-Methode allerdings einen Parameter, der eine entsprechende Farbe enthält, so nimmt der Stift diese Farbe an.
+```python
+import turtle
+color = turtle.pencolor()
+print(color)
+# Out: 'black'
+turtle.pencolor("red")
+turtle.forward(100)
+```
+
+Es gibt verschiedene Formate der `turtle.pencolor()`-Methode einen Farbparameter zu geben. Im oberen Beispiel wurde ein *color string* benutzt, eine weiteres Format besteht in einem *RGB-tuple* welches die Farbe als Mischung aus **R**ot, **G**rün und **B**lau angibt.
+```python
+import turtle
+turtle.pencolor((255, 0, 0)) # setzen der Farbe mit einem RGB-tuple
+turtle.forward(100)
+```
+
+Weitere Informationen zu den verschiedenen Formaten findest du in der Dokumentation zum `turtle`-Modul: https://docs.python.org/3/library/turtle.html#turtle.pencolor.
+
+Neben der Stiftfarbe ist es möglich die Stiftbreite zu ändern. Dafür wird die `turtle.pensize()`-Methode benutzt. Der folgende Codeschnippsel zeichnet das Quadrat von weiter oben, diesmal allerdings mit einer größeren Stiftbreite. Ähnlich zur `turtle.pencolor()`-Methode, liest die `turtle.pensize()` den aktuellen Wert aus, sollten keine Parameter übergeben werden und setzt den Wert der Stiftbreite, sollten Parameter übergeben worden sein.
+```python
+import turtle
+pen_size = turtle.pensize() # Auslesen der Stiftbreite
+print(pen_size) # Out: 1
+
+turtle.pensize(10) # Setzen der Stiftbreite
+turtle.penup() # Stift heben -> keine Linie
+turtle.setposition((-100, -100)) # Ausgangsposition
+turtle.pendown() # Stift senken -> Linie
+for i in range(4):
+ turtle.forward(200)
+ turtle.left(90)
+```
+Alternativ zur `turtle.pensize()`-Methode kann auch die `turtle.width()`-Methode benutzt werden.
+
+## Flächen füllen
+Mit den Methoden `turtle.begin_fill()` und `turtle.end_fill()` ist es möglich, Flächen zu färben, die von der turtle eingeschlossen wurden. Im folgenden Codeausschnitt wird dies (wieder am Beispiel eines Quadrates) demonstriert. Die Methode `turtle.fillcolor()` kann analog zur Methode `turtle.pencolor()` benutzt werden um die entsprechende Farbe festzulegen. Die Methode `turtle.filling()` wird analog zur Methode `turtle.isdown()` benutzt um zu erkennen, ob gerade eine Fläche gefüllt wird.
+```python
+import turtle
+turtle.penup() # Stift heben -> keine Linie
+turtle.setposition((-100, -100)) # Ausgangsposition
+turtle.pendown() # Stift senken -> Linie
+print("filling? ", turtle.filling())
+
+turtle.fillcolor("blue") # Setzen der Farbe zum ausfüllen
+turtle.begin_fill() # Ausfüllen starten
+
+for i in range(4):
+ turtle.forward(200)
+ turtle.left(90)
+ print("filling? ", turtle.filling())
+
+turtle.end_fill() # Ausfüllen beenden
+```
+
+Die Methode `turtle.color()` kann benutzt werden um sowohl die *pencolor* als auch die *fillcolor* festzulegen.
+```python
+import turtle
+turtle.color("red", "blue")
+print(turtle.pencolor()) # Out: red
+print(turtle.fillcolor()) # Out: blue
+```
+
+## Ändern der Geschwindigkeit
+Die Geschwindigkeit der turtle kann mit der `turtle.speed()`-Methode gelesen und geändert werden. Im folgenden Codeausschnitt wird das bereits bekannte Quadrat gezeichnet, jedoch wird beim Zeichnen die Geschwindigkeit von Kante zu Kante variiert.
+```python
+import turtle
+turtle.penup() # Stift heben -> keine Linie
+turtle.setposition((-100, -100)) # Ausgangsposition
+turtle.pendown() # Stift senken -> Linie
+speed = turtle.speed() # Auslesen der Geschwindigkeit
+print(speed) # Out: 3
+
+for i in range(4):
+ turtle.forward(200)
+ turtle.left(90)
+ turtle.speed(speed + 3) # Setzen des speed-Wertes
+```
+Die Geschwindigkeit kann auf zwei Arten angegeben werden: als `int` zwischen `0` und `10` oder als *speed string*. Wird ein Wert `<0.5` oder `>10` übergeben, wird der `speed`-Wert auf `0` gesetzt. Folgende *speed strings* sind möglich:
+* `“fastest”: 0`
+* `“fast”: 10`
+* `“normal”: 6`
+* `“slow”: 3`
+* `“slowest”: 1`
+
+## Weitere Funktionen
+Das `turtle`-Modul umfasst noch viele weitere Funktionen, sie alle hier aufzulisten wäre müßig und redundant. Du solltest nun die wichtigsten Methoden kennengelernt haben. Gerüstet mit diesen Methoden kannst du jetzt mit dem Modul experimentieren. In diesem Abschnitt folgen noch ein paar weitere Methoden, falls du noch mehr kennenlernen möchtest. Da wir hier nicht alle Methoden vorstellen solltest du trotzdem dir die Dokumentation zum `turtle`-Modul (du findest sie unter: https://docs.python.org/3/library/turtle.html) ansehen, um heraus zu finden, was noch alles möglich ist.
+
+### Sichtbarkeit der turtle
+Mit der Methode `turtle.hideturtle()` lässt sich die turtle verstecken, in der Dokumentation wird erwähnt, das dies die Performanz verbessern kann. Um die turtle wieder sichtbar zu machen, kann die Methode `turtle.showturtle()` verwendet werden. Alternativ können auch die Aliase der Methoden `turtle.ht()` bzw. `turtle.st()` benutzt werden.
+
+### Bildschirmgröße
+Das `turtle`-Modul bietet auch Methoden an auf den Fenster zuzugreifen, in dem sich die turtle bewegt. Beispielsweise kann mit der `turtle.screensize()` die Bildschirmgröße abgerufen und geändert werden.
+```python
+import turtle
+width, height = turtle.screensize()
+print(width, height) # Out: 400 300
+turtle.screensize((800, 600))
+```
+Die genaue Größe des Fensters in Pixeln zu kennen, kann hilfreich sein, um zu verhindern, dass die turtle den sichtbaren Bereich verlässt.
+
+### turtle.Turtle
\ No newline at end of file
diff --git a/wiki b/wiki
deleted file mode 120000
index a8256a7..0000000
--- a/wiki
+++ /dev/null
@@ -1 +0,0 @@
-../pythonfooLite.wiki
\ No newline at end of file