CSBootcampHSG

Lektion 03

Funktionen

Definiere Funktionen sauber, verstehe Parameter, Defaults und Rückgabewerte – und lerne die Stolperfallen, die in Quiz 03 geprüft werden.

Dauer:
45 Min. geschätzt
Voraussetzungen:
Grundlagen Kontrollfluss (Lektion 02)
Illustration: eine Python-Schlange, die sich um die Ziffer 3 windet

Theorie & Konzepte

Phase 1 / 3

Eine Funktion ist eine benannte Anweisungsfolge, die du später mit unterschiedlichen Daten wieder aufrufen kannst. Statt denselben Code an mehreren Stellen zu wiederholen, schreibst du ihn einmal, gibst ihm einen Namen und rufst ihn auf, wann immer du ihn brauchst.

Diese Lektion ist so aufgebaut, dass du jede Stolperfalle aus HSG Quiz 03 einzeln siehst und übst. Wenn du das Übungsquiz am Ende bestehst, sitzen die Ideen.

Definition und Aufruf

Eine Funktion definierst du mit def, gefolgt vom Namen, der Parameterliste und einem Doppelpunkt. Der Rumpf ist eingerückt.

def greet(name):
    print(f"Grüezi, {name}")

greet("Mira")   # gibt: Grüezi, Mira
  • name ist ein Parameter — ein Platzhalter, der beim Aufruf gefüllt wird.
  • "Mira" ist das Argument — der konkrete Wert, der in name landet.
  • Zwischen def und dem ersten Aufruf passiert nichts. Definition ≠ Ausführung.

Parameter vs. Argument

Funktionsanatomie: Definition mit Parametern gegenüber Aufruf mit ArgumentenDefinitiondef greet(name, excl="!"):return f"Hi {name}`{excl}`"Parametermit Defaultwird aufgerufenAufrufgreet("Mira", excl="?")positionalkeywordArgumente werden an Parameter gebunden — positional nach Reihenfolge, Keywords nach Namen.
Beim Aufruf bindet Python die Argumente an die Parameter der Definition — in Reihenfolge und/oder per Name.

Parameter mit Defaults

Parameter können Default-Werte bekommen. Wer beim Aufruf weglässt, bekommt den Default.

def volume(length, width=1, height=1):
    return length * width * height

volume(4)           # 4
volume(4, 2)        # 8
volume(4, 2, 3)     # 24

Die Regel: Defaults stehen rechts. Sobald ein Parameter einen Default hat, müssen alle folgenden ebenfalls einen haben.

Signatur — erlaubt vs. Syntaxfehler

Python erlaubt Defaults nur am Ende der Parameterliste.

So geht's

def f(a, b=2, c=3):
    return a + b + c

Defaults sind rechts. Jede Arität 1–3 ist gültig.

Syntaxfehler

def f(a=1, b, c=3):
    ...
# SyntaxError:
# non-default argument follows default argument

Sobald a einen Default hat, muss b auch einen haben.

Positional vs. Keyword

Argumente darfst du auf zwei Arten übergeben — und mischen, solange die Reihenfolge stimmt:

volume(4, 2, 3)                        # positional
volume(length=4, height=3, width=2)    # keyword (Reihenfolge egal)
volume(4, height=3)                    # gemischt: positional zuerst

Jeden Parameter darfst du nur einmal setzen. volume(4, length=5) ist ein TypeError, weil length zweimal besetzt wäre.

Defaults werden *einmal* ausgewertet

Defaults werden einmal ausgewertet, zum Zeitpunkt der DefinitionZeit →defausgewertet einmal[] (leere Liste)f()späterf()noch späterf()immer noch späterAlle Aufrufe teilen sich dieselbe Default-Liste.
Die Klammer nach `def` läuft ein einziges Mal, zum Zeitpunkt der Definition. Alle Aufrufe teilen sich denselben Default-Wert — mit bösen Folgen bei mutables.

Rückgabewerte

Eine Funktion gibt mit return einen Wert zurück. Ohne return ist der Rückgabewert implizit None — das ist nicht dasselbe wie gar kein Wert, sondern das konkrete Objekt None:

def warn(msg):
    print(msg)

result = warn("Achtung")   # druckt Achtung
print(result)              # → None

`return` in der Schleife + implizites `None`

Zwei Pfade aus der Schleife: expliziter Rückgabewert vs. implizites Nonedef first_big(numbers):for n in numbers:n > 100?(Treffer?)jareturn nnein → weiterSchleife ist durch · kein weiteres return · Funktion endet → Noneexplizite Rückgabe
Wenn das `return` im Schleifenrumpf in keinem Durchlauf erreicht wird, läuft die Schleife durch, die Funktion endet ohne expliziten Wert — und liefert `None`.

Typprüfung mit `isinstance`

In Python fließen verschiedene Typen durch dieselbe Funktion. Wenn du nur mit einem bestimmten Typ arbeiten willst, prüfe ihn explizit:

def first_string(values):
    for v in values:
        if isinstance(v, str):
            return v
    return None

isinstance(v, (int, float)) prüft gegen mehrere Typen. Für Floats mit NaN/Inf hilft math.isfinite.

