Vorwissen: Python Grundlagen (Variablen, Verzweigungen mit elif, Zufallszahlen, Format-Strings)

Lernziele. Nach diesem Kapitel kannst du …

  • eigene Funktionen definieren und aufrufen und erklären, in welcher Reihenfolge der Code dabei ausgeführt wird.
  • Funktionen mit Parametern schreiben und den Unterschied zwischen Parameter und Argument erklären.
  • Funktionen schreiben, die einen Wert zurückgeben (return), und erklären, worin sich return von print unterscheidet.
  • erklären, warum Variablen in einer Funktion lokal sind.
  • Funktionen mit assert testen.
  • ein grösseres Problem in kleine Funktionen zerlegen.

Mit einer while-Schleife wiederholst du einen Codeblock direkt hintereinander. Oft brauchst du aber den gleichen Codeblock an verschiedenen Stellen im Programm. Bisher bleibt dir dann nur Copy-Paste – und Copy-Paste heisst: Jeder Fehler steckt danach mehrfach im Code.

Mit einer Funktion gibst du einem Codeblock einen Namen. Danach kannst du ihn überall mit diesem Namen aufrufen. Das hat drei Vorteile:

  1. Wiederverwenden: Der Code steht nur einmal da, auch wenn du ihn oft brauchst.
  2. Lesbarkeit: turn_around() sagt sofort, was passiert. Zwei kara.turnLeft() muss man erst entschlüsseln.
  3. Zerlegen: Ein grosses Problem wird in kleine, überschaubare Teilprobleme aufgeteilt.

Kara kennt nur wenige Befehle, zum Beispiel keinen zum Umdrehen. Den bauen wir uns selbst:

########## M...>....# ########## # Definition: bringt Kara einen neuen Befehl bei def turn_around(): kara.turnLeft() kara.turnLeft() # Hauptprogramm while not kara.treeFront(): kara.move() turn_around() # 1. Aufruf while not kara.mushroomFront(): kara.move() turn_around() # 2. Aufruf an einer anderen Stelle
  • Eine neue Funktion definierst du mit dem Schlüsselwort def (von engl. define). Darauf folgen der Funktionsname, runde Klammern () und ein Doppelpunkt :.
  • Alle danach eingerückten Zeilen bilden den Funktionskörper.
  • Funktionsnamen schreibst du wie Variablennamen: Kleinbuchstaben, Wörter mit _ getrennt, z.B. turn_around. Diese Schreibweise heisst snake_case und ist in Python üblich. Wir verwenden englische Namen.
  • Karas eigene Befehle wie turnLeft sind dagegen in camelCase geschrieben (Wortanfänge gross). Das stammt aus der Programmiersprache Java, in der Kara ursprünglich entwickelt wurde. Für eigene Funktionen halten wir uns an die Python-Konvention.

Die Definition allein bewirkt noch nichts: Python merkt sich nur, dass es eine Funktion turn_around gibt. Erst der Aufruf turn_around() führt den Funktionskörper aus. Dabei passiert Folgendes:

  1. Python springt in die Funktion und führt den Funktionskörper von oben nach unten aus.
  2. Danach springt Python zurück an die Stelle des Aufrufs und macht dort mit der nächsten Zeile weiter.

Daraus folgen zwei Regeln:

  • Eine Funktion muss definiert sein, bevor sie aufgerufen wird. Deshalb stehen Funktionsdefinitionen immer oben im Programm, das Hauptprogramm darunter.
  • Die Klammern gehören zum Aufruf: turn_around() ruft die Funktion auf. turn_around ohne Klammern tut gar nichts, und zwar ohne Fehlermeldung!

Aufgabe K1: Vorhersage

Teil 1: Lies den folgenden Code, ohne ihn auszuführen. Schreibe auf Papier auf, was ausgegeben wird. Führe ihn erst dann aus und vergleiche.

def refrain(): print("B") print("C") print("A") refrain() print("D") refrain()

Teil 2: Was passiert, wenn du die Zeile print("A") samt den Zeilen darunter über die Funktionsdefinition verschiebst? Sag es zuerst voraus, dann probiere es aus. Lies die Fehlermeldung genau!

