Inhaltsverzeichnis

Python Vertiefung

1. Setup

Python

Ziel: Hello World in VS code.

Anweisung: Python & VSCode Setup

Git

Ziel:

Vorgehen:

KI-Chatbots als Tutor

Ziel: Chat-KIs fürs Lernen optimal einsetzen können.

Zitat von Unbekannt: „KIs machen die Gescheiten gescheiter und die Dummen dümmer.“.

Betrachte folgende Programmieraufgabe als Beispiel: „Schreibe eine Python-Funktion, die eine Liste der ersten n Primzahlen generiert und zurückgibt.“

Link: https://artificialcorner.com/p/master-the-perfect-chatgpt-prompt

Aufgabe:

2. Jupyter

Jupyter Notebooks sind eine gute Möglichkeit, um Dokumentation (Markdown) und Code zusammen abzulegen und auszuführen.

Ziel:

Auftrag 1: Einrichten

Auftrag 2: Markdown in Jupyter

Auftrag 3: Python in Jupyter

3. For-Schleife & Funktionen

ERINNERUNG: Von nun an müssen alle neu gelernten Python-Befehle unaufgefordert im Python-Portfolio dokumentiert werden!

Ziel: Da bis jetzt wahrscheinlich noch nicht alle 1M-TALITs im Grundlagenfach IF die for-Schleife und Funktionen kennengelernt haben, gibt es hier einen kurzen Crashkurs ;)

Erstelle ein Jupyter-Notebook for_loop_functions.ipynb und löse die Aufgaben darin. Dokumentiere neu gelerntes im Portfolio.

Auftrag 1: For-Schleife

Studiere hier die Theorie zu For-Schleifen (Aufgaben ignorieren). Löse nun die folgenden Aufgaben mit for-Schleifen. While ist streng verboten!

Aufgaben

  1. Gib alle ganzen Zahlen von $0$ bis und mit $10$ aus.
  2. Gib alle geraden Zahlen von $2$ bis und mit $42$ aus. Passe dafür den range() Befehl an.
  3. Starte mit der Liste li = ['Py','T','hON','is','GREAT','!']. Gib die Elemente der Reihe nach aus, der Output soll also sein:
    Py
    T
    hON
    is
    GREAT
    !
  4. Nimm nochmals die Liste aus der letzten Aufgabe. Erstelle einen leeren String s = ''. Gehe nun die Liste hindurch und füge jedes Element dem String auf der rechten Seite an, so dass der String am Schluss 'PyThONisGREAT!' ist.
  5. Erstelle eine leere Liste square_numbers = []. Befülle die nun mit ersten 13 Quadratzahlen, so dass sie am Schluss wie folgt aussieht: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169]
  6. Zusatzaufgabe I: Benutzer soll eine Zahl $1-9$ eingeben. Es wird dann die entsprechende Zahlenpyramide ausgegeben. Für die Eingabe $5$ sieht diese wie folgt aus:
        1
       121
      12321
     1234321
    123454321
  7. Zusatzaufgabe II: Erweiterung der letzten Zusatzaufgabe: Nun sollen auch Buchstaben eingegeben werden können, damit man noch grössere Pyramiden erstellen kann. Die alten Ägypter haben sich schliesslich auch nicht mit kleinen Pyramiden zufrieden gegeben! Die Reihenfolge der Symbole ist: symbols = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'

Auftrag 2: Funktionen

Studiere hier die Theorie zu Funktionen (Aufgaben ignorieren). Löse nun die folgenden Aufgaben mit Funktionen. Verwende wann immer for anstelle while.

Aufgaben

  1. Schreibe eine Funktion square(x), die das Quadrat einer Zahl berechnet und zurückgibt. Wichtig: In der Funktion darf nicht geprinted werde!
  2. Summiere zwei Zahlen: Schreibe eine Funktion summe(a, b), die zwei Zahlen entgegennimmt und ihre Summe zurückgibt. Wieder kein print in der Funktion.
  3. Schreibe eine Funktion is_even(n), die True zurückgibt, wenn n gerade ist, sonst False.
  4. Schreibe eine Funktion average(li), die eine Liste von Zahlen als Parameter erhält und den Durchschnitt zurückgibt. Der Durchschnitt soll selbst mit einer for-Schleife berechnet werden.

