Recap Python

🎯 Lernziele
Nach dieser Einheit sind Sie in der Lage dazu - einfache Programmierprobleme mittels Python zu lösen - hierzu Schleifen, Bedingungen und Datenstrukturen einzusetzen
Variablen
- Eine Variable ist ein Paar, bestehend aus einem Namen (kennzeichnet Platz im Speicher), dem ein Wert zugewiesen ist
- Der Wert kann durch weitere Zuweisungen verändert werden (ist variabel)
- Welcher Art der Wert (Inhalt) einer Variable ist, legt der Datentyp fest
- z.B. Ziffern, Zeichen, Buchstaben, Wörter, Listen,...
- dem entsprechend wir unterschiedlich viel Platz im Speicher reserviert

Beispiel
# der Variable foo wird der Wert 'zwanzig' als Zeichenkette / String zugeordnet
foo : str = 'zwanzig'
# der Variable ba wird der Wert 20 als Ganze Zahl / Integer zugeordnet
ba : int = 20
Primitive Datentypen

Integer
- ist eine ganze natürliche Zahl
- Beispiele: 9, 23, -162, 1095, 2012
- Maximale Größe eines Integers ist von der jeweiligen Rechner-Architektur abhängig
- Gewöhnlich ist der Wertebereich ca. +/- zwei Milliarden, da ein Integer als (vorzeichenbehafteter) 32-Bit-Wert gespeichert wird
# der Variable ba wird der Wert 20 als Ganze Zahl / Integer zugeordnet
ba = 20
# In Python müssen wir den Datentyp nicht explizit angebe
# Wir können ihn aber auch für Leser:innen angeben (Type hinting)
ba : int = 20
Double / Float
- Fließkommazahlen sind reelle Zahlen
- Also Zahlen mit Komma und Nachkommastellen
- Beispiele: 5.0, 29.3. 19674.2543, 0.999999999
- Achtung: Man muss das Komma als Punkt schreiben!
- Maximale Größe eines Double von der Rechner-Architektur abhängig
- als 64-Bit-Wert gespeichert, maximale Größe von ~ \(1.8 \cdot 10^{308}\) mit einer Genauigkeit von 14 Nachkommastellen
# der Variable ba wird der 3.14 als Gleitkommazahl / Float zugeordnet
ba = 3.14
ba : float = 3.14
String / Zeichenkette
- Es ist egal, um welche Zeichen es sich handelt (auch Zahlen)
- Werden durch
"oder'gekennzeichnet. Diese sind austauschbar, solange sie nicht gemischt werden"Hallo",'Hallo',"123","x@xxx"
- Ein String kann Buchstaben, Zahlen und Sonderzeichen enthalten
- Alle in einem String enthaltenen Zeichen werden als ein Wort angesprochen und behandelt
- Beispiele:
abcxyz,PHP_ist_super,20Euro,#*/[}%
- Beispiele:
# der Variable foo wird der Wert 'zwanzig' als Zeichenkette / String zugeordnet
foo : str = 'zwanzig'
- Strings verhalten Sich wie Listen
- Wir können Sie durchlaufen und manipulieren
- Wir können über den Index auf einzelne Zeichen zugreifen
- Das Konzept, dass sich verschiedene Datentypen gleich verhalten nennt sich Polymorphismus und wird uns in der objekt-orientierten Programmierung noch öfter begegnen
foo = 'zwanzig'
for letter in foo:
print(letter)
print(foo[::-1])
Boolean
- können entweder den Wert
TrueoderFalsehaben - Wird hauptsächlich bei Vergleichen und Schleifen angewendet
# den Variablen werden die Werte True und False zugeordnet
foo = True
ba = False
# Hiermit lässt sich die Boolesche Algebra anwenden
print(foo + ba) # Gibt 1 zurück
print(foo or ba) # Gibt True zurück
print(foo * ba) # 0
print(foo and ba) # False
Umwandlung zu anderen Typen (Casting)
-
Python kann einige Datentypen ineinander umwandeln
int("30") # Gibt 30 als Integer zurück float("3.14") # Gibt 3.14 als Float zurück str(20+3.14) # Gibt "23.14" als String zurück* Falsche/unerwartete Datentypen sind ein häufiger Grund für Fehlerfoo = '30' print(type(foo)) # Gibt <class 'str'> zurück. foo ist also ein String ba = int(foo) print(type(ba)) # Gibt <class 'int '> zurück. # in ba wurde foo als Integer umgewandelt gespeichert
Type Checking
- Type Hinting kann helfen, Fehler zu vermeiden
- Type Checking erzwingt, dass Variablen den richtigen Datentyp haben
# Reines Type Hinting
x : int = 10
y : int = 10
print(x + y) # Output: 20
# Type Checking
if isinstance(x, int) and isinstance(y, int):
print(x + y) # Output: 20
else:
print("x und y müssen Ganze Zahlen sein")
Datenstrukturen