Lösung

Aufgabe K2: Treppenhaus

Kara soll die Treppe hinunter zum Pilz. Das Hauptprogramm ist schon fertig: Es ruft die Funktion step() so lange auf, bis Kara vor dem Pilz steht. Nur: Die Funktion step() gibt es noch nicht.

Schreibe die Funktion step(), die Kara genau eine Stufe hinunterbringt. Danach soll Kara wieder nach rechts schauen. Das Hauptprogramm darfst du nicht verändern.

########## #>.####### ##..###### ###..##### ####..#### #####..### ######..## #######.M# ########## def step(): kara.move() # Ergänze hier, damit Kara genau eine Stufe hinuntersteigt # Hauptprogramm – nicht verändern! while not kara.mushroomFront(): step() def step(): kara.move() kara.turnRight() kara.move() kara.turnLeft() # Hauptprogramm – nicht verändern! while not kara.mushroomFront(): step() ########## #..####### ##..###### ###..##### ####..#### #####..### ######..## #######>M# ##########

Beachte: Hier hast du zuerst benutzt und dann gebaut: Das Hauptprogramm beschreibt die Lösung mit einem Befehl, den es noch gar nicht gibt. So gehen Programmierer:innen auch bei grossen Problemen vor.

turn_around() macht immer genau dasselbe. Oft soll eine Funktion aber leicht unterschiedliche Dinge tun, z.B. unterschiedlich viele Kleeblätter legen. Dazu gibt man der Funktion beim Aufruf eine Information mit:

############### #.............# #.............# #.>...........# #.............# #.............# ############### def draw_leaves(length): # legt 'length' Kleeblätter in einer Reihe while length > 0: kara.putLeaf() kara.move() length = length - 1 draw_leaves(5) # length hat den Wert 5 kara.turnRight() draw_leaves(2) # length hat den Wert 2
  • length in der Definition heisst Parameter. Er funktioniert in der Funktion wie eine gewöhnliche Variable.
  • 5 im Aufruf heisst Argument. Beim Aufruf erhält der Parameter den Wert des Arguments: length = 5.
  • Mehrere Parameter trennst du mit Kommas: def greet(name, town):. Beim Aufruf werden die Argumente der Reihe nach zugewiesen: greet("Oskar", "Amriswil") ergibt name = "Oskar" und town = "Amriswil". #### Aufgabe K3: Walk the Line

Schreibe eine Funktion walk(steps), die Kara steps Felder vorwärts bewegt. Das Hauptprogramm ist vorgegeben und soll Kara damit vor den Pilz bringen.

############ #>...#.....# #....#.....# #........M.# #..........# ############ def walk(steps): # Dein Code hier # Hauptprogramm walk(3) kara.turnRight() walk(2) kara.turnLeft() walk(4) def walk(steps): while steps > 0: kara.move() steps = steps - 1 # Hauptprogramm walk(3) kara.turnRight() walk(2) kara.turnLeft() walk(4) ############ #....#.....# #....#.....# #.......>M.# #..........# ############

Aufgabe K4: Quadrat

Verwende die Funktion draw_leaves(length) von oben, um eine Funktion draw_square(size) zu schreiben. Sie soll ein Quadrat aus Kleeblättern legen, dessen Seiten je size Kleeblätter lang sind. Am Schluss soll Kara wieder auf dem Startfeld stehen und nach rechts schauen.

Eine Funktion darf also selbst andere Funktionen aufrufen!

Tipp

############ #..........# #..........# #..........# #..........# #..........# #..........# #..........# #.>........# ############ def draw_leaves(length): while length > 0: kara.putLeaf() kara.move() length = length - 1 # Dein Code hier: def draw_square(size): ... # Hauptprogramm draw_square(7) def draw_leaves(length): while length > 0: kara.putLeaf() kara.move() length = length - 1 def draw_square(size): sides = 4 while sides > 0: draw_leaves(size - 1) # Eckfeld zählt zur nächsten Seite kara.turnLeft() sides = sides - 1 # Hauptprogramm draw_square(7) ############ #..........# #.LLLLLLL..# #.L.....L..# #.L.....L..# #.L.....L..# #.L.....L..# #.L.....L..# #.eLLLLLL..# ############

