Funktionen in Python - Grundlagen
Lerne die Grundlagen von Funktionen in Python: Definition, Aufrufe, return-Werte, Scope und das DRY-Prinzip.
Funktionen in Python - Grundlagen
Funktionen sind das Herzstueck jeder gut strukturierten Software. Sie helfen dir, Code zu organisieren, Wiederholungen zu vermeiden und Programme lesbar zu gestalten. In diesem Tutorial lernst du alles, was du ueber Funktionen in Python wissen musst.
Was sind Funktionen und warum brauchen wir sie?
Eine Funktion ist ein benannter Block von Code, der eine bestimmte Aufgabe erledigt. Du kannst sie dir wie eine kleine Maschine vorstellen: Du gibst etwas hinein (Parameter), die Maschine verarbeitet es, und du bekommst ein Ergebnis zurueck.
Das DRY-Prinzip
DRY steht fuer “Don’t Repeat Yourself” - Wiederhole dich nicht. Ohne Funktionen wuerdest du denselben Code immer wieder schreiben:
# SCHLECHT: Code-Wiederholung ohne Funktionen
print("=" * 40)
print("Willkommen, Anna!")
print("=" * 40)
# ... spaeter im Code ...
print("=" * 40)
print("Willkommen, Max!")
print("=" * 40)
# ... und nochmal ...
print("=" * 40)
print("Willkommen, Lisa!")
print("=" * 40)
Mit einer Funktion wird das viel eleganter:
# GUT: Eine Funktion fuer die Begruessung
def begruessung(name):
print("=" * 40)
print(f"Willkommen, {name}!")
print("=" * 40)
begruessung("Anna")
begruessung("Max")
begruessung("Lisa")
Die Vorteile liegen auf der Hand:
- Weniger Code - du schreibst die Logik nur einmal
- Einfacher zu aendern - Aenderungen an einer Stelle wirken ueberall
- Bessere Lesbarkeit - der Funktionsname beschreibt, was passiert
- Einfacher zu testen - du kannst einzelne Funktionen isoliert pruefen
Die def-Syntax
In Python definierst du eine Funktion mit dem Schluesselwort def:
def funktionsname():
# Funktionskoerper (eingerueckt)
# Hier steht der Code, der ausgefuehrt wird
pass
Die Grundstruktur besteht aus:
def- das Schluesselwort, das eine Funktionsdefinition einleitet- Funktionsname - ein beschreibender Name (Kleinbuchstaben, Unterstriche)
- Klammern
()- hier koennen Parameter stehen - Doppelpunkt
:- leitet den Funktionskoerper ein - Eingerueckter Block - der eigentliche Code der Funktion
def sage_hallo():
print("Hallo, Welt!")
def zeige_menue():
print("1. Neues Spiel")
print("2. Spiel laden")
print("3. Einstellungen")
print("4. Beenden")
Funktionen aufrufen
Eine Funktion zu definieren fuehrt ihren Code noch nicht aus. Du musst sie aufrufen, indem du ihren Namen gefolgt von Klammern schreibst:
def sage_hallo():
print("Hallo, Welt!")
# Funktion aufrufen
sage_hallo() # Ausgabe: Hallo, Welt!
# Mehrfach aufrufen
sage_hallo() # Ausgabe: Hallo, Welt!
sage_hallo() # Ausgabe: Hallo, Welt!
Du kannst Funktionen auch mit Parametern (auch Argumente genannt) aufrufen:
def begruessung(name):
print(f"Hallo, {name}!")
begruessung("Anna") # Ausgabe: Hallo, Anna!
begruessung("Max") # Ausgabe: Hallo, Max!
Mehrere Parameter werden durch Kommas getrennt:
def stelle_vor(vorname, nachname, alter):
print(f"Ich bin {vorname} {nachname} und {alter} Jahre alt.")
stelle_vor("Anna", "Mueller", 25)
# Ausgabe: Ich bin Anna Mueller und 25 Jahre alt.
Die return-Anweisung
Mit return gibst du einen Wert aus der Funktion zurueck. Das ist einer der wichtigsten Mechanismen in der Programmierung:
def addiere(a, b):
return a + b
ergebnis = addiere(3, 5)
print(ergebnis) # Ausgabe: 8
# Du kannst den Rueckgabewert direkt verwenden
print(addiere(10, 20)) # Ausgabe: 30
return beendet die Funktion sofort - Code nach return wird nicht mehr ausgefuehrt:
def pruefe_alter(alter):
if alter < 0:
return "Ungueltiges Alter"
if alter < 18:
return "Minderjaehrig"
return "Volljaehrig"
print("Diese Zeile wird nie erreicht!")
print(pruefe_alter(25)) # Ausgabe: Volljaehrig
print(pruefe_alter(15)) # Ausgabe: Minderjaehrig
print(pruefe_alter(-1)) # Ausgabe: Ungueltiges Alter
Funktionen ohne return (None)
Wenn eine Funktion kein return hat (oder return ohne Wert), gibt sie automatisch None zurueck:
def sage_hallo(name):
print(f"Hallo, {name}!")
ergebnis = sage_hallo("Anna") # Ausgabe: Hallo, Anna!
print(ergebnis) # Ausgabe: None
print(type(ergebnis)) # Ausgabe: <class 'NoneType'>
Das ist ein wichtiger Unterschied:
# Funktion die etwas AUSGIBT (print)
def zeige_summe(a, b):
print(a + b)
# Funktion die etwas ZURUECKGIBT (return)
def berechne_summe(a, b):
return a + b
# Den Unterschied sieht man hier:
x = zeige_summe(3, 5) # gibt 8 aus, aber x ist None
y = berechne_summe(3, 5) # gibt nichts aus, aber y ist 8
print(f"x = {x}") # Ausgabe: x = None
print(f"y = {y}") # Ausgabe: y = 8
Mehrere return-Werte (Tuple Unpacking)
Python erlaubt es, mehrere Werte gleichzeitig zurueckzugeben. Intern wird dabei ein Tuple erstellt:
def min_max(zahlen):
return min(zahlen), max(zahlen)
# Tuple Unpacking - die Werte werden direkt zugewiesen
kleinste, groesste = min_max([4, 2, 9, 1, 7])
print(f"Kleinste: {kleinste}") # Ausgabe: Kleinste: 1
print(f"Groesste: {groesste}") # Ausgabe: Groesste: 9
# Du kannst auch das Tuple direkt verwenden
ergebnis = min_max([4, 2, 9, 1, 7])
print(ergebnis) # Ausgabe: (1, 9)
print(type(ergebnis)) # Ausgabe: <class 'tuple'>
Ein praxisnahes Beispiel:
def analysiere_text(text):
woerter = text.split()
anzahl_woerter = len(woerter)
anzahl_zeichen = len(text)
durchschnitt = anzahl_zeichen / anzahl_woerter if anzahl_woerter > 0 else 0
return anzahl_woerter, anzahl_zeichen, round(durchschnitt, 1)
woerter, zeichen, schnitt = analysiere_text("Python ist eine tolle Sprache")
print(f"Woerter: {woerter}") # Ausgabe: Woerter: 5
print(f"Zeichen: {zeichen}") # Ausgabe: Zeichen: 29
print(f"Durchschnittlich: {schnitt}") # Ausgabe: Durchschnittlich: 5.8
Docstrings
Docstrings sind Dokumentationsstrings, die beschreiben, was eine Funktion tut. Sie stehen direkt nach der def-Zeile in dreifachen Anfuehrungszeichen:
def berechne_bmi(gewicht_kg, groesse_m):
"""Berechnet den Body-Mass-Index (BMI).
Args:
gewicht_kg: Koerpergewicht in Kilogramm.
groesse_m: Koerpergroesse in Metern.
Returns:
Den BMI-Wert als Float, gerundet auf eine Nachkommastelle.
Beispiel:
>>> berechne_bmi(75, 1.80)
23.1
"""
bmi = gewicht_kg / (groesse_m ** 2)
return round(bmi, 1)
Du kannst den Docstring einer Funktion mit help() oder dem __doc__-Attribut abrufen:
help(berechne_bmi)
print(berechne_bmi.__doc__)
Gute Docstrings sind unglaublich wertvoll, besonders in groesseren Projekten. Sie dienen als eingebaute Dokumentation und helfen dir und anderen Entwicklern, den Code zu verstehen.
Scope: Lokale vs. globale Variablen
Der Scope (Gueltigkeitsbereich) bestimmt, wo eine Variable sichtbar und verwendbar ist.
Lokale Variablen
Variablen, die innerhalb einer Funktion definiert werden, sind lokal - sie existieren nur innerhalb dieser Funktion:
def meine_funktion():
lokale_variable = "Ich bin lokal"
print(lokale_variable)
meine_funktion() # Ausgabe: Ich bin lokal
# print(lokale_variable) # FEHLER! NameError: name 'lokale_variable' is not defined
Globale Variablen
Variablen, die ausserhalb aller Funktionen definiert werden, sind global - sie sind ueberall lesbar:
globale_variable = "Ich bin global"
def lese_global():
print(globale_variable) # Lesen funktioniert
lese_global() # Ausgabe: Ich bin global
Aber Vorsicht beim Aendern:
zaehler = 0
def erhoehe():
# Das erstellt eine NEUE lokale Variable!
zaehler = 1
print(f"In der Funktion: {zaehler}")
erhoehe() # Ausgabe: In der Funktion: 1
print(f"Ausserhalb: {zaehler}") # Ausgabe: Ausserhalb: 0
Das global Keyword
Mit global kannst du explizit auf eine globale Variable zugreifen und sie aendern:
zaehler = 0
def erhoehe():
global zaehler
zaehler += 1
print(f"Zaehler ist jetzt: {zaehler}")
erhoehe() # Ausgabe: Zaehler ist jetzt: 1
erhoehe() # Ausgabe: Zaehler ist jetzt: 2
erhoehe() # Ausgabe: Zaehler ist jetzt: 3
print(f"Global: {zaehler}") # Ausgabe: Global: 3
Wichtig: Die Verwendung von
globalist meistens ein Zeichen fuer schlechtes Design. Bevorzuge es, Werte ueber Parameter und return-Werte zu uebergeben. Globale Variablen machen Code schwer nachvollziehbar und fehleranfaellig.
Funktionen als First-Class Objects
In Python sind Funktionen First-Class Objects. Das bedeutet, du kannst sie wie jeden anderen Wert behandeln - sie in Variablen speichern, als Argumente uebergeben oder aus Funktionen zurueckgeben:
Funktionen in Variablen speichern
def quadrat(x):
return x ** 2
# Funktion in einer Variable speichern (ohne Klammern!)
berechnung = quadrat
print(berechnung(5)) # Ausgabe: 25
# Funktionen in Listen speichern
def verdopple(x):
return x * 2
def halbiere(x):
return x / 2
operationen = [quadrat, verdopple, halbiere]
for op in operationen:
print(f"{op.__name__}(10) = {op(10)}")
# Ausgabe:
# quadrat(10) = 100
# verdopple(10) = 20
# halbiere(10) = 5.0
Funktionen als Argumente uebergeben
def wende_an(funktion, wert):
return funktion(wert)
def verdopple(x):
return x * 2
def quadriere(x):
return x ** 2
print(wende_an(verdopple, 5)) # Ausgabe: 10
print(wende_an(quadriere, 5)) # Ausgabe: 25
Funktionen aus Funktionen zurueckgeben
def erstelle_multiplizierer(faktor):
def multiplizierer(x):
return x * faktor
return multiplizierer
verdreifache = erstelle_multiplizierer(3)
verzehnfache = erstelle_multiplizierer(10)
print(verdreifache(5)) # Ausgabe: 15
print(verzehnfache(5)) # Ausgabe: 50
Praxis: BMI-Rechner
Lass uns einen vollstaendigen BMI-Rechner mit Funktionen bauen:
def berechne_bmi(gewicht_kg, groesse_m):
"""Berechnet den BMI aus Gewicht und Groesse."""
return round(gewicht_kg / (groesse_m ** 2), 1)
def bewerte_bmi(bmi):
"""Gibt eine Bewertung des BMI-Werts zurueck."""
if bmi < 18.5:
return "Untergewicht"
elif bmi < 25.0:
return "Normalgewicht"
elif bmi < 30.0:
return "Uebergewicht"
else:
return "Adipositas"
def formatiere_ergebnis(name, bmi, bewertung):
"""Erstellt eine formatierte Ergebnisausgabe."""
linie = "=" * 40
return f"""
{linie}
BMI-Ergebnis fuer {name}
{linie}
BMI-Wert: {bmi}
Bewertung: {bewertung}
{linie}
"""
def bmi_rechner(name, gewicht_kg, groesse_m):
"""Hauptfunktion: Fuehrt die komplette BMI-Berechnung durch."""
bmi = berechne_bmi(gewicht_kg, groesse_m)
bewertung = bewerte_bmi(bmi)
ausgabe = formatiere_ergebnis(name, bmi, bewertung)
print(ausgabe)
return bmi, bewertung
# Anwendung
bmi_rechner("Anna", 65, 1.70)
bmi_rechner("Max", 90, 1.85)
Praxis: Temperatur-Umrechner
def celsius_nach_fahrenheit(celsius):
"""Rechnet Celsius in Fahrenheit um."""
return round(celsius * 9/5 + 32, 1)
def fahrenheit_nach_celsius(fahrenheit):
"""Rechnet Fahrenheit in Celsius um."""
return round((fahrenheit - 32) * 5/9, 1)
def celsius_nach_kelvin(celsius):
"""Rechnet Celsius in Kelvin um."""
return round(celsius + 273.15, 2)
def temperatur_tabelle(start, ende, schritt=10):
"""Gibt eine Umrechnungstabelle aus."""
print(f"{'Celsius':>10} | {'Fahrenheit':>12} | {'Kelvin':>10}")
print("-" * 40)
temp = start
while temp <= ende:
f = celsius_nach_fahrenheit(temp)
k = celsius_nach_kelvin(temp)
print(f"{temp:>10.1f} | {f:>12.1f} | {k:>10.2f}")
temp += schritt
# Einzelne Umrechnungen
print(celsius_nach_fahrenheit(100)) # Ausgabe: 212.0
print(fahrenheit_nach_celsius(72)) # Ausgabe: 22.2
# Tabelle ausgeben
temperatur_tabelle(-20, 40, 10)
Uebungen
Uebung 1: Grundlagen
Schreibe eine Funktion ist_gerade(zahl), die True zurueckgibt, wenn die Zahl gerade ist, und False sonst.
def ist_gerade(zahl):
"""Prueft, ob eine Zahl gerade ist."""
return zahl % 2 == 0
# Test
print(ist_gerade(4)) # True
print(ist_gerade(7)) # False
print(ist_gerade(0)) # True
Uebung 2: Mehrere return-Werte
Schreibe eine Funktion statistik(zahlen), die den Durchschnitt, den Median und die Spannweite einer Zahlenliste zurueckgibt.
def statistik(zahlen):
"""Berechnet Durchschnitt, Median und Spannweite."""
sortiert = sorted(zahlen)
n = len(sortiert)
durchschnitt = sum(sortiert) / n
if n % 2 == 0:
median = (sortiert[n//2 - 1] + sortiert[n//2]) / 2
else:
median = sortiert[n//2]
spannweite = sortiert[-1] - sortiert[0]
return round(durchschnitt, 2), median, spannweite
# Test
d, m, s = statistik([4, 8, 15, 16, 23, 42])
print(f"Durchschnitt: {d}") # 18.0
print(f"Median: {m}") # 15.5
print(f"Spannweite: {s}") # 38
Uebung 3: Passwort-Validator
Schreibe eine Funktion, die prueft, ob ein Passwort den Anforderungen entspricht:
def validiere_passwort(passwort):
"""Prueft, ob ein Passwort sicher genug ist.
Anforderungen:
- Mindestens 8 Zeichen
- Mindestens ein Grossbuchstabe
- Mindestens ein Kleinbuchstabe
- Mindestens eine Zahl
"""
fehler = []
if len(passwort) < 8:
fehler.append("Mindestens 8 Zeichen erforderlich")
if not any(z.isupper() for z in passwort):
fehler.append("Mindestens ein Grossbuchstabe erforderlich")
if not any(z.islower() for z in passwort):
fehler.append("Mindestens ein Kleinbuchstabe erforderlich")
if not any(z.isdigit() for z in passwort):
fehler.append("Mindestens eine Zahl erforderlich")
ist_gueltig = len(fehler) == 0
return ist_gueltig, fehler
# Test
gueltig, fehler = validiere_passwort("Abc12345")
print(f"Gueltig: {gueltig}") # True
gueltig, fehler = validiere_passwort("abc")
print(f"Gueltig: {gueltig}") # False
for f in fehler:
print(f" - {f}")
Uebung 4: Taschenrechner mit Funktionen
def addiere(a, b):
return a + b
def subtrahiere(a, b):
return a - b
def multipliziere(a, b):
return a * b
def dividiere(a, b):
if b == 0:
return "Fehler: Division durch Null!"
return a / b
def taschenrechner(a, operator, b):
"""Einfacher Taschenrechner mit Funktionen."""
operationen = {
"+": addiere,
"-": subtrahiere,
"*": multipliziere,
"/": dividiere,
}
if operator not in operationen:
return f"Unbekannter Operator: {operator}"
return operationen[operator](a, b)
# Test
print(taschenrechner(10, "+", 5)) # 15
print(taschenrechner(10, "-", 3)) # 7
print(taschenrechner(10, "*", 4)) # 40
print(taschenrechner(10, "/", 3)) # 3.333...
print(taschenrechner(10, "/", 0)) # Fehler: Division durch Null!
Pro-Tipp: Funktionen richtig benennen
Gute Funktionsnamen sind wie eine Kurzbeschreibung: Sie sagen sofort, was die Funktion tut. Verwende Verben fuer Aktionen und beschreibende Namen:
# SCHLECHT - unklar, was die Funktion tut
def daten(x):
...
def mach_was(a, b):
...
# GUT - der Name beschreibt die Aktion
def berechne_durchschnitt(zahlen):
...
def validiere_email(adresse):
...
def konvertiere_celsius_nach_fahrenheit(temperatur):
...
Halte dich an die Python-Konvention: Funktionsnamen in kleinbuchstaben_mit_unterstrichen (snake_case). Und denke daran - eine Funktion sollte eine Aufgabe erledigen und diese gut machen. Wenn deine Funktion zu lang wird oder zu viele Dinge gleichzeitig tut, teile sie in kleinere Funktionen auf.