- Liste (Lineare Datenstruktur): Jeder Knoten hat genau einen Verweis auf seinen Nachfolger
- Baum: Jeder Knoten kann mehrere Verweise auf Nachfolger haben, aber jeder Knoten wird nur von höchstens einem Vorgängerknoten referenziert.
- Graph: Knoten können auch von mehreren Vorgängerknoten referenziert werden.
Listen
- Eine Reihe von Elementen des gleichen oder unterschiedlichen Datentyps
- Vergleichbar einer Art Liste von Objekten
- Listen werden in Python mit eckigen Klammern definiert
- Auf jedes dieser Objekte kann man mittels eines Indexes zugreifen
# Listen können mit eckigen Klammern erstellt werden - auch leere Listen
empty_list = [ ]
filled_list = ['a','b','c',1]
# Der Zugriff auf den Index 0 gibt das erste Element in der Liste ('a') zurück
filled_list[0]
# > 'a'
Listen Gleichen Datentypes
- stellen sicher, dass die gleichen Aktionen durchgeführt werden können
- ermöglicht es Warteschlangen zu bilden
- z.B. um die die Trainingsdauern für viele Trainings zu speichern
dauern_in_min = [10,15,30,45,60] print(dauern_in_min[1]) #> 15 dauern_in_min_new = dauern_in_min[:].append(20) print(dauern_in_min_new[:]) #> [10,15,30,45,60,20] - Diese Liste hat 5 Elemente. Ihr Index läuft von 0 bis 4.
Arrays
- Speicherung in einen zusammenhängenden Speicherblock
- Homogen: alle Einträge haben denselben Datentyp
- Statisch: Länge kann nicht verändert werden
- Um Arrays zu verwenden, müssen wir das Modul
numpyimportieren

✍ Aufgabe

- Wir möchten die durchschnittliche Leistung eines Ergometers über ein Training berechnen
- Wir müssen dazu die Leistung \(P\) (in Watt) für jeden Zeitpunkt ermitteln
- Die Leistung wird über die folgenden Formel berechnet: \(P = M\omega\)
- \(M\) ist das Moment in Newtonmeter (Nm), gemessen über einen Drehmomentsensor
- \(\omega\) ist die Winkelgeschwindigkeit in Rad/s, gemessen über einen Drehzahlsensor
- Die Samplerate beträgt 100 Hz
- Die Fahrt dauert ca. 27 h
- Wir möchten ermitteln, wie viel Energie \(W\) in kJ ein Fahrradfahrer während einer Trainingseinheit verbraucht
- Schreiben Sie ein Skript, das alle Zahlen zweier gleich langer Listen elementweise multipliziert und dann die Ergebnisse auf-addiert (entsprechend einer Matrixmultiplikation)
Sie können das folgende Skript als Vorlage verwenden
import time
start_time = time.perf_counter()
index = 0
result = 0
"""
ADD YOUR CODE HERE
"""
print("List Approach")
print("--- %s seconds ---" % (time.perf_counter() - start_time))
print(result)
✔️ Lösung
# Paket für numerische Aufgaben im Python
import numpy as np
start_time = time.perf_counter()
# Umwandlung der Listen in numpy arrays
# vgl. Konstruktor
array1 = np.array(list1_momentum_in_Nm, dtype=np.int64)
array2 = np.array(list2_omega_in_rad_per_s, dtype=np.int64)
# Aufruf der Funktion für Matrixmultiplikation des Pakets numpy
result = np.matmul(array1, array2)/len(array1)
print("Numpy")
print("--- %s seconds ---" % (time.perf_counter() - start_time))
print(result)
List Approach
--- 5.2479909490000125 seconds ---
Numpy
--- 0.018864246000248386 seconds ---
Kopieren von Primitiven Datentypen
- wir sind es gewohnt, dass der Zuweisungsoperator
=den Inhalt einer Variable kopiert:
var_a = 1
var_b = var_a
var_b = var_b + 1
print(var_b) #> 2
print(var_a) #> 1
Kopieren von Listen
- bei Listen passiert etwas merkwürdiges. Nach der Zuweisung zeigen beide Variablennamen auf das gleiche Objekt im Speicher
- entsprechend werden beide Listen in Zukunft verändert, wenn wir eine von beiden verändern
list_a = [1,2,3]
list_b = list_a
list_b.append(4)
print(list_b) #> [1,2,3,4]
print(list_a) #> [1,2,3,4]