Aufgabe K5: Nette Begrüssung

Schreibe eine Funktion greet(name, town), die eine Person herzlich begrüsst, z.B. so:

Hallo, mein lieber Oskar aus Amriswil, ich wünsche dir einen ganz tollen Tag!

Rufe die Funktion für drei verschiedene Personen auf.

Du verwendest schon lange Funktionen, die dir eine Antwort geben: kara.treeFront() liefert True oder False zurück, und diese Antwort verwendest du in if und while. Es gibt also zwei Arten von Funktionen:

Art Beispiel Resultat
Befehl kara.move(), turn_around() tut etwas, gibt aber nichts zurück
Abfrage kara.treeFront(), random.randint(1, 6) berechnet einen Wert und gibt ihn mit return zurück

Mit return schreibst du eigene Abfragen. Beispiel: Kara läuft so lange, bis sie in einem Tunnel steht, also links und rechts ein Baum ist:

############ #......##..# #>.........# #......##..# ############ def in_tunnel(): # gibt True zurück, wenn links und rechts ein Baum steht return kara.treeLeft() and kara.treeRight() # Hauptprogramm while not in_tunnel(): kara.move()

Der Aufruf in_tunnel() wird durch den zurückgegebenen Wert ersetzt, also durch True oder False. Genauso funktioniert es mit Zahlen:

import random def roll_dice(): # gibt eine zufällige Augenzahl von 1 bis 6 zurück pips = random.randint(1, 6) return pips total = roll_dice() + roll_dice() # zwei Würfe zusammenzählen print(f"Du hast {total} gewürfelt.")

return beendet die Funktion sofort. Code nach einem ausgeführten return wird nicht mehr ausgeführt. Deshalb kann eine Funktion mehrere return haben, z.B. in verschiedenen Zweigen einer Verzweigung:

def sign(x): if x > 0: return "positiv" if x < 0: return "negativ" return "null" # wird nur erreicht, wenn x weder > 0 noch < 0 ist print(sign(7)) print(sign(-2)) print(sign(0))

Aufgabe K6: Abzweigung finden

Kara läuft durch einen Gang und soll in die erste Abzweigung einbiegen. Schreibe die Abfrage side_free(). Sie soll True zurückgeben, wenn links oder rechts von Kara kein Baum steht, sonst False. Das Hauptprogramm ist vorgegeben.

########## #>.......# #####.#### #####.#### #####M#### ########## def side_free(): # Dein Code hier pass # Hauptprogramm while not side_free(): kara.move() # in die Abzweigung einbiegen if not kara.treeLeft(): kara.turnLeft() else: kara.turnRight() while not kara.mushroomFront(): kara.move() def side_free(): return not kara.treeLeft() or not kara.treeRight() # Hauptprogramm while not side_free(): kara.move() # in die Abzweigung einbiegen if not kara.treeLeft(): kara.turnLeft() else: kara.turnRight() while not kara.mushroomFront(): kara.move() ########## #........# #####.#### #####v#### #####M#### ##########

Aufgabe K7: Münzwurf

Schreibe eine Funktion head_or_tail(), die einen Münzwurf simuliert: Sie soll zufällig "Kopf" oder "Zahl" zurückgeben. Die Funktion selbst gibt nichts aus! Die Ausgabe erfolgt im Hauptprogramm.

Simuliere im Hauptprogramm 20 Münzwürfe und gib jedes Resultat aus. Zusatz: Zähle mit, wie oft "Kopf" kam.

Tipp

Das ist der klassische Stolperstein bei Funktionen:

print(x) return x
Wohin geht der Wert? auf den Bildschirm – für Menschen zurück an den Aufrufer – fürs Programm
Kann man damit weiterrechnen? nein ja: y = f(3) + 1
Was liefert der Aufruf? None (nichts) den Wert x

Faustregel: Eine Funktion, die etwas berechnet, gibt das Resultat mit return zurück. Ausgegeben wird im Hauptprogramm. So kann man die Funktion überall wiederverwenden, auch dort, wo man das Resultat gar nicht anzeigen will.