Sobald du fertig bist: Erstelle einen CodeWars-Account und beginne dort, Aufgaben zu lösen. Hier findest du Instruktionen: codewars

4. String Formatting

Ziel:

Frage 1: Wie funktioniert das?

name = 'Ada'
place = 'Birmingham'
print(f'Ich heisse {name} und wohne in {place}.')

Frage 2: Und hier?

print(f'Die Kreiszahl beträgt ungefähr {math.pi:.2f}.')

Frage 3: Und hier?

ortschaften = ['Egnach', 'Romanshorn', 'Weinfelden']
postleitzahlen = [9322, 8590, 8570]
 
for ort, plz in zip(ortschaften, postleitzahlen):
    print(f'{plz:<7}|{ort:>20}')

Aufgabe:

|  PLZ  |         Ort          | Bevölkerung  |  Fläche  |
|  9322 | Egnach               |         4897 |    18.43 |
|  8590 | Romanshorn           |        11556 |     8.73 |
|  8570 | Weinfelden           |        11893 |    15.48 |

Lösung

5. Dictionaries & JSON

Ziele:

Auftrag I

  1. Lade den Datensatz plz_schweiz.json im JSON-Format herunter plz_schweiz.json.zip und entzippe diesen.
  2. Lege das JSON-File in einem (noch zu erstellenden) Unterordner data in deinem Repo talit_python ab.
  3. Erstelle ein neues Jupyter-Notebook (im obersten Ordner des Repos, nicht in data) mit Namen dictionaries_json.ipynb: Beantworte hier die Fragen von weiter unten mithilfe von Dictinaries.
  4. Dokumentiere parallel die wichtigsten Befehle im Portfolio.

Fragen zu PLZ Schweiz:

Lies das JSON-File „plz_schweiz.json“ ein und speichere es in einem Dictionary, z.B. mit Namen data. Schreibe dann Code, um folgende Fragen zu beantworten:

  1. Welche Ortschaft hat die PLZ 6983?
  2. Finde die PLZ von Samedan.
  3. Wie viele Postleitzahlen gibt es für Zürich?
  4. Erstelle eine Liste mit allen PLZ (1000-9999), welche noch nicht vergeben sind.
  5. Du gründest deine eigene Ortschaft. Gib ihr einen Namen, wähle eine der freien PLZ und trage sie im Dictionary ein.
  6. Wie viele 6000er Postleitzahlen gibt es?
  7. In einer Volksabstimmung haben die Bewohnerinnen und Bewohner von Weinfelden beschlossen, dass die Stadt ab jetzt „Winefielden“ heissen soll. Passe das Dictionary entsprechend an.
  8. Die SalmsacherInnen haben beschlossen, sich Romanshorn anschliessen zu wollen. Entferne Salmsach aus dem Dictionary.
  9. Welche Ortschaft hat den längsten Namen? Welche PLZ hat diese Ortschaft?
  10. Wie viele Ortschaften fangen mit „W“ an?
  11. Speichere das Dictionary in einem neuen JSON plz_schweiz_modifiziert.json.

Auftrag II

  1. Lade das „Ortschaftenverzeichnis Kanton Thurgau 2023“ im JSON-Format herunter: https://opendata.swiss/de/dataset/ortschaftenverzeichnis-kanton-thurgau-2023
  2. … und lege wieder in Unterordner data in deinem Repo talit_python ab.
  3. Erstelle ein neues Jupyter-Notebook (im obersten Ordner des Repos, nicht in data) mit Namen dictionaries_json.ipynb: Beantworte hier die Fragen von weiter unten mithilfe von Dictinaries.

Fragen zum Datensatz Ortschaftenverzeichnis:

