Funktionen

Die Strukturierungseinheit, ohne die Programmierung sehr schnell unangenehm wird.

Grundlagen 12 min Einsteiger 26. April 2026

Jeder Python-Befehl, den du bisher benutzt hast — print(), input(), range(), len() — ist eine Funktion, die jemand anderes geschrieben hat. Funktionen sind der grundlegende Baustein jedes Programms: Sie nehmen Eingaben entgegen, erledigen Arbeit und liefern ein Ergebnis zurück.

In diesem Artikel lernst du, eigene Funktionen zu bauen, verstehst warum sie Code kürzer und sicherer machen, und entdeckst Scope — die unsichtbaren Regeln, die verhindern, dass Variablen aus Funktionen austreten und Chaos verursachen.

Was ist eine Funktion?

Du verwendest bereits seit deiner ersten Zeile Python Funktionen. Hier sind acht, die du schon kennst:

print() Gibt Text auf dem Bildschirm aus
input() Liest Tastatureingabe als String
range() Erzeugt eine Zahlenfolge
len() Zählt Elemente in einer Sammlung
type() Zeigt den Datentyp eines Werts
int() Wandelt in eine Ganzzahl um
str() Wandelt in einen String um
float() Wandelt in eine Dezimalzahl um

Funktion

AnalogieDefinition
Eine Funktion ist wie eine elektrische Saftpresse. Du gibst Orangen hinein (Eingabe/Parameter), drückst den Knopf (Funktionsaufruf), die Maschine erledigt interne Arbeit, die du nicht verstehen musst (Verarbeitung), und heraus kommt Orangensaft (Rückgabewert). Du musst nur wissen, was reingeht und was rauskommt.

Die Saftpressen-Analogie passt gut für Input/Output und Abstraktion. Aber eine Saftpresse kann nur pressen — eine Funktion kann beliebige Logik enthalten, inklusive Verzweigungen, Schleifen und Aufrufe anderer Funktionen. Manche Funktionen nehmen keine Eingabe entgegen, und manche liefern kein sinnvolles Ergebnis zurück.

So läuft ein Funktionsaufruf ab

1
Python sieht den Aufruf greet("Ada")
2
Das Argument "Ada" wird an den Parameter name gebunden
3
Der Funktionskörper wird ausgeführt: f"Hallo, {name}!"
4
return sendet den Wert "Hallo, Ada!" zurück
5
Der Aufrufer erhält den String und kann ihn weiterverwenden
print()

Zeigt Text auf dem Bildschirm an, gibt aber None zurück. Das Ergebnis kann nicht in einer Variable gespeichert oder weiterverwendet werden. Geeignet zum Anzeigen, nicht zum Rechnen.

return

Sendet einen Wert an den Aufrufer zurück. Das Ergebnis kann in einer Variable gespeichert, weiterverarbeitet oder an eine andere Funktion übergeben werden. So gibt man Daten aus einer Funktion heraus.

Häufiger Fehler: print() statt return

Anfänger verwechseln print() und return häufig. Eine Funktion, die nur print() benutzt, zeigt zwar etwas an — aber der Aufrufer erhält None statt eines brauchbaren Werts.

def verdopple(x):
    print(x * 2)    # Zeigt 10 an...

ergebnis = verdopple(5)
print(ergebnis)         # ...aber ergebnis ist None!

Richtig wäre: return x * 2 — dann enthält ergebnis den Wert 10 und kann weiterverwendet werden.

Warum Funktionen? DRY und Modularisierung

DRY-Prinzip

AnalogieDefinition
Stell dir vor, du erklärst fünf verschiedenen Leuten den Weg zu fünf verschiedenen Restaurants. Ohne Funktionen beschreibst du jedes Mal den kompletten Weg vom Bahnhof bis zur Stadtmitte, bevor du den restaurantspezifischen Teil anfügst. Mit Funktionen definierst du weg_zur_mitte() einmal und verwendest es wieder: "Nimm den üblichen Weg zur Mitte, dann zweimal rechts." Der Funktionsname dient als lesbarer Kurzbefehl.