- ein neues Objekt wird nur angelegt, wenn wir dies explizit mit dem
copy()Befehl angeben - selbes gilt für verwandte Datentypen (dictionaries, pandas dataframes etc.)
list_a = [1,2,3]
list_b = list_a.copy()
list_b.append(4)
print(list_b) #> [1,2,3,4]
print(list_a) #> [1,2,3]
Dictionaries

- Angenommen wir möchten zusammengesetzte Daten speichern (z.B. ein Trainingstagebuch)
- Mit Listen ist dies nur eingeschränkt sinnvoll möglich
dates = ["16.8.2022","18.8.2022", "19.8.2022" <...>]activity = ["Dauerlauf","Radfahren", "Dauerlauf" <...>]- über den
index, lassen sich die Daten und Aktivitäten zuordnen - Was sind Nachteile?
- Mehrere Aktivitäten an einem Tag?
- Löschen von einzelnen Aktivitäten?

- Alternativ können wir mit einer hierarchischen Datenstruktur basierend auf Hash-Maps arbeiten
-
Dictionaries speichern key-value-Paare
dict = {<key> : <value>}* Anstelle des Index können wir den key nutzendict = {"16.8.2022" : "Dauerlauf", "18.8.2022" : "Radfahren", "19.8.2022" : "Dauerlauf", [...] }print(dict["18.8.2022"]) >>> "Radfahren"
Hierarchische Dictionaries (Bäume)
- Dictionaries können ineinander geschachtelt werden
training_log = {"0": { "date" : "16.8.2022", "time" : "8:00", "activity" : "Radfahren", "distance_km" : 5}, "1": { "date" : "16.8.2022", "time" : "11:00", "activity" : "Dauerlauf", "distance_km" : 15}, } print(training_log["0"]["activity"]) #> "Radfahren" - Diese Struktur ist sehr flexibel und erlaubt es uns, beliebig viele Informationen zu speichern
- Entsprechend werden sollte Ansätze auch in den Praxis genutzt, um Daten zu speichern (z.B. in NoSQL-Datenbanken, JSON-Dateien, etc.)
Kontrollstrukturen
- Steuern den Programmablauf
- Die wichtigsten Kontrollstrukturen sind:
- Sequenz (Folge von Aktionen ohne jede Bedingung)
- Alternative/Verzweigung (
if,if-else,elseif) - Repetition/Schleife (
while,for)
- Alle weiteren Kontrollstrukturen (
do-while,foreach,switch,break, usw.) sind auf die bereits genannten zurückführbar
while-Schleife - abweisende Schleife
while <logischer Ausdruck>:
<Anweisungsblock>
True)
- Eventuell wird die Anweisung nie ausgeführt, weil zuerst die Bedingung überprüft wird