Lade den Datensatz in Python ein, speichere diesen in der Variablen data. Beantworte nun die folgenden Fragen:

  1. Finde deinen Wohnort und schaue die Daten dazu an.
  2. Gib mithilfe von f-Strings eine schöne Tabelle mit folgenden Spalten aus: | Name der Ortschaft | Einwohner |
  3. Finde die Gemeinde mit den meisten und mit den wenigsten Einwohnern.
  4. Summe aller Einwohner aller Gemeinden berechnen. Vergleiche das Resultat mit einem offiziellen Wert.
  5. Welche Gemeinde hat prozentual die meisten minderfährigen Einwohner?
  6. Erstelle für den Eintrag jeder Ortschaft einen neuen Eintrag mit key …
    1. einwohner_0_64: Anzahl Einwohner bis 64.
    2. i_live_here: Bei deinem Wohnort soll der zugehörige Value True, bei allen anderen False sein.
  7. Lösche alle Einträge mit key bezirk_nr.
  8. Erstelle einen neuen Datensatz (Liste mit Dictionaries), welcher nur die Einträge der Ortschaften übernimmt, die über $2000$ Einwohner haben. Schreibe diesen in ein neues JSON-File. Wichtig: Überschreibe nicht den ursprünglichen Datensatz.

Zusatzaufgabe: Finde auf https://opendata.swiss/de einen anderen Datensatz den dich interessiert und extrahiere auf ähnliche Art und Weise interessante Informationen.

6. Ausnahmebehandlung mit try-except

Betrachte folgenden Code:

zaehler = float(input("Gib den Nenner der Division ein."))
nenner = float(input("Gib den Zähler der Division ein."))
print("Quotient: ",zaehler/nenner)

Die Benutzerin wird nach einer Eingabe gefragt. Diese wird dann in einen Float (Zahl mit Nachkommastellen) umgewandelt, dann wird der Quotient der beiden bestimmt. Macht die Benutzerin zulässige Eingaben, so ist alles in Ordnung, macht sie dies aber nicht, crashed der Code und gibt eine Fehlermeldung aus. Folgende zwei Dinge können schief gehen:

  1. Eingabe(n) können nicht in Float umgewandelt werden, z.B. wenn ein String eingegeben wird → ValueError: could not convert string to float: 'i am a string'
  2. Falls nenner = 0, erhält man Division durch Null → ZeroDivisionError: float division by zero

Grundsätzlich sollte man seinen Code möglichst robust schreiben. Gibt die Benutzerin etwas falsches ein, soll der Code damit umgehen können und nicht einen Fehler ausgeben. Dafür kann man mit try-except eine Ausnahmebehandlung machen. Code, bei dem etwas schief gehen kann, wird in den try-Block geschrieben. Tritt ein Fehler auf, crashed der Code nicht, sondern springt in den except-Block:

try:
    # Code, der eine Ausnahme/einen Fehler auslösen könnte
except:
    # Code zur Behandlung der Ausnahme

Der obere Code fängt Fehler aller Art ab. Man kann aber die unterschiedlichen Arten von Fehlern einzeln abfangen:

try:
    # Code, der eine Ausnahme/einen Fehler auslösen könnte
except ValueError:
    # Code zur Behandlung der Ausnahme ValueError
except ZeroDivisionError:
    # Code zur Behandlung der Ausnahme ZeroDivisionError

Aufgabe 1: try-except

Löse diese Aufgabe in eine neues File try_except.ipynb.

Starte mit dem Code-Block:

zaehler = float(input("Gib den Nenner der Division ein."))
nenner = float(input("Gib den Zähler der Division ein."))
print("Quotient: ",zaehler/nenner)

Version 1

Version 2

Version 3

Aufgabe 2: Portfolio

Erstelle in deinem python_portfolio einen kurzen Eintrag zum Thema Ausnahmebehandlung mit try-except.

Aufgabe 3: Guess Number

Löse diese Aufgabe auch wieder im File try_except.ipynb.

7. Text Processing

Idee: Langen Text einlesen und verarbeiten

Programmierskills:

Auftrag:

