From ef65a6e0e06e55dd34a08f897c9f3d04a99591ce Mon Sep 17 00:00:00 2001 From: fedx21dragon Date: Wed, 2 Sep 2026 14:22:32 +0200 Subject: [PATCH 1/4] Lektion Hello wor Signed-off-by: fedx21dragon --- Code/HelloWorld.java | 5 ++ Code/helloworld.cpp | 6 ++ Code/test_installation.py | 20 +++++++ Lektionen/helloworld.typ | 116 ++++++++++++++++++++++++++++++++++++++ lib/helpers.typ | 30 +++++++++- 5 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 Code/HelloWorld.java create mode 100644 Code/helloworld.cpp create mode 100644 Code/test_installation.py create mode 100644 Lektionen/helloworld.typ diff --git a/Code/HelloWorld.java b/Code/HelloWorld.java new file mode 100644 index 0000000..9bc1603 --- /dev/null +++ b/Code/HelloWorld.java @@ -0,0 +1,5 @@ +public class HelloWorld { + public static void main(String[] args) { + System.out.println("Hello World!"); + } +} diff --git a/Code/helloworld.cpp b/Code/helloworld.cpp new file mode 100644 index 0000000..7dd560a --- /dev/null +++ b/Code/helloworld.cpp @@ -0,0 +1,6 @@ +#include + +int main() { + std::cout<<"Hello world!"< Date: Thu, 3 Sep 2026 15:35:44 +0200 Subject: [PATCH 2/4] Lektion Variablen und Arithmetik (Python) Signed-off-by: fedx21dragon --- .gitignore | 8 ++ Code/eingabe_zahlen.py | 17 +++ Code/rechnen.py | 18 +++ Code/rechner_eingabe.py | 13 ++ Code/variablen.py | 5 + Code/variablen_aendern.py | 23 ++++ Lektionen/variablen_aritmetik.typ | 206 ++++++++++++++++++++++++++++++ lib/helpers.typ | 10 +- main.typ | 19 +-- 9 files changed, 299 insertions(+), 20 deletions(-) create mode 100644 .gitignore create mode 100644 Code/eingabe_zahlen.py create mode 100644 Code/rechnen.py create mode 100644 Code/rechner_eingabe.py create mode 100644 Code/variablen.py create mode 100644 Code/variablen_aendern.py create mode 100644 Lektionen/variablen_aritmetik.typ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9e05a5d --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +graphify-out/ +graphity-out +.json +main.pdf +CLAUDE.md +.idea/ +__pycache__/ +*.pyc diff --git a/Code/eingabe_zahlen.py b/Code/eingabe_zahlen.py new file mode 100644 index 0000000..269dfce --- /dev/null +++ b/Code/eingabe_zahlen.py @@ -0,0 +1,17 @@ +# input() hält das Programm an und wartet auf eine Eingabe der Nutzerin. +# WICHTIG: input() liefert das Eingegebene IMMER als Text (str) zurück - +# auch dann, wenn die Nutzerin eine Zahl eingetippt hat. + +erste_eingabe = input("Gib eine Zahl ein: ") +zweite_eingabe = input("Gib noch eine Zahl ein: ") + +# "+" verbindet zwei Texte einfach hintereinander (Konkatenation). +# Bei den Eingaben "12" und "3" käme hier "123" heraus - nicht 15! +print("Als Text aneinandergehängt:", erste_eingabe + zweite_eingabe) + +# Damit wir rechnen können, müssen wir den Text erst in eine ganze Zahl +# umwandeln. Das erledigt die Funktion int(). +erste_zahl = int(erste_eingabe) +zweite_zahl = int(zweite_eingabe) + +print("Als Zahlen addiert:", erste_zahl + zweite_zahl) diff --git a/Code/rechnen.py b/Code/rechnen.py new file mode 100644 index 0000000..c6e011d --- /dev/null +++ b/Code/rechnen.py @@ -0,0 +1,18 @@ +# Rechnen mit ganzen Zahlen. Python nutzt die Rechenausdrücke, die wir aus +# der Schule kennen, plus die bereits bekannte Zuweisung mit "=". + +a = 18 +b = 5 + +print("Summe: ", a + b) # 23 +print("Differenz: ", a - b) # 13 +print("Produkt: ", a * b) # 90 +print("Quotient: ", a / b) # 3.6 <- / liefert IMMER eine Kommazahl (float) +print("Ganzzahl-Div: ", a // b) # 3 <- // schneidet den Rest ab +print("Rest (modulo):", a % b) # 3 <- was bei 18 : 5 übrig bleibt +print("Potenz: ", a ** b) # 1889568 <- a hoch b + +# Rechenreihenfolge ("Punkt vor Strich") gilt wie in der Mathematik. +# Mit Klammern kann man sie steuern: +print(2 + 3 * 4) # 14 +print((2 + 3) * 4) # 20 diff --git a/Code/rechner_eingabe.py b/Code/rechner_eingabe.py new file mode 100644 index 0000000..5bfdf6d --- /dev/null +++ b/Code/rechner_eingabe.py @@ -0,0 +1,13 @@ +# Ein kleines Rechenprogramm: Es nimmt zwei ganze Zahlen entgegen und gibt +# Summe, Differenz, Produkt und Quotient aus. + +erste_zahl = int(input("Gib eine ganze Zahl ein: ")) +zweite_zahl = int(input("Gib noch eine ganze Zahl ein: ")) + +print("Summe: ", erste_zahl + zweite_zahl) +print("Differenz: ", erste_zahl - zweite_zahl) +print("Produkt: ", erste_zahl * zweite_zahl) +print("Quotient: ", erste_zahl / zweite_zahl) + +# f-strings sind bequem, um Text und Werte zu mischen: +print(f"{erste_zahl} geteilt durch {zweite_zahl} ist {erste_zahl / zweite_zahl}") diff --git a/Code/variablen.py b/Code/variablen.py new file mode 100644 index 0000000..2fd9e51 --- /dev/null +++ b/Code/variablen.py @@ -0,0 +1,5 @@ +beschreibung = "wundervoll" + +print(f"Hallo, mein Tag war {beschreibung}!") +print(f"ich habe {beschreibung} aus einem skript gelernt.") +print(f"Ich hoffe dir geht es genauso {beschreibung}") diff --git a/Code/variablen_aendern.py b/Code/variablen_aendern.py new file mode 100644 index 0000000..3ae0c77 --- /dev/null +++ b/Code/variablen_aendern.py @@ -0,0 +1,23 @@ +# Ein Programm ist eine Folge von Anweisungen, die von oben nach unten +# abgearbeitet werden - keine Sammlung mathematischer Aussagen. + +zaehler = 0 # Lasse zaehler zuerst den Wert 0 haben. +zaehler = zaehler + 1 # Nimm den aktuellen Wert (0), addiere 1, speichere zurueck. +zaehler = zaehler + 1 # Und noch einmal: aus 1 wird 2. + +print("zaehler ist jetzt:", zaehler) + +# Mathematisch ergibt "zaehler = zaehler + 1" keinen Sinn. +# Als Anweisung gelesen heisst es: "Der Name links soll ab jetzt den +# Wert der rechten Seite tragen." + +# Eine Variable kann im Laufe des Programms ihren Wert - und sogar ihre +# Art von Wert - wechseln: +inhalt = "ein Text" +print(inhalt, "->", type(inhalt)) + +inhalt = 42 +print(inhalt, "->", type(inhalt)) + +inhalt = 3.5 +print(inhalt, "->", type(inhalt)) diff --git a/Lektionen/variablen_aritmetik.typ b/Lektionen/variablen_aritmetik.typ new file mode 100644 index 0000000..1019c4c --- /dev/null +++ b/Lektionen/variablen_aritmetik.typ @@ -0,0 +1,206 @@ +#import "../lib/helpers.typ": * + +== Variablen und Arithmetik + +Bisher haben unsere Programme immer exakt das Gleiche getan. Wir haben Text ausgegeben, und dieser Text stand fest im Quellcode. In dieser Lektion geben wir unseren Programmen ein Gedächtnis: Wir lernen, Werte unter einem Namen zu speichern, sie später wieder abzurufen und mit ihnen zu rechnen. Damit ist der Schritt von einer starren Ausgabe zu einem Programm getan, das auf Eingaben reagiert und etwas ausrechnet. + +#Theorie[ + === Was ist eine Variable? + + Stell dir ein beschriftetes Schließfach vor. Auf dem Schild steht ein Name, im Fach liegt ein Inhalt. Wenn du den Namen nennst, meinst du eigentlich den Inhalt. Genau das ist eine *Variable*: ein Name, unter dem ein Wert abgelegt ist. + + Die Ablage geschieht durch ein Gleichheitszeichen. Der Name steht links, der Wert rechts: + + ```python + beschreibung = "wundervoll" + ``` + + Ab dieser Zeile ist es im Programm so, als stünde überall dort, wo `beschreibung` geschrieben wird, das Wort `"wundervoll"`. Das ist praktisch, wenn derselbe Wert an mehreren Stellen gebraucht wird – ändern wir ihn an einer Stelle, ändert er sich überall. + + Das folgende Programm erzählt von seinem Tag. Führe es aus und schau dir die Ausgabe an. +] + +#Code("variablen.py") + +#Theorie[ + === Das Gleichheitszeichen ist keine Gleichung + + In der Mathematik bedeutet `=` „beide Seiten sind gleich“. In Python bedeutet `=` etwas anderes: *„Der Name auf der linken Seite soll ab jetzt den Wert der rechten Seite tragen.“* Es ist eine *Zuweisung*, kein Vergleich. + + Der Unterschied wird bei einer Zeile wie dieser deutlich: + + ```python + zaehler = zaehler + 1 + ``` + + Als Gleichung gelesen ist das Unsinn. Als Anweisung gelesen ist es klar: Nimm den aktuellen Wert von `zaehler`, addiere 1 dazu, und speichere das Ergebnis wieder unter dem Namen `zaehler`. + + Das liegt daran, dass ein Programm eine *Folge von Anweisungen* ist, die von oben nach unten abgearbeitet wird – keine Sammlung von Aussagen, die alle gleichzeitig gelten. Der Wert einer Variable kann sich im Laufe des Programms also ändern. + + === Datentypen + + Jeder Wert hat einen *Datentyp* – eine Art von Wert. `"wundervoll"` ist ein Text (in Python `str`, von _string_, „Zeichenkette“). `42` ist eine ganze Zahl (`int`, von _integer_). `3.5` ist eine Kommazahl (`float`). Der Typ ist wichtig, weil Python mit verschiedenen Typen unterschiedlich umgeht: Zwei Zahlen kann man multiplizieren, zwei Texte nicht sinnvoll. + + Anders als in vielen anderen Sprachen musst du den Typ in Python *nicht* vorab hinschreiben. Python erkennt ihn automatisch am Wert. Mit der Funktion `type()` kannst du nachfragen, welchen Typ ein Wert gerade hat. +] + +#Code("variablen_aendern.py") + +#Praxis[ + + Weise `beschreibung` in `variablen.py` ein anderes Wort zu und führe das Programm erneut aus. Was ändert sich in der Ausgabe? + + + Definiere in `variablen.py` eine zweite Variable (zum Beispiel `wetter = "sonnig"`) und schreibe mit ihr einen weiteren `print()`-Satz. + + + Schreibe ein Programm, das eine Variable `alter` auf einen Wert setzt, sie dann in mehreren Schritten verändert (`alter = alter + 1`) und nach jedem Schritt ausgibt. +] + +=== Eingaben von der Nutzerin + +#Theorie[ + Ein Programm wird erst dann wirklich nützlich, wenn es mit einer Nutzerin interagiert. Ausgaben kennen wir schon: `print()`. Für Eingaben gibt es die Funktion `input()`. + + ```python + name = input("Wie heißt du? ") + ``` + + `input()` hält das Programm an, zeigt den Text in den Klammern an und wartet, bis die Nutzerin etwas eintippt und Enter drückt. Das Eingetippte wird dann unter dem Namen links vom `=` gespeichert. + + *Der wichtigste Stolperstein dieser Lektion:* `input()` liefert das Eingegebene *immer als Text* (`str`) zurück – auch dann, wenn die Nutzerin eine Zahl eingetippt hat. Der Text `"12"` und die Zahl `12` sind für Python zwei verschiedene Dinge. + + Warum ist das ein Problem? Das `+`-Zeichen bedeutet für zwei Texte „hänge sie aneinander“. Die Eingaben `"12"` und `"3"` ergeben mit `+` also `"123"`, nicht `15`. + + Um mit einer Eingabe zu rechnen, musst du sie erst umwandeln: + + - `int("12")` macht aus dem Text die ganze Zahl `12` + - `float("3.5")` macht aus dem Text die Kommazahl `3.5` +] + +#Code("eingabe_zahlen.py") + +#Praxis[ + + Schreibe ein Programm, das nach dem Namen fragt und anschließend `Hallo, !` ausgibt. + + + Erweitere es: Frage zusätzlich nach dem Geburtsjahr, wandle die Eingabe mit `int()` um und gib aus, wie alt die Person dieses Jahr wird. + + + Was passiert, wenn du bei der Umwandlung mit `int()` keinen Zahlentext, sondern `"hallo"` eingibst? Lies die Fehlermeldung. +] + +=== Rechnen: Arithmetik + +#Theorie[ + Mit Zahlen können wir rechnen. Python versteht die Rechenausdrücke, die du aus der Schule kennst: + + - `+` — Addition + - `-` — Subtraktion + - `*` — Multiplikation + - `/` — Division + - `//` — Ganzzahl-Division (schneidet den Rest ab) + - `%` — Rest der Division („modulo“) + - `**` — Potenz (`a ** b` ist „a hoch b“) + + „Punkt vor Strich“ gilt wie gewohnt, und mit Klammern kannst du die Reihenfolge steuern: `(2 + 3) * 4` ergibt `20`. + + *Zwei Besonderheiten, an denen viele ins Straucheln geraten:* + + 1. `/` liefert in Python *immer* eine Kommazahl. `10 / 2` ergibt nicht `5`, sondern `5.0` (Typ `float`). Wenn du ein ganzzahliges Ergebnis willst, nutze `//`: `10 // 3` ergibt `3`. + + 2. `%` gibt den Rest an. `18 % 5` ist `3`, weil $18 = 3 dot 5 + 3$. Das ist überraschend nützlich, etwa um zu prüfen, ob eine Zahl gerade ist (`zahl % 2 == 0`). + + Eine angenehme Eigenschaft: Ganze Zahlen (`int`) haben in Python *keine Obergrenze*. `2 ** 200` rechnet Python ohne zu murren exakt aus. In vielen anderen Sprachen würde eine so große Zahl „überlaufen“. +] + +#Code("rechnen.py") + +#Theorie[ + Genauso können wir mit Zahlen rechnen, die die Nutzerin eingibt – vorausgesetzt, wir wandeln die Eingabe vorher mit `int()` um. +] + +#Code("rechner_eingabe.py") + +#Praxis[ + + Schreibe ein Programm, das zwei ganze Zahlen entgegennimmt und Summe, Differenz, Produkt *und* Quotient ausgibt. + + + Was fällt auf, wenn du `19` und `7` eingibst? Schau dir den Quotienten genau an. + + + Erweitere das Programm um Ganzzahl-Division (`//`) und Rest (`%`). + + + Was passiert, wenn du als zweite Zahl eine `0` eingibst? Lies die Fehlermeldung – wie heißt der Fehler? +] + +#Spiel[ + + Wie groß ist die größte Zahl, die du in Python speichern kannst? Probier `2 ** 1000` aus. Vergleiche das mit dem, was du vielleicht über andere Programmiersprachen gehört hast. + + + Gib `0.1 + 0.2` aus. Kommt `0.3` heraus? Kommazahlen werden im Computer nur *näherungsweise* gespeichert – das ist normal und begegnet dir in jeder Programmiersprache. + + + Was passiert, wenn du dich im Namen einer Variable vertippst, etwa `print(beschreibnug)` statt `print(beschreibung)`? + + + Texte kann man „addieren“ und sogar „multiplizieren“: Probier `"ha" * 3` und `"Hallo " + "Welt"` aus. Was passiert bei `"Hallo" + 3`? + + + Statt `zaehler = zaehler + 1` gibt es die Kurzschreibweise `zaehler += 1`. Es gibt auch `-=`, `*=` und `/=`. Probier sie aus. +] + +=== Häufige Fehler und ihre Ursachen + +#Theorie[ + *`NameError: name 'x' is not defined`* + + Python kennt den Namen nicht. Meist ein Tippfehler im Variablennamen, oder die Variable wurde erst *nach* ihrer Verwendung zugewiesen. Groß- und Kleinschreibung zählt: `Alter` und `alter` sind zwei verschiedene Namen. + + *`TypeError: can only concatenate str (not "int") to str`* + + Du versuchst, einen Text und eine Zahl mit `+` zu verbinden. Häufig, weil eine `input()`-Eingabe noch Text ist. Lösung: die Zahl mit `int()` umwandeln, oder im `print()` ein Komma statt `+` verwenden, oder einen f-string nutzen: `print(f"Alter: {alter}")`. + + *`ZeroDivisionError: division by zero`* + + Du hast durch `0` geteilt. Durch null zu teilen ist mathematisch nicht definiert, deshalb bricht das Programm ab. In der nächsten Lektion lernst du, solche Fälle vorher abzufangen. + + *`ValueError: invalid literal for int() with base 10: 'hallo'`* + + Du hast `int()` einen Text gegeben, der keine Zahl ist. + + *Verwechslung von `=` und `==`* + + `=` weist zu, `==` vergleicht („sind diese beiden gleich?“). Diese Unterscheidung wird in der nächsten Lektion wichtig. +] + +#Quiz(answer: "a ist 8")[ + Was steht am Ende in `a`? + ```python + a = 5 + a = a + 3 + ``` + + a ist 8 + + a ist 5 + + Es gibt einen Fehler, weil `a = a + 3` keine gültige Gleichung ist + + a ist 53 +] + +#Quiz(answer: "5.0 (eine Kommazahl)")[ + Was gibt `print(10 / 2)` in Python aus? + + 5.0 (eine Kommazahl) + + 5 (eine ganze Zahl) + + 2.5 + + Einen Fehler +] + +#Quiz(answer: "Immer einen Text (str)")[ + Welchen Datentyp liefert `input()` zurück? + + Immer einen Text (str) + + Eine ganze Zahl, wenn eine Zahl eingegeben wurde + + Den Typ, der zum Eingegebenen passt + + Eine Kommazahl (float) +] + +#Quiz(answer: "b), c)")[ + Welche Aussagen über `%` (modulo) sind korrekt? + + `10 % 3` ergibt `3.33` + + `10 % 2 == 0` prüft, ob `10` gerade ist + + `18 % 5` ergibt `3` + + `%` funktioniert nur mit Kommazahlen +] + +#Theorie[ + === Ausblick + + Du kannst jetzt Werte speichern, Eingaben entgegennehmen und rechnen. Aufgefallen ist dir vielleicht, dass ein Programm bei einer Eingabe wie `0` als Divisor einfach abstürzt. In der nächsten Lektion, *Kontrollfluss*, lernst du, wie ein Programm abhängig von seinen Eingaben unterschiedliche Wege einschlägt – und solche Abstürze höflich abfängt. +] diff --git a/lib/helpers.typ b/lib/helpers.typ index 2931db3..388fe6b 100644 --- a/lib/helpers.typ +++ b/lib/helpers.typ @@ -89,13 +89,15 @@ stack( #let Quiz_answers = state("Quiz_answers", ()) +#let Quiz_counter = counter("quiz") -// Quiz is abit more complicated than the other environments +// Quiz is abit more complicated than the other environments #let Quiz(answer: "", body) = { - context { - let number = counter(heading).get().at(0) + Quiz_counter.step() + context { + let number = Quiz_counter.get().at(0) Quiz_answers.update(s => s + ((number, answer),)) - + [=== Quiz #number ] set enum(numbering: "a)") body diff --git a/main.typ b/main.typ index 3d7377f..bc20522 100644 --- a/main.typ +++ b/main.typ @@ -56,24 +56,11 @@ = Python -== Numpy - - - -#let codesnippet(path, name) = { - [#set align(center) - #text(gray, style: "italic")[ - #name]] - - rect(stroke: gray, width: 100%)[ - #raw(lang: "Python", read(path), block: true)] -} - +#include "Lektionen/helloworld.typ" -//#zebraw(raw(lang: "Python", code, block: true)) +#include "Lektionen/variablen_aritmetik.typ" - -#Code("helloworld.py") +== Numpy From 2c0e15925420ade43f119cbbab5df298413c2d9a Mon Sep 17 00:00:00 2001 From: fedx21dragon Date: Fri, 4 Sep 2026 14:32:29 +0200 Subject: [PATCH 3/4] =?UTF-8?q?lektion=20f=C3=BCr=20Kontrollfluss=20und?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: fedx21dragon --- Code/division_pruefen.py | 18 ++ Code/einrueckung_wichtig.py | 23 +++ Code/noten_kategorie.py | 23 +++ Code/teilbarkeit.py | 14 ++ Code/vergleiche_und_wahrheit.py | 21 +++ Code/zahlenraten.py | 22 +++ Lektionen/kontrollfluss.typ | 285 ++++++++++++++++++++++++++++++++ main.typ | 2 + 8 files changed, 408 insertions(+) create mode 100644 Code/division_pruefen.py create mode 100644 Code/einrueckung_wichtig.py create mode 100644 Code/noten_kategorie.py create mode 100644 Code/teilbarkeit.py create mode 100644 Code/vergleiche_und_wahrheit.py create mode 100644 Code/zahlenraten.py create mode 100644 Lektionen/kontrollfluss.typ diff --git a/Code/division_pruefen.py b/Code/division_pruefen.py new file mode 100644 index 0000000..278709b --- /dev/null +++ b/Code/division_pruefen.py @@ -0,0 +1,18 @@ +# Aus der letzten Lektion: Dieses Programm stuerzt ab, wenn die zweite +# Zahl 0 ist (ZeroDivisionError). Jetzt fangen wir diesen Fall hoeflich ab. + +erste_zahl = int(input("Gib eine ganze Zahl ein: ")) +zweite_zahl = int(input("Gib noch eine ganze Zahl ein: ")) + +# Die bedingte Anweisung: Python prueft, ob die Bedingung nach "if" wahr ist. +if zweite_zahl == 0: + # Dieser Block wird NUR ausgefuehrt, wenn die Bedingung wahr ist. + print("Fehler: Durch 0 darf nicht geteilt werden.") +else: + # Dieser Block wird ausgefuehrt, wenn die Bedingung falsch ist. + ergebnis = erste_zahl / zweite_zahl + print(f"{erste_zahl} geteilt durch {zweite_zahl} ist {ergebnis}") + +# Diese Zeile steht NICHT eingerueckt - sie gehoert zu keinem Block +# und wird deshalb immer ausgefuehrt, egal wie die Eingabe war. +print("Das Programm ist fertig.") diff --git a/Code/einrueckung_wichtig.py b/Code/einrueckung_wichtig.py new file mode 100644 index 0000000..ee8532c --- /dev/null +++ b/Code/einrueckung_wichtig.py @@ -0,0 +1,23 @@ +# In Python entscheidet die EINRUECKUNG, welche Zeilen zu einem Block +# gehoeren. Es gibt keine geschweiften Klammern wie in anderen Sprachen. + +alter = int(input("Wie alt bist du? ")) + +# --- Version A: beide print-Zeilen sind eingerueckt --------------------- +# Beide Zeilen gehoeren zum if-Block. Bei alter >= 18 werden BEIDE +# ausgegeben, sonst KEINE. +if alter >= 18: + print("Du bist volljaehrig.") + print("Du darfst waehlen.") + +# --- Zum Ausprobieren: ruecke die zweite Zeile aus -------------------- +# Wenn "Du darfst waehlen." NICHT eingerueckt ist, gehoert sie nicht mehr +# zum if-Block. Dann wird sie IMMER ausgegeben - auch fuer eine 12. +# +# if alter >= 18: +# print("Du bist volljaehrig.") +# print("Du darfst waehlen.") # <- steht jetzt ausserhalb des if + +# Merke: Die Einrueckung ist nicht Deko, sie ist Teil der Bedeutung. +# Ueblich sind 4 Leerzeichen pro Stufe. Alle Zeilen eines Blocks muessen +# gleich weit eingerueckt sein. diff --git a/Code/noten_kategorie.py b/Code/noten_kategorie.py new file mode 100644 index 0000000..b6032c8 --- /dev/null +++ b/Code/noten_kategorie.py @@ -0,0 +1,23 @@ +# Mehr als zwei Faelle: mit "elif" (kurz fuer "else if") haengen wir +# weitere Bedingungen an. Python prueft sie der Reihe nach von oben nach +# unten und nimmt den ERSTEN Zweig, dessen Bedingung wahr ist. + +punkte = int(input("Wie viele Punkte hast du erreicht (0-100)? ")) + +if punkte >= 90: + note = "sehr gut" +elif punkte >= 75: + note = "gut" +elif punkte >= 60: + note = "befriedigend" +elif punkte >= 50: + note = "ausreichend" +else: + # Wird nur erreicht, wenn KEINE der Bedingungen oben wahr war. + note = "nicht bestanden" + +print(f"Ergebnis: {note}") + +# Warum ist die Reihenfolge wichtig? Bei 95 Punkten ist auch +# "punkte >= 75" wahr - aber Python hat den ersten passenden Zweig +# (punkte >= 90) schon genommen und ueberspringt den Rest. diff --git a/Code/teilbarkeit.py b/Code/teilbarkeit.py new file mode 100644 index 0000000..e7e8ae5 --- /dev/null +++ b/Code/teilbarkeit.py @@ -0,0 +1,14 @@ +# Teilt die zweite Zahl die erste? Wir nutzen den Rest-Operator "%" +# aus der letzten Lektion: Ist der Rest 0, dann ist die Division glatt +# aufgegangen - die zweite Zahl ist ein Teiler der ersten. + +zahl = int(input("Zahl: ")) +teiler = int(input("Moeglicher Teiler: ")) + +if teiler == 0: + print("Durch 0 teilt es sich nicht.") +elif zahl % teiler == 0: + print(f"{teiler} teilt {zahl}.") +else: + rest = zahl % teiler + print(f"{teiler} teilt {zahl} nicht (Rest {rest}).") diff --git a/Code/vergleiche_und_wahrheit.py b/Code/vergleiche_und_wahrheit.py new file mode 100644 index 0000000..556ded5 --- /dev/null +++ b/Code/vergleiche_und_wahrheit.py @@ -0,0 +1,21 @@ +# Jede Bedingung ist im Kern eine Frage, die Python mit True (wahr) oder +# False (falsch) beantwortet. True und False sind ein eigener Datentyp: bool. + +alter = 20 + +print(alter == 20) # Gleich? -> True +print(alter != 20) # Ungleich? -> False +print(alter < 18) # Kleiner? -> False +print(alter >= 18) # Groesser-gleich? -> True + +# Mit and, or und not lassen sich Bedingungen verknuepfen: +temperatur = 24 +sonnig = True + +print(temperatur > 20 and sonnig) # beide muessen wahr sein -> True +print(temperatur > 30 or sonnig) # eine reicht -> True +print(not sonnig) # kehrt um -> False + +# Genau dieselben Ausdruecke stehen sonst hinter einem "if": +if temperatur > 20 and sonnig: + print("Zeit fuer eine Pause draussen.") diff --git a/Code/zahlenraten.py b/Code/zahlenraten.py new file mode 100644 index 0000000..411c38a --- /dev/null +++ b/Code/zahlenraten.py @@ -0,0 +1,22 @@ +# Ein kleines Ratespiel - noch mit nur einem Versuch. +# (In der naechsten Lektion, "Schleifen", geben wir mehrere Versuche.) + +GESUCHTE_ZAHL = 7 + +tipp = int(input("Ich denke an eine Zahl von 1 bis 10. Dein Tipp? ")) + +if tipp == GESUCHTE_ZAHL: + print("Volltreffer!") +elif tipp < GESUCHTE_ZAHL: + print("Zu klein.") +else: + print("Zu gross.") + +# Bonus: verschachtelte Bedingung. Der innere if steht weiter eingerueckt +# und wird nur geprueft, wenn der aeussere if schon wahr war. +if tipp != GESUCHTE_ZAHL: + abstand = GESUCHTE_ZAHL - tipp + if abstand < 0: + abstand = -abstand + if abstand == 1: + print("Aber ganz knapp daneben!") diff --git a/Lektionen/kontrollfluss.typ b/Lektionen/kontrollfluss.typ new file mode 100644 index 0000000..9ff13c2 --- /dev/null +++ b/Lektionen/kontrollfluss.typ @@ -0,0 +1,285 @@ +#import "../lib/helpers.typ": * + +== Lektion: Kontrollfluss + +Bisher lief jedes unserer Programme stur von oben nach unten durch , jede Zeile genau einmal, immer in derselben Reihenfolge. Am Ende der letzten Lektion ist uns dabei etwas Unangenehmes passiert: Gibt die Nutzerin als Divisor eine `0` ein, stürzt das Programm mit einem `ZeroDivisionError` ab. In dieser Lektion geben wir dem Programm die Fähigkeit, *abhängig von seinen Daten unterschiedliche Wege einzuschlagen* , und solche Abstürze höflich abzufangen. Diese Abhängigkeit des Programmablaufs von den Werten, mit denen es arbeitet, nennen wir *Kontrollfluss*. + +#Theorie[ + === Eine Weggabelung im Programm + + Stell dir vor, du kochst nach einem Rezept. Die meisten Schritte machst du einfach der Reihe nach. An einer Stelle steht aber: „Falls du keine frische Milch hast, nimm Hafermilch , sonst nimm die frische Milch.“ Ab hier hängt dein nächster Handgriff von einer Bedingung ab. Du prüfst etwas, und je nach Antwort tust du das eine *oder* das andere, aber nie beides. + + Genau dieses Muster gibt es in Python. Es heißt *bedingte Anweisung* oder kurz *if-Anweisung* (von englisch _if_, „falls“): + + ```python + if zweite_zahl == 0: + print("Fehler: Durch 0 darf nicht geteilt werden.") + else: + print(erste_zahl / zweite_zahl) + ``` + + Wörtlich gelesen: „*Falls* `zweite_zahl` gleich `0` ist, gib die Fehlermeldung aus. *Andernfalls* (`else`) gib das Ergebnis der Division aus.“ Python prüft die Bedingung hinter `if`. Trifft sie zu, wird der erste Block ausgeführt und der `else`-Block übersprungen. Trifft sie nicht zu, ist es umgekehrt. + + Drei Bestandteile sind syntaktisch verpflichtend: + + 1. Das Schlüsselwort `if`, gefolgt von einer *Bedingung* , einem Ausdruck, der entweder wahr oder falsch ist. + 2. Ein *Doppelpunkt* `:` am Zeilenende. Er kündigt an: „Jetzt kommt ein Block, der zu diesem `if` gehört.“ + 3. Der *eingerückte Block* darunter: die Anweisungen, die nur in diesem Fall ausgeführt werden. + + Der `else`-Zweig ist optional. Oft will man nur etwas tun, *wenn* eine Bedingung zutrifft, und sonst nichts , dann lässt man `else` einfach weg. +] + +#Code("division_pruefen.py") + +#Theorie[ + === Der Doppelgänger: `=` und `==` + + In der letzten Lektion war das einfache Gleichheitszeichen eine *Zuweisung*: `x = 5` bedeutet „lege den Wert `5` unter dem Namen `x` ab“. Zum *Vergleichen* braucht Python ein anderes Zeichen, nämlich das *doppelte* Gleichheitszeichen `==`. Der Ausdruck `x == 5` stellt eine Frage: „Ist der Wert von `x` gleich `5`?“ , und die Antwort ist wahr oder falsch. + + Diese Verwechslung ist ein klassischer Stolperstein. Merkhilfe: `=` *macht* gleich, `==` *fragt*, ob gleich. + + Neben `==` gibt es weitere *Vergleichsoperatoren*, die du aus dem Matheunterricht kennst: + + - `==` — gleich + - `!=` — ungleich + - `<` — kleiner als + - `>` — größer als + - `<=` — kleiner oder gleich + - `>=` — größer oder gleich + + Alle vergleichen zwei Werte und liefern als Ergebnis wahr oder falsch. Das funktioniert übrigens nicht nur mit Zahlen: `name == "Xenia"` prüft, ob in `name` genau diese Zeichenkette steht. + + === Warum die Leerzeichen zählen + + In vielen Programmiersprachen markiert man zusammengehörige Anweisungen mit geschweiften Klammern `{ ... }`. Die Einrückung ist dort nur Kosmetik für das menschliche Auge. Python geht einen anderen Weg: Hier *ist die Einrückung die Syntax*. Es gibt keine Klammern um Blöcke , stattdessen entscheidet allein die Position am Zeilenanfang, was zu einem Block gehört und was nicht. + + Das ist zunächst ungewohnt, aber die Idee dahinter ist angenehm: Code, der ordentlich eingerückt ist, *sieht* so aus, wie er *funktioniert*. Es gibt keine zwei Wahrheiten mehr , kein „sieht eingerückt aus, ist aber nicht drin“. + + *Analogie:* Denk an eine Gliederung mit Unterpunkten. Was unter einer Überschrift eingerückt steht, gehört zu ihr. Rückt ein Punkt wieder nach links aus, beginnt ein neuer, übergeordneter Abschnitt. + + Betrachte den Unterschied: + + ```python + if alter >= 18: + print("Du bist volljaehrig.") + print("Du darfst waehlen.") + print("Programmende.") + ``` + + Die ersten beiden `print`-Zeilen sind eingerückt , sie gehören zum `if` und werden nur bei `alter >= 18` ausgeführt. Die dritte Zeile steht wieder am linken Rand, *außerhalb* des `if`, und läuft deshalb immer. + + Verschiebt man nun die zweite Zeile an den Rand: + + ```python + if alter >= 18: + print("Du bist volljaehrig.") + print("Du darfst waehlen.") + ``` + + … dann gehört `"Du darfst waehlen."` nicht mehr zum `if`. Jetzt bekommt auch eine 12-Jährige die Wahlberechtigung bescheinigt. Das Programm ist weiterhin gültig , es tut nur etwas anderes. + + *Die Regeln in Kurzform:* + + - Pro Einrückungsstufe verwendet man üblicherweise *vier Leerzeichen*. + - Alle Zeilen eines Blocks müssen *gleich weit* eingerückt sein. + - *Mische niemals Leerzeichen und Tabulatoren.* Für das Auge sehen beide gleich aus, für Python sind es verschiedene Zeichen. Die meisten Editoren (auch VSCode) wandeln einen Tastendruck auf `Tab` automatisch in Leerzeichen um , lass diese Einstellung an. +] + +#Code("einrueckung_wichtig.py") + +#Praxis[ + + Öffne `division_pruefen.py` und führe es zweimal aus: einmal mit einer `0` als zweiter Zahl, einmal mit einer anderen Zahl. Verfolge, welcher Block jeweils läuft. + + + Ersetze in `division_pruefen.py` das `==` durch ein einfaches `=` (also `if zweite_zahl = 0:`). Führe das Programm aus und lies die Fehlermeldung. Mach die Änderung anschließend rückgängig. + + + Entferne in `einrueckung_wichtig.py` die vier Leerzeichen vor der ersten `print`-Zeile im `if`-Block. Was meldet Python? In welcher Zeile? + + + Schreibe ein Programm, das nach dem Alter fragt und `Zutritt erlaubt` ausgibt, wenn die Person mindestens 16 ist, sonst `Zutritt verweigert`. +] + +=== Mehr als zwei Fälle + +#Theorie[ + Nicht jede Entscheidung hat nur zwei Ausgänge. Eine Punktzahl in eine Note zu übersetzen heißt, zwischen mehreren Stufen zu unterscheiden. Dafür gibt es `elif` , eine Zusammenziehung von _else if_, „sonst falls“. + + ```python + if punkte >= 90: + note = "sehr gut" + elif punkte >= 75: + note = "gut" + elif punkte >= 60: + note = "befriedigend" + else: + note = "nicht bestanden" + ``` + + Python arbeitet die Bedingungen *von oben nach unten* ab und nimmt den *ersten* Zweig, dessen Bedingung wahr ist. Alle weiteren werden dann nicht mehr geprüft. Der `else`-Zweig am Ende fängt alles ab, was durch keine der Bedingungen erfasst wurde. + + Deshalb ist die *Reihenfolge* entscheidend. Bei `95` Punkten ist auch `punkte >= 75` wahr , aber Python hat den passenden Zweig `punkte >= 90` bereits genommen und überspringt den Rest. Würde man die Prüfungen in umgekehrter Reihenfolge notieren (die kleinste zuerst), bekäme *jede* bestandene Arbeit die Note „ausreichend“. + + Ein `if` darf beliebig viele `elif`-Zweige haben, aber *höchstens ein* `else`, und das steht immer am Schluss. +] + +#Code("noten_kategorie.py") + +#Praxis[ + + Führe `noten_kategorie.py` mit den Eingaben `95`, `60` und `30` aus und prüfe, ob die Note stimmt. + + + Erweitere das Programm um eine Stufe `ausreichend` für `punkte >= 50`. + + + Schreibe ein Programm, das eine Uhrzeit als ganze Stunde (`0`–`23`) einliest und `Guten Morgen`, `Guten Tag`, `Guten Abend` oder `Gute Nacht` ausgibt , je nach Tageszeit. + + + Was passiert in `noten_kategorie.py`, wenn du `120` eingibst? Und bei `-5`? Überlege, ob das Programm das abfangen sollte. +] + +=== Wahrheitswerte und verknüpfte Bedingungen + +#Theorie[ + Jede Bedingung, die wir hinter ein `if` schreiben, ist im Kern eine Frage, die Python mit einem von genau zwei Werten beantwortet: `True` (wahr) oder `False` (falsch). Diese beiden bilden einen eigenen Datentyp, den *Wahrheitswert* , in Python `bool`, benannt nach dem Mathematiker George Boole. + + Du kannst dir das direkt ansehen, indem du einen Vergleich einfach ausgibst: + + ```python + print(5 > 3) # True + print(2 == 10) # False + ``` + + Manchmal soll eine Anweisung nur laufen, wenn *mehrere* Dinge gleichzeitig zutreffen , oder wenn *mindestens eines* von mehreren zutrifft. Dafür gibt es drei Wörter: + + - `and` — wahr, wenn *beide* Seiten wahr sind + - `or` — wahr, wenn *mindestens eine* Seite wahr ist + - `not` — kehrt wahr und falsch um + + ```python + if temperatur > 20 and sonnig: + print("Zeit fuer eine Pause draussen.") + ``` + + Gelesen: „Falls es wärmer als 20 Grad ist *und* die Sonne scheint …“. Ist auch nur eine der beiden Bedingungen falsch, wird der Block übersprungen. +] + +#Code("vergleiche_und_wahrheit.py") + +#Theorie[ + Mit diesem Werkzeug können wir die Aufgabe aus der letzten Lektion sauber lösen: prüfen, ob eine Zahl eine andere teilt. Der Rest-Operator `%` verrät es uns , ist der Rest `0`, geht die Division glatt auf. +] + +#Code("teilbarkeit.py") + +#Praxis[ + + Schreibe ein Programm, das eine ganze Zahl einliest und ausgibt, ob sie gerade oder ungerade ist. (Tipp: `zahl % 2`.) + + + Schreibe ein Programm, das prüft, ob eine eingegebene Jahreszahl ein Schaltjahr ist. Regel: durch 4 teilbar, aber nicht durch 100, es sei denn, auch durch 400. (Diese Aufgabe braucht `and`, `or` und `not`.) + + + Frage nach einer Zahl und gib `im Bereich` aus, wenn sie zwischen `1` und `100` liegt (beide Grenzen eingeschlossen), sonst `ausserhalb`. +] + +#Spiel[ + Das Programm `zahlenraten.py` denkt sich eine feste Zahl aus und sagt dir nach deinem Tipp, ob er zu groß, zu klein oder richtig war. Führe es ein paar Mal aus. Verändere anschließend `GESUCHTE_ZAHL` und den erlaubten Bereich im `input`-Text. + + Weitere Dinge zum Ausprobieren: + + + Was passiert, wenn du in `division_pruefen.py` den Doppelpunkt hinter `if zweite_zahl == 0` weglässt? Lies die Fehlermeldung genau. + + + Baue in `zahlenraten.py` mit `and` eine zusätzliche Reaktion ein: Wenn der Tipp *kleiner als 1 oder größer als 10* ist, soll das Programm „Das war gar keine gültige Zahl!“ sagen. + + + Schreibe ein Programm, das nach deinem Namen fragt. Tippt die Nutzerin den Namen deiner Tutorin ein, soll das Programm sich begeistert über die Namensgleichheit zeigen, sonst einfach freundlich grüßen. + + + In Python gilt eine `0` in einer Bedingung als falsch und jede andere Zahl als wahr. Probier `if 3:` und `if 0:` aus. Merkwürdig? Für den Anfang: bleib bei echten Vergleichen, dann bist du auf der sicheren Seite. +] + +#Code("zahlenraten.py") + +#Quiz(answer: "b)")[ + Was ist der Unterschied zwischen `=` und `==`? + + Es gibt keinen, beide vergleichen zwei Werte. + + `=` weist einen Wert zu, `==` prüft auf Gleichheit. + + `=` prüft auf Gleichheit, `==` weist einen Wert zu. + + `==` funktioniert nur mit Zahlen, `=` auch mit Text. +] + +#Quiz(answer: "c)")[ + ```python + temperatur = 15 + if temperatur >= 20: + print("warm") + print("fertig") + ``` + Was gibt dieses Programm aus? + + `warm` und `fertig` + + nur `warm` + + nur `fertig` + + einen `IndentationError` +] + +#Quiz(answer: "b)")[ + ```python + punkte = 82 + if punkte >= 50: + note = "ausreichend" + elif punkte >= 75: + note = "gut" + elif punkte >= 90: + note = "sehr gut" + print(note) + ``` + Welche Note wird ausgegeben? + + `gut` + + `ausreichend` + + `sehr gut` + + einen Fehler, weil mehrere Bedingungen zutreffen +] + +#Quiz(answer: "d)")[ + Wodurch erkennt Python, welche Zeilen zu einem `if`-Block gehören? + + An geschweiften Klammern `{ }` um den Block. + + An einem `end`-Schlüsselwort am Blockende. + + An einem Strichpunkt `;` hinter jeder Zeile des Blocks. + + An der Einrückung der Zeilen. +] + +#Quiz(answer: "b), c)")[ + Welche Aussagen über `and`, `or` und `not` sind korrekt? + + `a and b` ist wahr, wenn mindestens eine Seite wahr ist. + + `a or b` ist wahr, wenn mindestens eine Seite wahr ist. + + `not True` ergibt `False`. + + `and` verbindet nur Zahlen, nicht Wahrheitswerte. +] + + +=== Häufige Fehler und ihre Ursachen + +#Theorie[ + *`IndentationError: expected an indented block after 'if' statement`* + + Nach einem `if:` (oder `elif:`, `else:`) fehlt der eingerückte Block. Jede bedingte Anweisung braucht mindestens eine Zeile darunter, und die muss eingerückt sein. + + *`IndentationError: unexpected indent`* + + Eine Zeile ist eingerückt, obwohl davor kein `:` einen Block eröffnet hat. Häufig ein versehentliches Leerzeichen am Zeilenanfang. + + *`TabError: inconsistent use of tabs and spaces in indentation`* + + Innerhalb desselben Blocks wurden Tabulatoren und Leerzeichen gemischt. Optisch nicht zu sehen. Lösung: im Editor „Tabs in Leerzeichen umwandeln“ aktivieren und die betroffenen Zeilen neu einrücken. + + *`SyntaxError: expected ':'`* + + Der Doppelpunkt am Ende der `if`-, `elif`- oder `else`-Zeile fehlt. + + *`SyntaxError: invalid syntax` bei `if x = 5:`* + + Hier steht eine Zuweisung, wo eine Bedingung hingehört. Gemeint war der Vergleich `if x == 5:`. + + *Das Programm läuft, entscheidet aber falsch* + + Kein Absturz, keine Fehlermeldung , trotzdem stimmt das Ergebnis nicht. Fast immer liegt es an der *Reihenfolge* der `elif`-Zweige oder an einer verrutschten Einrückung. Hilfreich: an den entscheidenden Stellen ein `print()` einbauen und den Wert der geprüften Variable ausgeben lassen. +] + + + +#Theorie[ + === Ausblick + + Mit bedingten Anweisungen kann dein Programm jetzt an einer Stelle *einen* von mehreren Wegen wählen. Was es noch nicht kann: eine Aufgabe *wiederholen*, bis etwas erledigt ist, etwa so lange nach einer Zahl fragen, bis die Eingabe gültig ist, oder alle Teiler einer Zahl durchprobieren. Genau das leisten *Schleifen*, das Thema der nächsten Lektion. Du wirst dabei feststellen, dass die Einrückung dort dieselbe Rolle spielt wie hier. +] + diff --git a/main.typ b/main.typ index bc20522..bb5de8d 100644 --- a/main.typ +++ b/main.typ @@ -60,6 +60,8 @@ #include "Lektionen/variablen_aritmetik.typ" +#include "Lektionen/kontrollfluss.typ" + == Numpy From ae42e6f30c608781d1b4b7573384603ed6d3a1ec Mon Sep 17 00:00:00 2001 From: fedx21dragon Date: Sat, 5 Sep 2026 18:04:26 +0200 Subject: [PATCH 4/4] code organisiert nach den lektionen Signed-off-by: fedx21dragon --- Code/{ => 01_vorbereitung}/test_installation.py | 0 Code/{ => 02_helloworld}/HelloWorld.java | 0 Code/{ => 02_helloworld}/helloworld.cpp | 0 Code/{ => 02_helloworld}/helloworld.py | 0 Code/{ => 07_variablen_arithmetik}/eingabe_zahlen.py | 0 Code/{ => 07_variablen_arithmetik}/rechnen.py | 0 .../{ => 07_variablen_arithmetik}/rechner_eingabe.py | 0 Code/{ => 07_variablen_arithmetik}/variablen.py | 0 .../variablen_aendern.py | 0 Code/{ => 08_kontrollfluss}/division_pruefen.py | 0 Code/{ => 08_kontrollfluss}/einrueckung_wichtig.py | 0 Code/{ => 08_kontrollfluss}/noten_kategorie.py | 0 .../vergleiche_und_wahrheit.py | 0 Code/{ => 08_kontrollfluss}/zahlenraten.py | 0 Code/{ => 09_schleifen}/teilbarkeit.py | 0 Lektionen/helloworld.typ | 4 ++-- Lektionen/kontrollfluss.typ | 12 ++++++------ Lektionen/variablen_aritmetik.typ | 10 +++++----- Lektionen/vorbereitung.typ | 6 +++--- Lektionen/while.typ | 2 ++ 20 files changed, 18 insertions(+), 16 deletions(-) rename Code/{ => 01_vorbereitung}/test_installation.py (100%) rename Code/{ => 02_helloworld}/HelloWorld.java (100%) rename Code/{ => 02_helloworld}/helloworld.cpp (100%) rename Code/{ => 02_helloworld}/helloworld.py (100%) rename Code/{ => 07_variablen_arithmetik}/eingabe_zahlen.py (100%) rename Code/{ => 07_variablen_arithmetik}/rechnen.py (100%) rename Code/{ => 07_variablen_arithmetik}/rechner_eingabe.py (100%) rename Code/{ => 07_variablen_arithmetik}/variablen.py (100%) rename Code/{ => 07_variablen_arithmetik}/variablen_aendern.py (100%) rename Code/{ => 08_kontrollfluss}/division_pruefen.py (100%) rename Code/{ => 08_kontrollfluss}/einrueckung_wichtig.py (100%) rename Code/{ => 08_kontrollfluss}/noten_kategorie.py (100%) rename Code/{ => 08_kontrollfluss}/vergleiche_und_wahrheit.py (100%) rename Code/{ => 08_kontrollfluss}/zahlenraten.py (100%) rename Code/{ => 09_schleifen}/teilbarkeit.py (100%) create mode 100644 Lektionen/while.typ diff --git a/Code/test_installation.py b/Code/01_vorbereitung/test_installation.py similarity index 100% rename from Code/test_installation.py rename to Code/01_vorbereitung/test_installation.py diff --git a/Code/HelloWorld.java b/Code/02_helloworld/HelloWorld.java similarity index 100% rename from Code/HelloWorld.java rename to Code/02_helloworld/HelloWorld.java diff --git a/Code/helloworld.cpp b/Code/02_helloworld/helloworld.cpp similarity index 100% rename from Code/helloworld.cpp rename to Code/02_helloworld/helloworld.cpp diff --git a/Code/helloworld.py b/Code/02_helloworld/helloworld.py similarity index 100% rename from Code/helloworld.py rename to Code/02_helloworld/helloworld.py diff --git a/Code/eingabe_zahlen.py b/Code/07_variablen_arithmetik/eingabe_zahlen.py similarity index 100% rename from Code/eingabe_zahlen.py rename to Code/07_variablen_arithmetik/eingabe_zahlen.py diff --git a/Code/rechnen.py b/Code/07_variablen_arithmetik/rechnen.py similarity index 100% rename from Code/rechnen.py rename to Code/07_variablen_arithmetik/rechnen.py diff --git a/Code/rechner_eingabe.py b/Code/07_variablen_arithmetik/rechner_eingabe.py similarity index 100% rename from Code/rechner_eingabe.py rename to Code/07_variablen_arithmetik/rechner_eingabe.py diff --git a/Code/variablen.py b/Code/07_variablen_arithmetik/variablen.py similarity index 100% rename from Code/variablen.py rename to Code/07_variablen_arithmetik/variablen.py diff --git a/Code/variablen_aendern.py b/Code/07_variablen_arithmetik/variablen_aendern.py similarity index 100% rename from Code/variablen_aendern.py rename to Code/07_variablen_arithmetik/variablen_aendern.py diff --git a/Code/division_pruefen.py b/Code/08_kontrollfluss/division_pruefen.py similarity index 100% rename from Code/division_pruefen.py rename to Code/08_kontrollfluss/division_pruefen.py diff --git a/Code/einrueckung_wichtig.py b/Code/08_kontrollfluss/einrueckung_wichtig.py similarity index 100% rename from Code/einrueckung_wichtig.py rename to Code/08_kontrollfluss/einrueckung_wichtig.py diff --git a/Code/noten_kategorie.py b/Code/08_kontrollfluss/noten_kategorie.py similarity index 100% rename from Code/noten_kategorie.py rename to Code/08_kontrollfluss/noten_kategorie.py diff --git a/Code/vergleiche_und_wahrheit.py b/Code/08_kontrollfluss/vergleiche_und_wahrheit.py similarity index 100% rename from Code/vergleiche_und_wahrheit.py rename to Code/08_kontrollfluss/vergleiche_und_wahrheit.py diff --git a/Code/zahlenraten.py b/Code/08_kontrollfluss/zahlenraten.py similarity index 100% rename from Code/zahlenraten.py rename to Code/08_kontrollfluss/zahlenraten.py diff --git a/Code/teilbarkeit.py b/Code/09_schleifen/teilbarkeit.py similarity index 100% rename from Code/teilbarkeit.py rename to Code/09_schleifen/teilbarkeit.py diff --git a/Lektionen/helloworld.typ b/Lektionen/helloworld.typ index 4862b14..bca9ec4 100644 --- a/Lektionen/helloworld.typ +++ b/Lektionen/helloworld.typ @@ -11,7 +11,7 @@ Es gibt Hunderte von Programmiersprachen. Python hat sich für Anfänger als ideal erwiesen, weil: - 1. *Lesbarkeit:* Python-Code sieht dem Englischen ähnlich. `print(“Hallo”)` ist selbsterklärend, anders als etwa #Code("helloworld.cpp") oder #Code("helloworld.java") . + 1. *Lesbarkeit:* Python-Code sieht dem Englischen ähnlich. `print(“Hallo”)` ist selbsterklärend, anders als etwa #Code(“02_helloworld/helloworld.cpp”) oder #Code(“02_helloworld/helloworld.java”) . 2. *Minimalistische Syntax:* Python erzwingt saubere Formatierung durch Einrückungen. Das führt zu besseren Gewohnheiten. @@ -53,7 +53,7 @@ Speichere und führe das Programm aus. Die Ausgabe sollte sein: `Hello World!` ] -#Code("helloworld.py") +#Code("02_helloworld/helloworld.py") === Anatomie des Befehls diff --git a/Lektionen/kontrollfluss.typ b/Lektionen/kontrollfluss.typ index 9ff13c2..e5c3f30 100644 --- a/Lektionen/kontrollfluss.typ +++ b/Lektionen/kontrollfluss.typ @@ -29,7 +29,7 @@ Bisher lief jedes unserer Programme stur von oben nach unten durch , jede Zeile Der `else`-Zweig ist optional. Oft will man nur etwas tun, *wenn* eine Bedingung zutrifft, und sonst nichts , dann lässt man `else` einfach weg. ] -#Code("division_pruefen.py") +#Code("08_kontrollfluss/division_pruefen.py") #Theorie[ === Der Doppelgänger: `=` und `==` @@ -85,7 +85,7 @@ Bisher lief jedes unserer Programme stur von oben nach unten durch , jede Zeile - *Mische niemals Leerzeichen und Tabulatoren.* Für das Auge sehen beide gleich aus, für Python sind es verschiedene Zeichen. Die meisten Editoren (auch VSCode) wandeln einen Tastendruck auf `Tab` automatisch in Leerzeichen um , lass diese Einstellung an. ] -#Code("einrueckung_wichtig.py") +#Code("08_kontrollfluss/einrueckung_wichtig.py") #Praxis[ + Öffne `division_pruefen.py` und führe es zweimal aus: einmal mit einer `0` als zweiter Zahl, einmal mit einer anderen Zahl. Verfolge, welcher Block jeweils läuft. @@ -120,7 +120,7 @@ Bisher lief jedes unserer Programme stur von oben nach unten durch , jede Zeile Ein `if` darf beliebig viele `elif`-Zweige haben, aber *höchstens ein* `else`, und das steht immer am Schluss. ] -#Code("noten_kategorie.py") +#Code("08_kontrollfluss/noten_kategorie.py") #Praxis[ + Führe `noten_kategorie.py` mit den Eingaben `95`, `60` und `30` aus und prüfe, ob die Note stimmt. @@ -158,13 +158,13 @@ Bisher lief jedes unserer Programme stur von oben nach unten durch , jede Zeile Gelesen: „Falls es wärmer als 20 Grad ist *und* die Sonne scheint …“. Ist auch nur eine der beiden Bedingungen falsch, wird der Block übersprungen. ] -#Code("vergleiche_und_wahrheit.py") +#Code("08_kontrollfluss/vergleiche_und_wahrheit.py") #Theorie[ Mit diesem Werkzeug können wir die Aufgabe aus der letzten Lektion sauber lösen: prüfen, ob eine Zahl eine andere teilt. Der Rest-Operator `%` verrät es uns , ist der Rest `0`, geht die Division glatt auf. ] -#Code("teilbarkeit.py") +#Code("09_schleifen/teilbarkeit.py") #Praxis[ + Schreibe ein Programm, das eine ganze Zahl einliest und ausgibt, ob sie gerade oder ungerade ist. (Tipp: `zahl % 2`.) @@ -188,7 +188,7 @@ Bisher lief jedes unserer Programme stur von oben nach unten durch , jede Zeile + In Python gilt eine `0` in einer Bedingung als falsch und jede andere Zahl als wahr. Probier `if 3:` und `if 0:` aus. Merkwürdig? Für den Anfang: bleib bei echten Vergleichen, dann bist du auf der sicheren Seite. ] -#Code("zahlenraten.py") +#Code("08_kontrollfluss/zahlenraten.py") #Quiz(answer: "b)")[ Was ist der Unterschied zwischen `=` und `==`? diff --git a/Lektionen/variablen_aritmetik.typ b/Lektionen/variablen_aritmetik.typ index 1019c4c..0e1c480 100644 --- a/Lektionen/variablen_aritmetik.typ +++ b/Lektionen/variablen_aritmetik.typ @@ -20,7 +20,7 @@ Bisher haben unsere Programme immer exakt das Gleiche getan. Wir haben Text ausg Das folgende Programm erzählt von seinem Tag. Führe es aus und schau dir die Ausgabe an. ] -#Code("variablen.py") +#Code("07_variablen_arithmetik/variablen.py") #Theorie[ === Das Gleichheitszeichen ist keine Gleichung @@ -44,7 +44,7 @@ Bisher haben unsere Programme immer exakt das Gleiche getan. Wir haben Text ausg Anders als in vielen anderen Sprachen musst du den Typ in Python *nicht* vorab hinschreiben. Python erkennt ihn automatisch am Wert. Mit der Funktion `type()` kannst du nachfragen, welchen Typ ein Wert gerade hat. ] -#Code("variablen_aendern.py") +#Code("07_variablen_arithmetik/variablen_aendern.py") #Praxis[ + Weise `beschreibung` in `variablen.py` ein anderes Wort zu und führe das Programm erneut aus. Was ändert sich in der Ausgabe? @@ -75,7 +75,7 @@ Bisher haben unsere Programme immer exakt das Gleiche getan. Wir haben Text ausg - `float("3.5")` macht aus dem Text die Kommazahl `3.5` ] -#Code("eingabe_zahlen.py") +#Code("07_variablen_arithmetik/eingabe_zahlen.py") #Praxis[ + Schreibe ein Programm, das nach dem Namen fragt und anschließend `Hallo, !` ausgibt. @@ -109,13 +109,13 @@ Bisher haben unsere Programme immer exakt das Gleiche getan. Wir haben Text ausg Eine angenehme Eigenschaft: Ganze Zahlen (`int`) haben in Python *keine Obergrenze*. `2 ** 200` rechnet Python ohne zu murren exakt aus. In vielen anderen Sprachen würde eine so große Zahl „überlaufen“. ] -#Code("rechnen.py") +#Code("07_variablen_arithmetik/rechnen.py") #Theorie[ Genauso können wir mit Zahlen rechnen, die die Nutzerin eingibt – vorausgesetzt, wir wandeln die Eingabe vorher mit `int()` um. ] -#Code("rechner_eingabe.py") +#Code("07_variablen_arithmetik/rechner_eingabe.py") #Praxis[ + Schreibe ein Programm, das zwei ganze Zahlen entgegennimmt und Summe, Differenz, Produkt *und* Quotient ausgibt. diff --git a/Lektionen/vorbereitung.typ b/Lektionen/vorbereitung.typ index eb80f30..0a17460 100644 --- a/Lektionen/vorbereitung.typ +++ b/Lektionen/vorbereitung.typ @@ -132,7 +132,7 @@ cd ~/Programmiervorkurs Kopiere diesen Code rein: -#Code("helloworld.py") +#Code("02_helloworld/helloworld.py") Speichern (Ctrl+S), dann im Terminal: @@ -196,7 +196,7 @@ Das öffnet VSCode im `Programmiervorkurs` Ordner. Erstelle eine neue Datei `helloworld.py` mit: -#Code("helloworld.py") +#Code("02_helloworld/helloworld.py") Speichern (Cmd+S), dann im Terminal: @@ -265,7 +265,7 @@ Erstelle eine neue Datei: Kopiere diesen Code rein: -#Code("helloworld.py") +#Code("02_helloworld/helloworld.py") Speichern (Ctrl+S), dann im Terminal: diff --git a/Lektionen/while.typ b/Lektionen/while.typ new file mode 100644 index 0000000..f19102b --- /dev/null +++ b/Lektionen/while.typ @@ -0,0 +1,2 @@ +#include "../lib/helpers.typ" +