Aufgabe K8: Vorhersage

Was gibt dieses Programm aus? Schreib es zuerst auf Papier auf, dann führe es aus.

def double_print(x): print(2 * x) def double_return(x): return 2 * x a = double_print(5) b = double_return(5) print(a) print(b)

Lösung

Aufgabe K9: Formeln als Funktionen

Funktionen mit Rückgabewert haben einen grossen Vorteil: Man kann sie automatisch testen. Die Zeile

assert volume_cube(2) == 8

prüft, ob deine Funktion für die Seitenlänge 2 wirklich 8 zurückgibt. Stimmt etwas nicht, gibt es einen AssertionError. Die Tests dieser Aufgabe laufen automatisch mit. Schreibe die folgenden Funktionen. Alle sollen ihr Resultat zurückgeben, nicht ausgeben:

  • volume_cube(x): Volumen eines Würfels mit Seitenlänge x.
  • volume_sphere(r): Volumen einer Kugel mit Radius r: $V = \frac{4\pi}{3}\cdot r^3$. Die Zahl $\pi$ erhältst du mit math.pi.
  • pythagoras(a, b): Länge der Hypotenuse eines rechtwinkligen Dreiecks mit den Katheten a und b. Die Wurzel ziehst du mit math.sqrt(x).

Gib danach im Hauptprogramm aus: Welches Volumen hat ein Würfel mit 13 cm Seitenlänge?

Aufgabe K10: Fakultät

Die Fakultät einer natürlichen Zahl $n$ ist das Produkt aller natürlichen Zahlen von $1$ bis $n$. Man schreibt sie mit einem Ausrufezeichen: $5! = 1 \cdot 2 \cdot 3 \cdot 4 \cdot 5 = 120$. Per Definition ist $0! = 1$.

Schreibe eine Funktion factorial(n), die $n!$ zurückgibt.

Challenge für absolute Freaks: Kannst du die Fakultät ganz ohne Schleife berechnen? Tipp: $5! = 5 \cdot 4!$. Dann hast du das Prinzip der Rekursion entdeckt: Eine Funktion ruft sich selbst auf!

Variablen, die innerhalb einer Funktion entstehen, sind lokal: Es gibt sie nur, während die Funktion läuft. Von aussen sind sie unsichtbar.

def make_secret(): secret = 42 # lokale Variable make_secret() print(secret) # NameError: secret gibt es hier nicht

Auch Parameter sind lokal. Ändert die Funktion ihren Parameter, bleibt die Variable des Aufrufers unverändert:

def countdown(n): while n > 0: print(n) n = n - 1 # ändert nur das lokale n print("Los!") start = 3 countdown(start) print(start) # Was wird hier ausgegeben? Sag es voraus!

Das ist kein Nachteil, sondern genau der Sinn der Sache: Eine Funktion ist eine abgeschlossene Blackbox. Was hineingeht, sind die Argumente, was herauskommt, ist der Rückgabewert. Alles dazwischen bleibt drinnen.

Und wenn eine Funktion etwas zählen soll? Dann zählt sie mit einer lokalen Variablen und gibt das Resultat mit return zurück. Versucht sie dagegen, eine Variable von ausserhalb zu verändern, gibt es einen Fehler (UnboundLocalError). Das zeigt die nächste Aufgabe.

Aufgabe K11: Kleeblätter zählen

Kara soll bis zum Baum laufen und zählen, auf wie vielen Feldern ein Kleeblatt liegt. Der vorgegebene Code funktioniert aber nicht.

  1. Führe den Code aus und lies die Fehlermeldung. Erkläre in eigenen Worten, was das Problem ist.
  2. Repariere die Funktion count_leaves(): Sie soll mit einer lokalen Variablen zählen und die Anzahl zurückgeben. Das Hauptprogramm speichert das Resultat in n und gibt es aus.
############ #>L.LL.L.L.# ############ count = 0 def count_leaves(): while not kara.treeFront(): kara.move() if kara.onLeaf(): count = count + 1 # Hauptprogramm count_leaves() print(f"Kara hat {count} Kleeblätter gefunden.") def count_leaves(): count = 0 # lokale Variable while not kara.treeFront(): kara.move() if kara.onLeaf(): count = count + 1 return count # Hauptprogramm n = count_leaves() print(f"Kara hat {n} Kleeblätter gefunden.") assert n == 5, f"Es liegen 5 Kleeblätter, gezählt wurden aber {n}"