# Beispiel Ausgabe aller ganzen Zahlen im Bereich von 1...1000,
n = 1 # Variable als Zähler
while (n <= 1000):
print(n) # Was eingerückt ist, ist in der Schleife und wird wiederholt
n = n + 1 # Das wird in jeder Schleife ausgeführt
for-Schleife - Zählschleife
- Führt den Anweisungsblock mit einer bestimmten Anzahl von Wiederholungen aus
for <Element> in <Liste>: <Anweisungsblock> -
Kann zum Beispiel auch eine Liste durchgehen
for wert in [1,2,3,4,5,6,7]: print(wert) # Gibt nacheinander 1,2,3,4,5,6,7 aus -
Anstelle von Listen können auch Zahlenbereich definiert werden
for wert in range(1,8): print(wert) # Gibt nacheinander 1,2,3,4,5,6,7 aus
for-Schleife - mit Counter
- der
inBefehl ist eine Verkürzung in Python - in anderen Programmiersprachen muss der
indexmanuell übergeben werden
liste = [1,2,3,4,5,6,7]
start_index = 0
end_index = len(liste)
for index in range(start_index,end_index):
wert = liste[index]
print(wert) # Gibt nacheinander 1,2,3,4,5,6,7 aus
for-Schleife - mit Counter pythonic
- der
inBefehl ist eine Verkürzung in Python - in anderen Programmiersprachen muss der
indexmanuell übergeben werden
liste = [1,2,3,4,5,6,7]
for index, wert in enumerate(liste):
print(index, wert) # Gibt nacheinander 1,2,3,4,5,6,7 aus
if-Abfrage - einseitige Alternative
if <logischer Ausdruck>:
<Anweisungsblock>
TRUE: Anweisungsblock ausführen
- FALSE: Anweisungsblock überspringen
# Beispiel printed nur, wenn condition = True
pin_correct = True
if pin_correct:
print('Pin is correct!')
🧠 if-else-Abfrage - zweiseitige Alternative
if <logischer Ausdruck>:
<Anweisungsblock a>
else:
<Anweisungsblock b>
TRUE: Anweisungsblock a ausführen
- FALSE: Anweisungsblock b ausführen
# Beispiel printed Lösung
a = 4
b = 3
if a>b:
print("a ist größer b")
else:
print("b ist größer a")
# Beispiel Ausgabe aller ganzen Zahlen im Bereich von 1...1000,
# die durch 13 gerade teilbar sind
n = 0
while (n <= 1000):
if (n % 13 == 0): # Die Bedingung prüft, ob n genau durch 13 teilbar ist
print(n) # Das wird nur ausgeführt, wenn die Bedingung im if Block wahr ist
n = n + 1 # Das wird in jeder Schleife ausgeführt, weil es nicht im if-Block steht
Ausnahmebehandlung
- (Un)erwartete Fehler im Code zur Laufzeit
- Programme sollen nicht abstürzen
- Behandlung von Fehlern zur Laufzeit
numbers = [1,2,0,4,5]
for number in numbers:
result = 10 / number
print("{}/{}={}".format(10,number,result))
Try-Except-Blöcke
numbers = [1,2,0,4,5]
for number in numbers:
# Versuche folgende Operation
try:
result = 10 / number
print("{}/{}={}".format(10,number,result))
# Wenn ein ZeroDivisionError auftritt
except ZeroDivisionError:
# Mache folgendes
print("Division durch Null ist nicht erlaubt.")
# Anstelle die Ausführung des Programms zu unterbrechen
Weitere Struktur
try-Block führt einen Code-Block versuchsweise aus- Der
except-Block ist der Code, der bei einem Fehler ausgeführt wird- Es lassen sich auch verschiedene Exception Types getrennt behandeln
else-Block wird ausgeführt, wenn keine Exception auftritt- Der
finally-Block wird auf jeden Fall ausgeführt
Beispiel eine weiteren except-Block
numbers = [1, 2, 0, "3", 4, 5]
for number in numbers:
# Versuche folgende Operation
try:
result = 10 / number
print("{}/{}={}".format(10,number,result))
# Wenn ein ZeroDivisionError auftritt
except ZeroDivisionError:
# Mache folgendes
print("Division durch Null ist nicht erlaubt.")
# Anstelle die Ausführung des Programms zu unterbrechen
except TypeError:
print("Division von String nicht erlaubt")
✍️ Anwendungsfall: Leistungstest mit Ergometer

Stufentest

Auswertung

- aerobe Schwelle ist der Punkt, an dem der Laktatspiegel im Blut zu steigen beginnt
- aerob-anaerobe Schwelle (Laktatschwelle): höchstmögliche Belastungsintensität, welche unter Aufrechterhaltung eines Gleichgewichtszustandes zwischen der Bildung und dem Abbau (der weiteren oxidativen Verstoffwechselung) von Laktat erbracht werden kann Quelle
🏆 Sakai-Aufgabe 1: Anlegen eines Versuchs

Stellen Sie sich vor, Sie erstellen eine Liste mit zehn Leistungstests, die alle heute auszuführen sind und mittels eines Dictionaries beschrieben werden. Diese Tests haben alle Sie als Versuchsleiter, dasselbe Erstellungsdatum und eine eindeutige Id_Nummer, die mit bei einer beliebigen Variable first_experiment_id beginnt.
- Schreiben Sie eine Schleife, um die 10 Experimente zu erstellen.
- Bauen Sie ein try-except-Block ein, um sicherzustellen, dass das Programm bei Eingaben von floats und strings als
first_experiment_idnicht abstürzt - Nutzen Sie Type Hinting, um den Datentyp der Variablen zu spezifizieren
-
Schreiben Sie eine zweite Schleife, um die ersten fünf Experimente anzuzeigen
-
Geben Sie aus, wie viele Experimente mit einer geraden ID erstellt wurden
- Kopieren Sie ihren Python Code in die Lösung