Löse Auftrag in Dokument text_processing.ipynb.

  1. Wähle einen der folgenden langen Texte, lade diesen herunter und entzippe diesen. Schreibe deinen Code unten so, dass er ohne Anpassungen auch für die anderen Text funktioniert.
    1. Bible (en): king_james_en.txt.zip (1.4M)
  2. Dauerauftrag: Erweitere dein Python-Portfolio um alle wichtigen Python-Befehle, die du hier lernst.
  3. Lese die Textdatei ein.
  4. Ermittle die Anzahl Zeilen im Text.
  5. Zeichen im Text:
    1. Verschaffe dir einen Überblick über die Zeichen, die in dem Text vorkommen.
    2. Erstelle dazu einen String oder eine Liste, die alle Symbole des Texts genau einmal beinhalten.
  6. Modifiziere den Text so, dass er besser analysiert werden kann:
    1. Alle Kleinbuchstaben in Grossbuchstaben umwandeln
    2. Umlaute Ä,Ö,Ü zählen als eigene Buchstaben
    3. Bei allen anderen Buchstaben mit Akzenten werden diese ignoriert, z.B. wird ein „É“ als „E“ betrachtet.
    4. Tipp: replace(...)
    5. Achtung: In der Bibel kommen viele Symbole wie „é“ überhaupt nicht vor. Teste deshalb deinen Code unbedingt mit dem countries_de.csv-File.
    6. Die zu betrachtenden Buchstaben sind also: "ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ"
  7. Häufigkeitsanalyse:
    1. Zähle, wie oft jeder Buchstabe im Text vorkommt.
    2. Nutze dazu ein Dictionary: {<Buchstabe>:count}, z.B: {'A':4,'B':25, ...}.
    3. Bestimme dann für jeden Buchstaben in Prozent, wie oft er vorkommt. Stelle das ganze in einer schönen Tabelle dar (wie in früherer Lektion gelernt): Linke Spalte Buchstaben, rechte Spalte deren Wahrscheinlichkeit
    4. Ausblick: Im Grundlagenfach Informatik der 2M sprechen wir über „Verschlüsselung“. Dort lernen wir, dass Häufigkeitsanalysen verwendet werden können, um verschlüsselte Nachrichten zu entschlüsseln.
  8. Häufigkeit vorgegebenes Wort:
    1. Die Benutzerin soll ein Wort eingeben.
    2. Der Code ermittelt dann, wie oft das Wort vorkommt, und gibt die Anzahl aus.
  9. Häufigkeit alle Wörter:
    1. Erstelle ein Dictionary, welches alle Wörter des Textes beinhaltet und angibt, wie oft es vorkommt, z.B.: {... 'PIZZA':42, ...}
    2. Tipp: Zuerst müssen die einzelnen Zeilen in Listen mit den einzelnen Wörter aufgeteilt werden: split(...)
    3. Gib dann z.B. die 20 häufigsten Wörter geordnet in einer Schönen Tabelle („Wort“, „Häufigkeit“) aus.

Optional:

  1. Führe die Häufigkeitsanalyse der Buchstaben für zwei vergleichbare Texte in zwei Sprachen durch, z.B. Bibel auf Deutsch und Bibel auf Englisch. Vergleiche diese miteinander.

8. List Comprehensions

Idee: Listen in einer Zeile erstellen mit List Comprehensions

Programmierskills:

Auftrag: Löse jede der folgenden Aufgaben mit List Comprehensions und auf jeweils einer Zeile! Mache parallel Notizen in deinem Portfolio.

  1. Einfache List Comprehensions (ohne Condition):
    1. Liste mit den ersten $20$ ungeraden Zahlen.
    2. Liste mit den ersten $20$ Quadratzahlen: 1,4,9,…
    3. String in Liste mit chars umwandeln: „KSR2024“ → ['K','S','R','2','0','2','4']. Verwendung von Funktion list(...) ist verboten.
    4. Liste mit $10$ Zufallszahlen im Bereich $0$ bis $100$.
    5. Gib Liste mit Strings vor. Erstelle Liste, die Anzahl chars der einzelnen Strings angibt: [„Hallo“,„ksr“,„Romanshorn“,„7“] → [5,3,10,1]

  2. List Comprehensions mit Conditions:
    1. Gib eine Liste mit Zahlen vor. Erstelle eine Teilliste, welche nur die geraden Zahlen der ursprünglichen Liste beinhaltet.
    2. Gib eine Liste mit einzelnen Buchstaben vor. Erstelle Teilliste, welche nur Grossbuchstaben der ursprünglichen Liste beinhaltet. ['r','O','M','A','n','s','h','o','r','n',] → ['O','M','A']
    3. Gleich wie letzte Aufgabe, nur soll ein String vorgegeben und erstellt werden: "rOMAnshorn""OMA". Idee: Erstelle Liste mit Grossbuchstaben und setzt diese dann zu einem String zusammen. Tipp: mit ''.join(my_list) werden die Elemente in der Liste my_list zu einem String zusammengesetzt.

  3. Zusatzaufgaben (anspruchsvoll):
    1. Liste mit allen Primzahlen bis $100$. Verwende die Funktion all(...) (nutze KI als Tutor).