Hintergrund

Fehler Was passiert Lösung
Funktion aufgerufen, bevor sie definiert ist NameError: name '…' is not defined Definitionen nach oben, Hauptprogramm nach unten
Klammern beim Aufruf vergessen: turn_around gar nichts, auch keine Fehlermeldung! turn_around()
Falsche Anzahl Argumente: walk() statt walk(3) TypeError: … missing 1 required positional argument Definition und Aufruf vergleichen
return vergessen Aufruf liefert None Resultat mit return zurückgeben
print statt return Wert erscheint auf dem Bildschirm, ist aber für das Programm verloren siehe print oder return?
Doppelpunkt nach def …() vergessen SyntaxError def name():

Aufgabe K12: Fehlersuche

Im folgenden Programm stecken vier Fehler. Behebe sie einen nach dem anderen. Lies dazu jedes Mal die Fehlermeldung und die Zeilennummer genau! Die Tests laufen erst durch, wenn alle Fehler behoben sind.

Lösung

Die meisten Würfel haben 6 Seiten, manche aber 12 oder 20. Mit einem Vorgabewert (engl. default value) muss man die Seitenzahl nur angeben, wenn sie von 6 abweicht:

import random def roll_dice(sides=6): return random.randint(1, sides) print(roll_dice()) # 6er-Würfel: Vorgabewert wird verwendet print(roll_dice(12)) # 12er-Würfel print(roll_dice(20)) # 20er-Würfel

Wird für sides kein Argument übergeben, gilt sides = 6. Üblich ist, beim Vorgabewert keine Leerzeichen um das = zu setzen.

Aufgabe K13: Grussformel

Schreibe eine Funktion greeting(name, word="Hallo"), die den Gruss als String zurückgibt. Er soll aus dem Grusswort, einem Komma, dem Namen und einem Ausrufezeichen bestehen: - greeting("Oskar") gibt "Hallo, Oskar!" zurück. - greeting("Oskar", "Grüezi") gibt "Grüezi, Oskar!" zurück.

Vergleiche mit Aufgabe K5: Warum ist diese Version vielseitiger?

Nützliche Funktionen willst du nicht in jedes Programm neu kopieren. Stattdessen legst du sie in eine eigene Datei, z.B. toolbox.py. Das ist dein Werkzeugkasten, und mit import holst du die Werkzeuge ins Hauptprogramm:

from toolbox import draw_square, walk   # holt genau diese zwei Funktionen

Das kennst du schon: import random holt Pythons Werkzeugkasten für Zufallszahlen.

Aufgabe K14: Toolbox

  1. Kopiere deine Funktionen draw_leaves(length) und draw_square(size) aus K4 sowie walk(steps) aus K3 in die Datei toolbox.py.
  2. Schreibe in main.py ein Programm, das fünf Quadrate der Grösse 3 nebeneinander zeichnet, mit je einem leeren Feld Abstand.
######################## #......................# #......................# #......................# #>.....................# ######################## # holt Funktionen aus toolbox.py from toolbox import draw_square, walk # Dein Code hier: zeichne 5 Quadrate from toolbox import draw_square, walk squares = 5 while squares > 0: draw_square(3) walk(4) # Quadrat (3) + Abstand (1) squares = squares - 1 def draw_leaves(length): while length > 0: kara.putLeaf() kara.move() length = length - 1 def draw_square(size): sides = 4 while sides > 0: draw_leaves(size - 1) kara.turnLeft() sides = sides - 1 def walk(steps): while steps > 0: kara.move() steps = steps - 1 ######################## #......................# #LLL.LLL.LLL.LLL.LLL...# #L.L.L.L.L.L.L.L.L.L...# #LLL.LLL.LLL.LLL.LLL...# ########################

Aufgabe K15: Quadrat-Treppe (optional)