Die Wegbeschreibungs-Analogie passt gut: Wiederholte Teilrouten werden ausgelagert, der Name dient als Referenz, und eine Änderung wirkt sich überall aus. Im echten Leben kann man auf implizites Wissen setzen ("du kennst den Weg") — im Code muss jede Anweisung explizit sein.

Beispiel: Bruttopreis-Berechnung

Ohne Funktion — dieselbe Formel dreimal kopiert:

preis1 = 100 * 1.19    # 119.0
preis2 = 250 * 1.19    # 297.5
preis3 = 49.90 * 1.19  # 59.381

Mit Funktion — die Formel existiert nur einmal:

def brutto(netto):
    return netto * 1.19

preis1 = brutto(100)    # 119.0
preis2 = brutto(250)    # 297.5
preis3 = brutto(49.90)  # 59.381

Ändert sich der Steuersatz von 19% auf 16%, aktualisierst du eine einzige Zeile statt das gesamte Programm zu durchsuchen.

Modularisierung bedeutet, ein großes Problem in kleine, benannte Funktionen aufzuteilen. Jede Funktion hat eine klare Aufgabe: daten_laden(), validieren(), verarbeiten(), anzeigen(). Die Funktionsnamen wirken wie eine Gliederung — man kann den Programmablauf lesen, ohne jeden einzelnen Schritt zu verstehen.

Irrtum: Funktionen braucht man erst bei großen Programmen

Schon ein 20-Zeilen-Skript profitiert von Struktur. Wenn du dieselbe Logik zweimal schreibst, ist das ein Zeichen: Extrahiere sie in eine Funktion. Und Copy-Paste mit kleinen Anpassungen ist keine Lösung — parametrisiere die Unterschiede stattdessen.

Scope — Wo Variablen leben und sterben

Scope (Gültigkeitsbereich)

AnalogieDefinition
Stell dir ein Hotel vor. Die Lobby ist der globale Scope — jeder kann sie sehen und nutzen. Dein Zimmer ist der lokale Scope einer Funktion. Dinge, die du im Zimmer lässt (lokale Variablen), sind nur dort verfügbar. Wenn du auscheckst (Funktion endet), wird das Zimmer geräumt und sein Inhalt verschwindet.

Die Hotel-Analogie passt gut: öffentlicher Raum (global) vs. privater Raum (lokal), und beim Auschecken verschwindet der Inhalt. Aber im Hotel kann man Gegenstände aus dem Zimmer in die Lobby tragen — in Python muss man Werte per return zurückgeben und außerhalb zuweisen.

Beispiel: Gleicher Name, verschiedener Scope

nachricht = "Ich bin global"

def zeige_nachricht():
    nachricht = "Ich bin lokal"
    print(nachricht)      # "Ich bin lokal"

zeige_nachricht()
print(nachricht)          # "Ich bin global"

Innerhalb der Funktion existiert eine eigene Variable nachricht, die die globale "überschattet". Die globale Variable bleibt unverändert — genau das ist gewollt. Scope hält Funktionen voneinander unabhängig.

Fehler: Zugriff außerhalb des Scope

def berechne():
    x = 42

berechne()
print(x)    # NameError: name 'x' is not defined

Die Variable x existiert nur innerhalb der Funktion berechne(). Nach dem Aufruf ist sie verschwunden — wie ein Hotelzimmer nach dem Auschecken.

Warnung: Globale Variablen in Funktionen ändern

Mit dem Schlüsselwort global kann eine Funktion globale Variablen direkt verändern. Das funktioniert — ist aber fast immer eine schlechte Idee, weil es Funktionen von ihrer Umgebung abhängig macht und Fehler schwer auffindbar werden.

zaehler = 0

def erhoehe():
    global zaehler
    zaehler += 1

erhoehe()
print(zaehler)    # 1

Bevorzuge return statt global. Die saubere Variante: den neuen Wert zurückgeben und außerhalb zuweisen.

Interaktiv: Funktionsaufruf Schritt für Schritt