List Slicing & Ranges

Wir kennen bereits den einfachen Listenzugriff mit eckigen Klammern:

fruit = ['Apfel', 'Birne', 'Zwetschge']
print(fruit[1])  # Birne

Aber die Indexierung in Python kann noch viel mehr:

Negative Indices

Statt von 0..len(fruit)-1 können wir auch vom letzten Element her Indexieren:

fruit = ['Apfel', 'Birne', 'Zwetschge']
print(fruit[-1])  # Zwetschge

Negative Indices laufen von -1 (letztes Element) bis zu -len(fruit) (erstes Element).

Slicing

Statt einem einzelnen Element lässt sich auch eine Sub-Liste extrahieren:

print(fruit[1:3])  # ['Birne', 'Zwetschge']

Dabei ist die Zahl vor dem Doppelpunkt das erste Element und die Zahl hinter dem Doppelpunkt das exklusive Ende (also nicht mehr dabei). Die Zahlen werden also gleich behandelt wie die Argument der Funktion range().

Gleich wie bei range() können wir auch noch eine Schrittweite angeben, um z.B. jedes zweite Element einzuschliessen:

print(fruit[0:3:2])  # ['Apfel', 'Zwetschge']

Die Zahlen können auch weggelassen werden und bedeuten dann einfach ab Beginn bzw. bis zum Schluss (kopiert von Stackoverflow):

a[start:stop]  # Elemente von start bis stop-1
a[start:]      # Elemente von start bis zum Schluss
a[:stop]       # Elemente vom ersten bis stop-1
a[:]           # Eine Kopie der Liste

Auch hier lassen sich negative Indices verwenden:

a[-2:]   # Die beiden letzten Elemente
a[:-2]   # Alle ausser den beiden letzten Elementen

Auch negative Schrittweiten sind möglich:

a[::-1]    # Die ganze Liste rückwärts
a[1::-1]   # Die ersten beiden Elemente, rückwärts
a[:-3:-1]  # Die beiden letzten Elemente, rückwärts
a[-3::-1]  # Alle ausser den letzten beiden Elementen, rückwärts

Aufgaben

Zauber Spiel

  1. Schreibe einen Code, der dir die Zahlen für die Karten des Spiels „der magische Computer“ generiert und ausgibt. Die grösste mögliche Zahl (z.B. $31$,$63$,$127$ usw.) soll vorgeben werden können. Arbeite mit Dictionaries und/oder List-Comprehensions. Tipps: siehe unten.

  2. Erstelle nun selbst ein Spiel. Wähle dazu eine passende Zahl grösser $63$, also z.B. $127, 255, \ldots$ und generiere die zugehörigen Zahlen. Erstelle die zugehörigen Karten (z.B. Word) und drucke sie aus.

  3. Spiele dein Spiel mit jemandem.

Tipps: Um Dezimalzahlen in Binärzahlen und umgekehrt umzurechnen, kannst du deine eigenen Funktionen aus dem GF verwenden. Alternativ kannst du die integrierten Funktionen verwenden:

Lösungen

For-Schleife & Funktionen

Dictionaries & JSON Auftrag I

Ausnahmebehandlung mit try-except

Text Processing