Zeichne mit deiner Toolbox nebeneinander Quadrate der Grösse 2, 3, 4 und 5, wieder mit je einem leeren Feld Abstand. Verwende eine Schleife und eine Variable size.

###################### #....................# #....................# #....................# #....................# #>...................# ###################### from toolbox import draw_square, walk # Dein Code hier from toolbox import draw_square, walk size = 2 while size <= 5: draw_square(size) walk(size + 1) size = size + 1 def draw_leaves(length): while length > 0: kara.putLeaf() kara.move() length = length - 1 def draw_square(size): sides = 4 while sides > 0: draw_leaves(size - 1) kara.turnLeft() sides = sides - 1 def walk(steps): while steps > 0: kara.move() steps = steps - 1 ###################### #............LLLLL...# #.......LLLL.L...L...# #...LLL.L..L.L...L...# #LL.L.L.L..L.L...L...# #LL.LLL.LLLL.LLLLL...# ######################

Aufgabe K16: Notenrechner

Schreibe eine Funktion grade(points), welche die Note für eine Punktzahl zurückgibt:

$$\text{Note} = \frac{5 \cdot \text{Punkte}}{\text{Punkte für Note 6}} + 1$$

  • Lege die Punktzahl für die Note 6 in einer Konstanten fest: eine Variable, die sich nie ändert und deshalb in Grossbuchstaben geschrieben wird, z.B. POINTS_FOR_SIX = 40.
  • Runde die Note mit round(note, 2) auf zwei Nachkommastellen.
  • Wer mehr Punkte erreicht als nötig, erhält trotzdem eine 6.

Aufgabe K17: Glückskeks

Schreibe eine Funktion fortune_cookie(), die bei jedem Aufruf zufällig einen von fünf Glückskeks-Sprüchen zurückgibt. Erfinde selbst Sprüche oder klaue sie dreist aus dem Internet. Rufe die Funktion im Hauptprogramm dreimal auf und gib die Sprüche aus.

Tipp

import random # Dein Code hier

Aufgabe K18: Quadratische Gleichungen

Eine quadratische Gleichung hat die Form $ax^2 + bx + c = 0$ (mit $a \neq 0$). Ihre Lösungen sind:

$$x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}$$

Wie viele Lösungen es gibt, verrät die Diskriminante $D = b^2 - 4ac$: Ist $D < 0$, gibt es keine Lösung, ist $D = 0$, gibt es eine, und ist $D > 0$, gibt es zwei.

  1. Schreibe eine Funktion count_solutions(a, b, c), die die Anzahl Lösungen zurückgibt (0, 1 oder 2).
  2. Schreibe eine Funktion print_solutions(a, b, c), die count_solutions verwendet und die Lösungen in einem schönen Satz ausgibt.

Kontrolle: - $3x^2 - 6x - 5 = 0$ hat zwei Lösungen: $-0.632993$ und $2.63299$ - $x^2 - 4x + 4 = 0$ hat eine Lösung: $2$ - $x^2 + 2x + 7 = 0$ hat keine Lösung

def name(parameter1, parameter2=vorgabewert):   # Definition
    # Funktionskörper (eingerückt)
    return resultat                              # optional: beendet die Funktion
 
wert = name(argument1, argument2)                # Aufruf
  • Definition (def) merkt sich den Code, erst der Aufruf (mit Klammern!) führt ihn aus. Definitionen stehen oben.
  • Parameter stehen in der Definition, Argumente im Aufruf. Beim Aufruf erhalten die Parameter die Werte der Argumente.
  • return gibt einen Wert an den Aufrufer zurück und beendet die Funktion. print zeigt nur etwas an.
  • Variablen in einer Funktion sind lokal: Sie existieren nur während des Aufrufs.
  • Funktionen mit Rückgabewert kann man mit assert testen.
  • Grosse Probleme zerlegst du in kleine Funktionen. Oft hilft es, das Hauptprogramm zuerst zu schreiben.

Mit Funktionen kannst du nun auch grössere Probleme in kleine Teile zerlegen. Genau das brauchst du in Algorithmen II!

  • gf_informatik/karatutorial/funktionen.txt
  • Zuletzt geändert: 2026-11-02 16:25
  • von hof