Du hast gelernt, dass lokale Variablen nur innerhalb ihrer Funktion existieren. Aber WO genau leben sie? Klicke dich durch die Schritte eines Funktionsaufrufs und beobachte den Call Stack — die interne Datenstruktur, in der Python für jeden Aufruf einen eigenen Rahmen (Frame) anlegt. Achte darauf, wie Variablen im Frame erscheinen und beim Return wieder verschwinden.

1
2
3
4
5
6
Code
1def greet(name):
2 msg = f"Hello, {name}!"
3 return msg
4
5result = greet("Ada")
6print(result)
Call Stack
<module>
(leer)
Schritt 1 / 6Startposition

Python trifft auf die Zeile result = greet("Ada"). Es erkennt einen Funktionsaufruf und bereitet sich darauf vor, die Funktion greet auszuführen.

Parameter können Standardwerte haben. Wird beim Aufruf kein Argument übergeben, greift der Standard:

def begruessung(name="Welt"):
    return f"Hallo, {name}!"

print(begruessung())         # "Hallo, Welt!"
print(begruessung("Ada"))    # "Hallo, Ada!"

Mit Keyword-Argumenten kannst du Parameter beim Namen ansprechen: begruessung(name="Ada"). Bei mehreren Parametern macht das den Code lesbarer, weil die Reihenfolge egal wird.

Vorsicht: Verwende niemals eine leere Liste als Standardwert (def f(items=[])). Python erstellt den Standardwert nur einmal — die Liste sammelt Einträge über mehrere Aufrufe hinweg an. Verwende stattdessen items=None und erstelle die Liste im Funktionskörper.

Die wahre Stärke von Funktionen zeigt sich, wenn der Rückgabewert einer Funktion als Eingabe für die nächste dient — eine Pipeline aus kleinen, spezialisierten Bausteinen:

def laden(datei):
    return open(datei).read()

def bereinigen(text):
    return text.strip().lower()

def zaehlen(text):
    return len(text.split())

# Pipeline: laden -> bereinigen -> zaehlen
inhalt = laden("daten.txt")
sauber = bereinigen(inhalt)
anzahl = zaehlen(sauber)
print(f"{anzahl} Wörter")

In späteren Artikeln wirst du dieses Muster in der Datenverarbeitung und in Machine-Learning-Workflows wiederfinden.

Das Wichtigste auf einen Blick

  1. Eine Funktion wird mit def definiert, nimmt Parameter als Eingabe und nutzt return, um ein Ergebnis zurückzugeben. Ohne return gibt die Funktion None zurück.
  2. print() zeigt Text auf dem Bildschirm an, gibt aber None zurück. return übergibt einen Wert an den Aufrufer zur Weiterverwendung. Die beiden sind nicht austauschbar.
  3. Das DRY-Prinzip: Logik einmal schreiben, überall aufrufen. Bei Änderungen wird nur eine Stelle aktualisiert.
  4. Modularisierung bedeutet, ein großes Problem in kleine, benannte Funktionen aufzuteilen. Jede Funktion hat eine klare Aufgabe.
  5. Variablen innerhalb einer Funktion sind lokal — sie existieren nur während der Ausführung und sind außerhalb unsichtbar. Diese Isolation macht Funktionen wiederverwendbar ohne Seiteneffekte.

Quiz: Funktionen

Frage 1 / 4
Noch offen

Was gibt eine Funktion zurück, wenn sie kein return-Statement enthält?

Wählen Sie eine Antwort
Auflösung: 1) C · 2) B · 3) B · 4) B

Checkpoint

  • Was ist der Unterschied zwischen der Definition einer Funktion mit def und ihrem Aufruf mit Klammern? Wann wird der Code im Funktionskörper tatsächlich ausgeführt?
  • Warum ist es besser, eine wiederkehrende Berechnung wie die Bruttopreis-Formel in eine eigene Funktion auszulagern, anstatt denselben Codeblock mehrmals zu kopieren?
  • Warum verursacht print(x) außerhalb einer Funktion einen NameError, wenn x nur innerhalb der Funktion definiert wurde? Erkläre es mit dem Konzept Scope.