Tupel und Unpacking

Ein Tupel ist eine unveränderliche Folge von Werten. Unpacking zerlegt es in einem Rutsch in benannte Teile:

pair = (3, "drei")
x, name = pair         # Unpacking

people = [("Mira", 22), ("Luca", 19)]
for name, age in people:
    print(name, "ist", age)

Tupel gruppieren zusammengehörige Werte sicher — niemand ändert ihre Länge, niemand ersetzt ihre Elemente.

Tupel-Immutabilität betrifft den Container

Das Tupel hat fixe Slots. Eine Liste, auf die ein Slot zeigt, ist weiterhin mutable.t — Tupel (immutable)Slot 0 →"Python"Slot 1 →Liste (Ref)Liste (mutable)1234.append(4) fügt anDie Referenz in Slot 1 bleibt dieselbe.Das Tupel ändert sich nie. Der Inhalt des Objekts, auf das Slot 1 zeigt, schon.
Die Slots des Tupels sind fixiert. Aber wenn ein Slot auf ein *mutables* Objekt (z. B. eine Liste) zeigt, kann dieses Objekt sich weiter verändern — ohne dass das Tupel etwas merkt.

Aufgaben

Phase 2 / 3
Aufgabe

Fortlaufende Summe mit Defaults

2 Punkte

Schreibe eine Funktion running_total(stop, start=0, step=1), die die Summe aller ganzen Zahlen von start (inklusive) bis stop (exklusive) mit Schrittweite step zurückgibt.

Beispiele:

  • running_total(5)0 + 1 + 2 + 3 + 4 = 10
  • running_total(6, 2)2 + 3 + 4 + 5 = 14
  • running_total(10, 0, 2)0 + 2 + 4 + 6 + 8 = 20

Ist stop <= start, soll die Funktion 0 zurückgeben.

Hinweise

    Aufgabe

    Ping-Pong-Muster bauen

    2 Punkte

    Schreibe eine Funktion ping_pong(count), die eine Liste der Länge count zurückgibt. Der Inhalt folgt diesen Regeln (geprüft in dieser Reihenfolge!):

    1. Für jedes i von 1 bis count (inklusive):
    2. Wenn i sowohl durch 2 als auch durch 7 teilbar ist, nimm den String "PingPong".
    3. Ansonsten, wenn i nur durch 2 teilbar ist, nimm "Ping".
    4. Ansonsten, wenn i nur durch 7 teilbar ist, nimm "Pong".
    5. Sonst nimm die Zahl i selbst (als int, nicht als String).

    Beispiel: ping_pong(15) ergibt [1, "Ping", 3, "Ping", 5, "Ping", "Pong", "Ping", 9, "Ping", 11, "Ping", 13, "PingPong", 15].

    Hinweise

      Aufgabe

      Einzigartige Werte, sortiert

      2 Punkte

      Schreibe eine Funktion unique_sorted(items), die aus einer beliebigen Liste eine aufsteigend sortierte Liste der eindeutigen Werte erzeugt.

      Beispiele:

      • unique_sorted([3, 1, 2, 1, 3])[1, 2, 3]
      • unique_sorted([])[]
      • unique_sorted(["b", "a", "a", "c"])["a", "b", "c"]

      Die Funktion soll das Original-items nicht verändern.

      Hinweise

        Aufgabe

        Ersten nicht-leeren String finden

        2 Punkte

        Schreibe eine Funktion first_nonempty_string(values), die in der Reihenfolge von links nach rechts den ersten String zurückgibt, der nicht leer ist. Kommt kein solcher vor (oder ist values leer), gib None zurück.

        Achtung: True und False sind in Python technisch auch Zahlen (bool ist Subtyp von int), aber keine Strings. Dein Filter soll nur Werte vom Typ str berücksichtigen.

        Beispiele:

        • first_nonempty_string([1, "", "HSG", 3.14])"HSG"
        • first_nonempty_string([1, 2, 3])None
        • first_nonempty_string(["", "", "ok"])"ok"

        Hinweise

          Aufgabe

          Spalten aus Tupellisten herauslösen

          2 Punkte

          Schreibe eine Funktion pluck(records, which="first"), die aus einer Liste von Tupeln eine neue Liste baut. Der Parameter which entscheidet, welches Element pro Tupel eingesammelt wird:

          • which="first" → das erste Element jedes Tupels
          • which="last" → das letzte Element jedes Tupels

          Für alle anderen which-Werte soll die Funktion einen ValueError mit der Nachricht "unsupported 'which' value" werfen.

          Beispiele:

          • pluck([(1, "a"), (2, "b"), (3, "c")])[1, 2, 3] (Default which="first")
          • pluck([(1, "a"), (2, "b"), (3, "c")], which="last")["a", "b", "c"]
          • pluck([], which="last")[]
          • pluck([(1,)], which="last")[1]

          Hinweise

            Übungsquiz

            Phase 3 / 3

            Teste dein Verständnis in 15 Minuten mit 5 Frage(n), direkt an den HSG-Quizstolperfallen ausgerichtet.

            Quiz starten