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.
Analogie:
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.
Definition:
Eine Funktion ist ein benannter, wiederverwendbarer Codeblock, definiert mit dem Schlüsselwort def, gefolgt von einem Namen, Klammern mit optionalen Parametern und einem Doppelpunkt. Der eingerückte Körper wird erst ausgeführt, wenn die Funktion mit Klammern aufgerufen wird. Parameter sind Platzhalter in der Definition; Argumente sind konkrete Werte beim Aufruf. Das Schlüsselwort return beendet die Funktion und sendet einen Wert an den Aufrufer zurück. Ohne return gibt die Funktion implizit None zurück.
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.
Analogie:
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.
Definition:
Das DRY-Prinzip ("Don't Repeat Yourself") besagt, dass jedes Stück Logik an genau einer Stelle existieren soll. Wenn du eine Berechnung an fünf Stellen kopierst, erfordert eine zukünftige Änderung fünf Updates — und eine vergessene Stelle erzeugt einen Bug. Modularisierung geht weiter: Statt ein monolithisches 1000-Zeilen-Skript zu schreiben, teilst du es in kleine Funktionen mit klaren Namen auf, die jeweils ein Teilproblem lösen.
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.
Ä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.
Analogie:
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.
Definition:
Scope bestimmt, wo eine Variable sichtbar ist. Variablen, die innerhalb einer Funktion definiert werden, sind lokal — sie existieren nur während des Funktionsaufrufs und werden danach zerstört. Variablen auf Modulebene (außerhalb aller Funktionen) sind global — von überall lesbar, aber nicht ohne Weiteres von innerhalb einer Funktion schreibbar. Hat eine lokale Variable denselben Namen wie eine globale, "überschattet" die lokale Version die globale innerhalb der Funktion, ohne die globale zu verändern.
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.
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.
Deep Dive: Standardwerte und Keyword-Argumente
Parameter können Standardwerte haben. Wird beim Aufruf kein Argument übergeben, greift der Standard:
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.
Deep Dive: Funktionen rufen Funktionen auf
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:
In späteren Artikeln wirst du dieses Muster in der Datenverarbeitung und in Machine-Learning-Workflows wiederfinden.
Das Wichtigste auf einen Blick
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.
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.
Das DRY-Prinzip: Logik einmal schreiben, überall aufrufen. Bei Änderungen wird nur eine Stelle aktualisiert.
Modularisierung bedeutet, ein großes Problem in kleine, benannte Funktionen aufzuteilen. Jede Funktion hat eine klare Aufgabe.
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?
1. Was gibt eine Funktion zurück, wenn sie kein return-Statement enthält?
☐ A) 0
☐ B) Einen leeren String
☐ C) None
☐ D) Einen Fehler
2. Was ist der Wert von ergebnis nach diesem Code?
def verdopple(x):
print(x * 2)
ergebnis = verdopple(5)
☐ A) 10
☐ B) None
☐ C) Python wirft einen Fehler
☐ D) "10"
3. Was gibt print(x) am Ende aus?
x = "global"
def test():
x = "lokal"
test()
print(x)
☐ A) "lokal"
☐ B) "global"
☐ C) Einen Fehler
☐ D) None
4. Du hast dieselbe Berechnung an 5 Stellen in deinem Code. Die Formel ändert sich. Was ist die beste Vorgehensweise?
☐ A) Alle 5 Stellen einzeln suchen und ersetzen
☐ B) Die Berechnung in eine Funktion auslagern und 5-mal aufrufen
☐ C) Die neue Formel an alle 5 Stellen kopieren
☐ D) Die alte Formel auskommentieren und neuen Code daneben schreiben
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.